@qwen-code/qwen-code 0.19.9 → 0.19.10
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 +7 -0
- package/bundled/qc-helper/docs/features/channels/dingtalk.md +3 -0
- package/bundled/qc-helper/docs/features/channels/overview.md +11 -3
- package/bundled/qc-helper/docs/features/code-review.md +88 -44
- package/bundled/qc-helper/docs/features/commands.md +6 -6
- package/bundled/qc-helper/docs/features/hooks.md +29 -0
- package/bundled/qc-helper/docs/features/sub-agents.md +21 -0
- package/bundled/qc-helper/docs/qwen-serve.md +46 -20
- package/bundled/qc-helper/docs/reference/keyboard-shortcuts.md +1 -1
- package/bundled/review/DESIGN.md +219 -33
- package/bundled/review/SKILL.md +449 -153
- package/chunks/{MaxSizedBox-6HYJ3ZPJ.js → MaxSizedBox-67ODZ4SZ.js} +31 -31
- package/chunks/{StandaloneSessionPicker-WS4GXYOG.js → StandaloneSessionPicker-SIPBQT5Z.js} +51 -49
- package/chunks/{acpAgent-5FWSOZL5.js → acpAgent-VPZJXLFX.js} +528 -478
- package/chunks/{agent-HOLHB3RT.js → agent-Z7NWL6XL.js} +26 -26
- package/chunks/{agent-headless-SXL6H56A.js → agent-headless-73HZ6ROQ.js} +26 -26
- package/chunks/{anthropicContentGenerator-L73TO3DB.js → anthropicContentGenerator-56U3YCP2.js} +5 -5
- package/chunks/{artifact-tool-U7IRTLIV.js → artifact-tool-BWZZJ42H.js} +2 -2
- package/chunks/{askUserQuestion-2DLUUZZG.js → askUserQuestion-WU3S5A5T.js} +2 -2
- package/chunks/{bridge-BCJQ7BBB.js → bridge-XFKW6S7Q.js} +32 -32
- package/chunks/{ca-UJ6HC4H2.js → ca-C2JTT2N5.js} +4 -1
- package/chunks/channel-worker-group-K7QKH6IG.js +13 -0
- package/chunks/channel-worker-manager-5RWKSGEU.js +418 -0
- package/chunks/channel-worker-supervisor-PCDAZN4D.js +20 -0
- package/chunks/{chunk-LXNEJD34.js → chunk-2FO5GFKZ.js} +1 -1
- package/chunks/{chunk-B5ORX3FG.js → chunk-2UUAIFQO.js} +1 -1
- package/chunks/{chunk-L36P3NBD.js → chunk-2W3OOD4W.js} +2 -0
- package/chunks/{chunk-7R3CZA3Q.js → chunk-2Z5UX4KI.js} +1 -1
- package/chunks/chunk-3MX7D6QN.js +516 -0
- package/chunks/{chunk-E2IY465S.js → chunk-3XJFUTNM.js} +10 -10
- package/chunks/{chunk-JZETEN3Z.js → chunk-422XAKCK.js} +3 -3
- package/chunks/{chunk-N3EMS75V.js → chunk-4FMG7EDJ.js} +1268 -1233
- package/chunks/{chunk-HKMAENAO.js → chunk-4YWLED2A.js} +8 -6
- package/chunks/{chunk-SCGXUJBT.js → chunk-5EBKKSBX.js} +3 -3
- package/chunks/chunk-5HBA2Z7V.js +28 -0
- package/chunks/{chunk-XYQSMABS.js → chunk-5LROA5W4.js} +4 -4
- package/chunks/{chunk-ZJE7NSL3.js → chunk-5M6IDOMF.js} +34 -97
- package/chunks/{chunk-VA4KQY6V.js → chunk-65N2J6V2.js} +3 -3
- package/chunks/{chunk-4C5BQ2D2.js → chunk-6GETGQWP.js} +71 -12
- package/chunks/{chunk-PVZM22CK.js → chunk-6GKMJPOC.js} +5 -5
- package/chunks/{chunk-W2UIXQDL.js → chunk-6OATMEYN.js} +1 -1
- package/chunks/{chunk-GZRTYZ2R.js → chunk-6W6DI34P.js} +154 -1
- package/chunks/{chunk-EMDMPBJ4.js → chunk-7L4XBYVW.js} +3 -3
- package/chunks/{chunk-EAXLGSFP.js → chunk-7MJAZMXK.js} +8 -8
- package/chunks/{chunk-K434OPES.js → chunk-7NAWTFVY.js} +3 -3
- package/chunks/{chunk-J4TSQ5EQ.js → chunk-7NFB7LBQ.js} +8 -1
- package/chunks/{chunk-5SFOMFG4.js → chunk-7R4DPSRA.js} +36 -2
- package/chunks/{chunk-P67PFTUT.js → chunk-AAR5SGMD.js} +4 -4
- package/chunks/{chunk-RDJSGHZE.js → chunk-ALGGS7UH.js} +1 -38
- package/chunks/{chunk-GWHYEOV2.js → chunk-ARKANCNX.js} +2 -1
- package/chunks/{chunk-D2GFWEXB.js → chunk-B5I2IIWY.js} +6 -6
- package/chunks/{chunk-524RQP4Q.js → chunk-B7NUUEXC.js} +10 -4
- package/chunks/{chunk-CUMMSHH6.js → chunk-BBNVFRGD.js} +1 -1
- package/chunks/{chunk-5HOMWMCL.js → chunk-CEW4HDPK.js} +4166 -1338
- package/chunks/chunk-CJFNEBYB.js +91 -0
- package/chunks/{chunk-VWPVHAMO.js → chunk-CUUXANEQ.js} +5 -1
- package/chunks/{chunk-GWLSNBG4.js → chunk-DK33QJ3V.js} +30 -26
- package/chunks/{chunk-HPDUL5MF.js → chunk-DPFBNG72.js} +1 -1
- package/chunks/{chunk-KKNMOEZH.js → chunk-E2UVIFI2.js} +185 -398
- package/chunks/{chunk-MC23XKFE.js → chunk-E67NFMF4.js} +3 -3
- package/chunks/{chunk-OQ4DRIOA.js → chunk-EQY6POVO.js} +2 -2
- package/chunks/{chunk-XUOOWUZS.js → chunk-F7NXQH4Y.js} +1 -1
- package/chunks/{chunk-YLV3XXFB.js → chunk-FBU7WRZI.js} +17 -1
- package/chunks/{chunk-LK7KUE55.js → chunk-FSA7ERJ2.js} +1 -1
- package/chunks/{chunk-PDZ7MBDG.js → chunk-FXMC7SL2.js} +27 -6
- package/chunks/{chunk-SJHDYNHF.js → chunk-GDQQRV43.js} +3 -3
- package/chunks/{chunk-34MW4KTI.js → chunk-GGJII3FM.js} +2 -2
- package/chunks/{chunk-3BTRNWWD.js → chunk-GOXKNSDZ.js} +1 -64
- package/chunks/chunk-GYTKQYDB.js +23 -0
- package/chunks/{chunk-HVY356M2.js → chunk-H3FQOPPS.js} +3 -3
- package/chunks/{chunk-YVEDCAUE.js → chunk-HGT6JR3U.js} +19 -0
- package/chunks/{chunk-WQUQVGTF.js → chunk-HHEFI4RP.js} +183 -96
- package/chunks/chunk-IDS7MSUP.js +74 -0
- package/chunks/{chunk-6PESIEKJ.js → chunk-JSJFKYWT.js} +68 -6
- package/chunks/{chunk-CNEIYWSA.js → chunk-K4PZ5F5T.js} +5 -5
- package/chunks/{chunk-NVYTCB5Z.js → chunk-K7CRWKOE.js} +14534 -13980
- package/chunks/{chunk-ORBGV7NJ.js → chunk-KKRTYONM.js} +6 -4
- package/chunks/{chunk-IAVB3HM3.js → chunk-KSO42X3Z.js} +13 -0
- package/chunks/chunk-L37RC7MQ.js +493 -0
- package/chunks/{chunk-4QLQE5WJ.js → chunk-L5U3ELZX.js} +1 -1
- package/chunks/{chunk-3G7CIHVV.js → chunk-L62SEJWY.js} +4 -4
- package/chunks/{chunk-EGYZ275M.js → chunk-LNUXFLLJ.js} +4 -4
- package/chunks/{chunk-4ZVWQHEQ.js → chunk-LQIDP6K5.js} +1 -1
- package/chunks/{chunk-VTU57BWZ.js → chunk-LQU7EVFA.js} +1 -1
- package/chunks/{chunk-B4G2WOFA.js → chunk-LTNI523B.js} +2 -2
- package/chunks/{chunk-DC5Z3DU6.js → chunk-LXLTBIDP.js} +43 -6
- package/chunks/{chunk-KHUQZZJ6.js → chunk-MO7O5722.js} +370 -36
- package/chunks/chunk-MR3PXB6E.js +48 -0
- package/chunks/{chunk-5VXNZWGF.js → chunk-N6FXRR6P.js} +1 -1
- package/chunks/{chunk-WL4L7EZH.js → chunk-OA4JVLSA.js} +27 -1
- package/chunks/{chunk-TO6QE22P.js → chunk-OATTJGPJ.js} +26 -22
- package/chunks/{chunk-X6TJ3YZV.js → chunk-OFEVHGVU.js} +159 -57
- package/chunks/{chunk-X4NKFGFJ.js → chunk-OJAMDVF5.js} +0 -15
- package/chunks/{chunk-BZIFY5TF.js → chunk-OKAIGAYW.js} +3 -3
- package/chunks/{chunk-3VAGG5T5.js → chunk-P6LART6G.js} +116 -15
- package/chunks/{chunk-3SJSQXNS.js → chunk-PEJWA3QQ.js} +12 -8
- package/chunks/{chunk-BAPGSC7U.js → chunk-Q5GLXH5Q.js} +23 -9
- package/chunks/{chunk-MXL5UP4X.js → chunk-Q6TUALBE.js} +1 -1
- package/chunks/{chunk-QYMQSECS.js → chunk-QAW7PIHT.js} +2 -2
- package/chunks/{chunk-LUODI7WD.js → chunk-RCEEXIOO.js} +6 -4
- package/chunks/{chunk-YAUFFXDS.js → chunk-RDRVMDWV.js} +12 -11
- package/chunks/{chunk-CEA3E3JB.js → chunk-SPJQO2CE.js} +2 -2
- package/chunks/{chunk-U2NNEY4R.js → chunk-SPUYQB4T.js} +1 -1
- package/chunks/{chunk-34Z3U5RQ.js → chunk-SXU3KKNI.js} +514 -114
- package/chunks/{chunk-ECNYL4AA.js → chunk-TISZXPAX.js} +1 -1
- package/chunks/{chunk-JSG7ZSBC.js → chunk-TQBODCFD.js} +1 -1
- package/chunks/{chunk-AKIVHSJR.js → chunk-TTUO4DNG.js} +111 -93
- package/chunks/chunk-TV6K2FB4.js +224 -0
- package/chunks/{chunk-4GORAUCN.js → chunk-TXY2C3D2.js} +1 -1
- package/chunks/{chunk-5XUCZNSY.js → chunk-TYLOFD2U.js} +1 -1
- package/chunks/{chunk-CLFKOZEK.js → chunk-UFOKA4PR.js} +1 -1
- package/chunks/{channel-worker-supervisor-WSOAAYUO.js → chunk-URU5UEK6.js} +67 -35
- package/chunks/{chunk-D5SKC4YG.js → chunk-V7EQTZYR.js} +41 -13
- package/chunks/{chunk-L6P4KPHR.js → chunk-VBRRNQB7.js} +59 -39
- package/chunks/{chunk-BMGVRZN4.js → chunk-W34A5MJH.js} +1 -1
- package/chunks/{chunk-PODM4SZ4.js → chunk-WDW64OW3.js} +5 -5
- package/chunks/{chunk-W3JHSWRP.js → chunk-WDWJ4OQJ.js} +4 -4
- package/chunks/{chunk-Q4YQW46J.js → chunk-WIASPMLX.js} +31 -17
- package/chunks/{chunk-ZLXQN2QS.js → chunk-WIEO4CWB.js} +1 -1
- package/chunks/{chunk-A3XKDTSH.js → chunk-WLXYAKV7.js} +4 -4
- package/chunks/{chunk-Q6I5QHMH.js → chunk-WTSXKLG5.js} +1 -1
- package/chunks/{chunk-J3JA76CF.js → chunk-WX6SD4IQ.js} +1 -1
- package/chunks/{chunk-77XJ3SWN.js → chunk-X362TMXZ.js} +5 -5
- package/chunks/{chunk-CCDMCZPP.js → chunk-XLIRF7IK.js} +1 -1
- package/chunks/{chunk-AURZZYMD.js → chunk-XXJKGHZV.js} +4 -4
- package/chunks/{chunk-TDEXZKMT.js → chunk-Y66VOBRP.js} +2 -2
- package/chunks/{chunk-CC2ITGCF.js → chunk-YHN5SUIJ.js} +49 -6
- package/chunks/{chunk-3AHXV67U.js → chunk-YU56QGXX.js} +1 -1
- package/chunks/{chunk-5U27BZ72.js → chunk-YX4LLZ3D.js} +187 -75
- package/chunks/{chunk-ATAKVRIF.js → chunk-YYPXHMWO.js} +7 -7
- package/chunks/{chunk-XLA62MYB.js → chunk-ZKMGAFYV.js} +2 -2
- package/chunks/{chunk-UOZWKTQG.js → chunk-ZPAHLFZU.js} +2 -2
- package/chunks/{chunk-7PU4FYLG.js → chunk-ZQTZXVHP.js} +4 -4
- package/chunks/chunk-ZRKBI3DP.js +34 -0
- package/chunks/{computer-use-HM37RX6A.js → computer-use-IYTX45WA.js} +26 -26
- package/chunks/{config-utils-NV2SVGPB.js → config-utils-CFT33LTP.js} +3 -2
- package/chunks/{contextCommand-OF5SFGH2.js → contextCommand-272V77WU.js} +28 -28
- package/chunks/{create-sub-session-KPRT7ECJ.js → create-sub-session-CBJMQLYP.js} +26 -26
- package/chunks/{create-sub-session-INX7TXJI.js → create-sub-session-WNX2OQVX.js} +2 -2
- package/chunks/{cron-create-AMBKGZX6.js → cron-create-36TIFKRT.js} +4 -4
- package/chunks/{cron-delete-LRU4OJYG.js → cron-delete-OQD3WULU.js} +4 -4
- package/chunks/{cron-list-WVP2JXER.js → cron-list-4533T2FH.js} +4 -4
- package/chunks/{daemon-ARHTSTXP.js → daemon-RNGFPMAB.js} +575 -58
- package/chunks/{daemon-status-provider-B2UTZUJ2.js → daemon-status-provider-L4STG5VO.js} +36 -36
- package/chunks/{de-EBJN3OVN.js → de-2VCDRDGU.js} +4 -1
- package/chunks/{dist-VHV4EVHG.js → dist-3V3ZV6ML.js} +1 -1
- package/chunks/{dist-XKU3ABM5.js → dist-ERCPDVA6.js} +1 -1
- package/chunks/{dist-PNVLTKTL.js → dist-HNN7DR2L.js} +158 -4
- package/chunks/{dist-WKPOYU7O.js → dist-JZE7F6YR.js} +1 -1
- package/chunks/{dist-QYCAEZIT.js → dist-MOEC47TR.js} +5 -1
- package/chunks/{dist-R7LN5AZE.js → dist-PHEPJLXD.js} +2 -2
- package/chunks/{earlyInputCapture-3VTHRC4C.js → earlyInputCapture-EN4BRREQ.js} +27 -27
- package/chunks/{edit-VNI4NJ73.js → edit-OMAF2QDR.js} +27 -27
- package/chunks/{en-5A6LA7RK.js → en-NJCA3TAA.js} +5 -1
- package/chunks/{enter-worktree-IYYBKPZT.js → enter-worktree-BBZX52HG.js} +26 -26
- package/chunks/{enterPlanMode-GMC5FD5A.js → enterPlanMode-5NNFMBUY.js} +42 -27
- package/chunks/{environment-5HSSRMJ7.js → environment-7TEWMJYN.js} +30 -29
- package/chunks/{errors-HMFCJJ7P.js → errors-I4VKVX3F.js} +28 -28
- package/chunks/{exit-worktree-6BHCMP5G.js → exit-worktree-FUWRJI33.js} +26 -26
- package/chunks/{exitPlanMode-CJW7G74W.js → exitPlanMode-IHCJ5EEI.js} +26 -26
- package/chunks/{fast-path-FRDMDVHG.js → fast-path-ZA57TOH4.js} +3 -3
- package/chunks/{fast-path-settings-5QZE64HR.js → fast-path-settings-DAOVFADC.js} +6 -4
- package/chunks/{fr-YXRABLYZ.js → fr-5F3E7WKD.js} +4 -1
- package/chunks/{gemini-QYSEGHAX.js → gemini-UOAKVXBG.js} +139 -76
- package/chunks/{geminiContentGenerator-J7YNZDYP.js → geminiContentGenerator-G6UCE6MW.js} +4 -4
- package/chunks/{glob-BRCSGFOT.js → glob-4GJQ2UFF.js} +28 -27
- package/chunks/{grep-EE2DUOSY.js → grep-5QSYXF2E.js} +26 -26
- package/chunks/{handleAutoUpdate-5NWTLR67.js → handleAutoUpdate-ULHNWL6R.js} +30 -30
- package/chunks/{i18n-BASPENNQ.js → i18n-CYDUTF6F.js} +27 -27
- package/chunks/initializer-NRFKUGIO.js +73 -0
- package/chunks/{installationInfo-W6V4DT7W.js → installationInfo-WELKRHHE.js} +27 -27
- package/chunks/{ja-7VQOANVG.js → ja-66J6B53L.js} +5 -2
- package/chunks/{keychain-token-storage-VKUBNCP4.js → keychain-token-storage-AU22CQI6.js} +2 -2
- package/chunks/list-JVDXEG2E.js +76 -0
- package/chunks/loadedSettingsAdapter-WAM4VUTG.js +70 -0
- package/chunks/{loop-wakeup-WX7BLWWP.js → loop-wakeup-MVUKDVCP.js} +5 -5
- package/chunks/{ls-ZB2BDP6T.js → ls-RXNIAQDE.js} +4 -4
- package/chunks/{lsp-V5DN4YUJ.js → lsp-HB5LM5IL.js} +2 -2
- package/chunks/mcp-YHOZN3ZM.js +70 -0
- package/chunks/{monitor-X5Z3H4FY.js → monitor-R7XZPJHQ.js} +26 -26
- package/chunks/nonInteractiveCli-NSOB6D74.js +129 -0
- package/chunks/{notebook-edit-TRM2QIJK.js → notebook-edit-6RNKE2L2.js} +27 -27
- package/chunks/{openaiContentGenerator-AAYONPMF.js → openaiContentGenerator-XNS5S64I.js} +12 -12
- package/chunks/{pidfile-D4I4FTVA.js → pidfile-XE4RRR2P.js} +27 -27
- package/chunks/{pt-2C6YCSHL.js → pt-TFZO5Y6T.js} +4 -1
- package/chunks/{qwenContentGenerator-K3HZ2H76.js → qwenContentGenerator-APDPJ3VN.js} +28 -28
- package/chunks/{qwenOAuth2-PJQ27GSO.js → qwenOAuth2-LEYOU7RU.js} +5 -5
- package/chunks/{read-file-7SZSIZOL.js → read-file-XSUWXSR7.js} +8 -8
- package/chunks/{read-mcp-resource-SM5DA4RG.js → read-mcp-resource-6LRTZKXI.js} +2 -2
- package/chunks/{record-artifact-4XKZX3UW.js → record-artifact-PMDTY4OS.js} +2 -2
- package/chunks/{ripGrep-YNPFVCZP.js → ripGrep-APB3CDMU.js} +26 -26
- package/chunks/{ru-6BBHVZZV.js → ru-4L4LFHIT.js} +4 -1
- package/chunks/{run-qwen-serve-DMWV5N6L.js → run-qwen-serve-NWTGPERT.js} +1232 -371
- package/chunks/{runtime-57WWRVHN.js → runtime-EIO3NQKR.js} +42 -37
- package/chunks/{scheduler-YBLGWSIL.js → scheduler-JJDZBDRN.js} +26 -26
- package/chunks/{send-message-F36YD6KQ.js → send-message-SR4WSXP2.js} +3 -3
- package/chunks/{serve-R63NK3CV.js → serve-WTIPB3EI.js} +36 -34
- package/chunks/{server-Z22GCAXP.js → server-NJPHQHLH.js} +5238 -1328
- package/chunks/{session-HKAAI7BN.js → session-O4AO7FTS.js} +298 -98
- package/chunks/{settings-3EYN66GK.js → settings-HQNDK7TG.js} +34 -32
- package/chunks/{shell-6YXINTWJ.js → shell-UIXM6PWG.js} +26 -26
- package/chunks/{skill-OO57P4X6.js → skill-3XMB4ULV.js} +10 -10
- package/chunks/{spawnChannel-JD7G4VU6.js → spawnChannel-3R632QRM.js} +28 -28
- package/chunks/{src-G5UPLZSZ.js → src-USZKPUOC.js} +85 -27
- package/chunks/{standalone-update-OB7F4JPZ.js → standalone-update-L5XW3D7K.js} +28 -28
- package/chunks/{startInteractiveUI-73EGLIIH.js → startInteractiveUI-CPZOL2WB.js} +730 -397
- package/chunks/{syntheticOutput-34H7LGA7.js → syntheticOutput-YKFNUQZD.js} +3 -3
- package/chunks/{task-create-FRGOEIKY.js → task-create-NUFOHU53.js} +8 -7
- package/chunks/{task-list-OW766BXZ.js → task-list-Z2IKQY3S.js} +6 -5
- package/chunks/{task-stop-SIR5SNBN.js → task-stop-KQFIVQTJ.js} +2 -2
- package/chunks/{task-update-YRA532MT.js → task-update-HKADXSTD.js} +8 -7
- package/chunks/{team-create-PECAAPXK.js → team-create-XXPRF3IQ.js} +26 -26
- package/chunks/{team-delete-6OSECUZC.js → team-delete-SDNTGZLG.js} +6 -5
- package/chunks/{team-plan-approval-L6F434RY.js → team-plan-approval-EOTTKHDW.js} +26 -26
- package/chunks/{theme-manager-ZG4RY6GU.js → theme-manager-P6UITO2L.js} +27 -27
- package/chunks/{todoWrite-YDMFEV4G.js → todoWrite-YNXB27GB.js} +4 -4
- package/chunks/{tool-search-THVIWAPB.js → tool-search-DDNGK2LR.js} +9 -9
- package/chunks/{total-session-admission-JOKNRIIA.js → total-session-admission-PL5N7DNY.js} +33 -33
- package/chunks/tree-sitter-YJVE2ZUK.js +2980 -0
- package/chunks/{trustedFolders-EOGT3UVS.js → trustedFolders-C5LMF3UR.js} +29 -28
- package/chunks/types-ML3TRJQ5.js +16 -0
- package/chunks/{updateCheck-2KYEYVSB.js → updateCheck-QTVVISH7.js} +29 -29
- package/chunks/{validateNonInterActiveAuth-EN6ZQSR2.js → validateNonInterActiveAuth-RY4RKBQG.js} +75 -71
- package/chunks/{version-3UEA6ZIR.js → version-U45RYOSD.js} +1 -1
- package/chunks/{web-fetch-PAAEQKBW.js → web-fetch-ZSPR3PRR.js} +5 -5
- package/chunks/{workflow-QCCCMYP3.js → workflow-TCIAQYOA.js} +27 -27
- package/chunks/workspace-providers-status-I3G2HYLY.js +73 -0
- package/chunks/workspace-registration-store-IH5GLZ6Y.js +27 -0
- package/chunks/{workspace-registry-24QFLQYH.js → workspace-registry-QEKBELIX.js} +33 -33
- package/chunks/workspace-service-ORKHGLP3.js +86 -0
- package/chunks/workspace-skills-status-D7QCNDYY.js +72 -0
- package/chunks/{write-file-I3MUDRIE.js → write-file-JGRQR5VM.js} +27 -27
- package/chunks/{zh-RQE7I22T.js → zh-FSAH32JB.js} +6 -2
- package/chunks/{zh-TW-TBPQGHKH.js → zh-TW-D2YIE2LO.js} +6 -2
- package/cli.js +11 -11
- package/locales/ca.js +6 -0
- package/locales/de.js +6 -0
- package/locales/en.js +8 -0
- package/locales/fr.js +6 -0
- package/locales/ja.js +7 -1
- package/locales/pt.js +6 -0
- package/locales/ru.js +6 -0
- package/locales/zh-TW.js +9 -1
- package/locales/zh.js +9 -1
- package/package.json +3 -3
- package/web-shell/assets/{arc-C15hqnJe.js → arc-CUeDlxvE.js} +1 -1
- package/web-shell/assets/{architectureDiagram-3BPJPVTR-B-At37J_.js → architectureDiagram-3BPJPVTR-PiUszkQA.js} +1 -1
- package/web-shell/assets/{blockDiagram-GPEHLZMM-B51wjcU7.js → blockDiagram-GPEHLZMM-s2wYSO7e.js} +1 -1
- package/web-shell/assets/{c4Diagram-AAUBKEIU-xBK7BAwN.js → c4Diagram-AAUBKEIU-DyLxZoz9.js} +1 -1
- package/web-shell/assets/channel-DkuJJ0qd.js +1 -0
- package/web-shell/assets/{chunk-2J33WTMH-xKmLg7Yr.js → chunk-2J33WTMH-Dsdai7Tk.js} +1 -1
- package/web-shell/assets/{chunk-4BX2VUAB-BfkdKZCM.js → chunk-4BX2VUAB-DEosOjV7.js} +1 -1
- package/web-shell/assets/{chunk-55IACEB6-DT713sZf.js → chunk-55IACEB6-sNsRLTXf.js} +1 -1
- package/web-shell/assets/{chunk-727SXJPM-CYEeAamv.js → chunk-727SXJPM-DkRNZzmh.js} +1 -1
- package/web-shell/assets/{chunk-AQP2D5EJ-DBN-5CFd.js → chunk-AQP2D5EJ-BrsRNpzd.js} +1 -1
- package/web-shell/assets/{chunk-FMBD7UC4-CGZKk4PH.js → chunk-FMBD7UC4-CI039lpl.js} +1 -1
- package/web-shell/assets/{chunk-ND2GUHAM-qQbC2O-y.js → chunk-ND2GUHAM-M-pkeIfu.js} +1 -1
- package/web-shell/assets/{chunk-QZHKN3VN-B3zeXwsX.js → chunk-QZHKN3VN-C4ckGNbH.js} +1 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-CwqHc0TB.js +1 -0
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-CwqHc0TB.js +1 -0
- package/web-shell/assets/{cose-bilkent-S5V4N54A-BKsl1Wvy.js → cose-bilkent-S5V4N54A-BciKUAFq.js} +1 -1
- package/web-shell/assets/{dagre-BM42HDAG-CuuuLiBK.js → dagre-BM42HDAG-C1nTSgU6.js} +1 -1
- package/web-shell/assets/{diagram-2AECGRRQ-CG4_eKiV.js → diagram-2AECGRRQ-BDPNWr1m.js} +1 -1
- package/web-shell/assets/{diagram-5GNKFQAL-DSFTmZB1.js → diagram-5GNKFQAL-CNFhTszL.js} +1 -1
- package/web-shell/assets/{diagram-KO2AKTUF-BxwlEHn8.js → diagram-KO2AKTUF-CjPa4p5a.js} +1 -1
- package/web-shell/assets/{diagram-LMA3HP47-BUAg-jMG.js → diagram-LMA3HP47-ZzPykSyG.js} +1 -1
- package/web-shell/assets/{diagram-OG6HWLK6-BFM2jlO5.js → diagram-OG6HWLK6-0UVtZ9A4.js} +1 -1
- package/web-shell/assets/{erDiagram-TEJ5UH35-CerbFPa2.js → erDiagram-TEJ5UH35-CajDZCat.js} +1 -1
- package/web-shell/assets/{flowDiagram-I6XJVG4X-BNeZz5Zz.js → flowDiagram-I6XJVG4X-BRuFBIvL.js} +1 -1
- package/web-shell/assets/{ganttDiagram-6RSMTGT7-CTOogLaM.js → ganttDiagram-6RSMTGT7-BevGmJqG.js} +3 -3
- package/web-shell/assets/{gitGraphDiagram-PVQCEYII-yxSFkXPj.js → gitGraphDiagram-PVQCEYII-DvPMpBMb.js} +1 -1
- package/web-shell/assets/index-Cnvv4VcI.css +5 -0
- package/web-shell/assets/index-D1Uyklxa.js +1088 -0
- package/web-shell/assets/index-DzHwQkQq.js +3 -0
- package/web-shell/assets/{infoDiagram-5YYISTIA-DYdAUevm.js → infoDiagram-5YYISTIA-Oixn7tA9.js} +1 -1
- package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-CNuijZ90.js → ishikawaDiagram-YF4QCWOH-BgKpeg-j.js} +1 -1
- package/web-shell/assets/{journeyDiagram-JHISSGLW-BTyiuonf.js → journeyDiagram-JHISSGLW-74mwxIaA.js} +1 -1
- package/web-shell/assets/{kanban-definition-UN3LZRKU-DPJo0Uow.js → kanban-definition-UN3LZRKU-D4D6cEqA.js} +1 -1
- package/web-shell/assets/{linear-C8wKCbIC.js → linear-atZRE_L2.js} +1 -1
- package/web-shell/assets/{mermaid.core-BV5o7nW5.js → mermaid.core-KKudX-JC.js} +5 -5
- package/web-shell/assets/{mindmap-definition-RKZ34NQL-BtLcBmSt.js → mindmap-definition-RKZ34NQL-CMCej9yG.js} +1 -1
- package/web-shell/assets/{pieDiagram-4H26LBE5-C22J7A9Q.js → pieDiagram-4H26LBE5-nhx40X7q.js} +1 -1
- package/web-shell/assets/{quadrantDiagram-W4KKPZXB-DSL10wiL.js → quadrantDiagram-W4KKPZXB-CUmVcN3M.js} +1 -1
- package/web-shell/assets/{requirementDiagram-4Y6WPE33-feqh0UpX.js → requirementDiagram-4Y6WPE33-C_vyEwyy.js} +1 -1
- package/web-shell/assets/{sankeyDiagram-5OEKKPKP-Z4OVaWaZ.js → sankeyDiagram-5OEKKPKP-DU6G4VWR.js} +1 -1
- package/web-shell/assets/{sequenceDiagram-3UESZ5HK-DIluIcb1.js → sequenceDiagram-3UESZ5HK-DdeRR_KJ.js} +1 -1
- package/web-shell/assets/{stateDiagram-AJRCARHV-hlhnuoYH.js → stateDiagram-AJRCARHV-C6iCI8ps.js} +1 -1
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-C0_6nR6C.js +1 -0
- package/web-shell/assets/{timeline-definition-PNZ67QCA-Dqf_CqgL.js → timeline-definition-PNZ67QCA-B_Ea8Cb7.js} +1 -1
- package/web-shell/assets/{vennDiagram-CIIHVFJN-DD2QhaTX.js → vennDiagram-CIIHVFJN-BPUVZEJA.js} +1 -1
- package/web-shell/assets/{wardley-L42UT6IY-B2uI85U_.js → wardley-L42UT6IY-BWEj0lKY.js} +1 -1
- package/web-shell/assets/{wardleyDiagram-YWT4CUSO-U1aJX71g.js → wardleyDiagram-YWT4CUSO-BvDsdIQw.js} +1 -1
- package/web-shell/assets/{xychartDiagram-2RQKCTM6-C0ODHUee.js → xychartDiagram-2RQKCTM6-crz0QhF_.js} +1 -1
- package/web-shell/index.html +2 -2
- package/chunks/chunk-CU3L64TP.js +0 -93
- package/chunks/initializer-UTQ7FB7G.js +0 -71
- package/chunks/list-DEICDL65.js +0 -74
- package/chunks/loadedSettingsAdapter-NOWEGDYJ.js +0 -68
- package/chunks/mcp-L5JXEEIA.js +0 -68
- package/chunks/nonInteractiveCli-LS2K4X6A.js +0 -124
- package/chunks/types-JNKGKUJT.js +0 -12
- package/chunks/workspace-providers-status-4KMGETOJ.js +0 -71
- package/chunks/workspace-service-RVLBMSMZ.js +0 -80
- package/chunks/workspace-skills-status-DS4ZVFTO.js +0 -70
- package/web-shell/assets/channel-CLiQD50f.js +0 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-D3sYqow5.js +0 -1
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-D3sYqow5.js +0 -1
- package/web-shell/assets/index-D5IWFVk1.css +0 -5
- package/web-shell/assets/index-KFJRDhX7.js +0 -783
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-BhQMwgpl.js +0 -1
|
@@ -12,32 +12,6 @@ import {
|
|
|
12
12
|
__name
|
|
13
13
|
} from "./chunk-J2S4EL5Y.js";
|
|
14
14
|
|
|
15
|
-
// packages/channels/base/dist/paths.js
|
|
16
|
-
init_esbuild_shims();
|
|
17
|
-
import * as path from "node:path";
|
|
18
|
-
import * as os from "node:os";
|
|
19
|
-
function resolvePath(dir) {
|
|
20
|
-
let resolved = dir;
|
|
21
|
-
if (resolved === "~" || resolved.startsWith("~/") || resolved.startsWith("~\\")) {
|
|
22
|
-
const relativeSegments = resolved === "~" ? [] : resolved.slice(2).split(/[/\\]+/).filter(Boolean);
|
|
23
|
-
resolved = path.join(os.homedir(), ...relativeSegments);
|
|
24
|
-
}
|
|
25
|
-
if (!path.isAbsolute(resolved)) {
|
|
26
|
-
resolved = path.resolve(resolved);
|
|
27
|
-
}
|
|
28
|
-
return resolved;
|
|
29
|
-
}
|
|
30
|
-
__name(resolvePath, "resolvePath");
|
|
31
|
-
function getGlobalQwenDir() {
|
|
32
|
-
const envDir = process.env["QWEN_HOME"];
|
|
33
|
-
if (envDir) {
|
|
34
|
-
return resolvePath(envDir);
|
|
35
|
-
}
|
|
36
|
-
const homeDir = os.homedir();
|
|
37
|
-
return homeDir ? path.join(homeDir, ".qwen") : path.join(os.tmpdir(), ".qwen");
|
|
38
|
-
}
|
|
39
|
-
__name(getGlobalQwenDir, "getGlobalQwenDir");
|
|
40
|
-
|
|
41
15
|
// packages/channels/base/dist/sanitize.js
|
|
42
16
|
init_esbuild_shims();
|
|
43
17
|
var PROMPT_UNSAFE_INVISIBLES = new RegExp("[\\u0080-\\u009f\\p{Cf}\\u2028\\u2029]|\\p{Variation_Selector}", "gu");
|
|
@@ -74,6 +48,32 @@ __name(sanitizeLogText, "sanitizeLogText");
|
|
|
74
48
|
// packages/channels/base/dist/index.js
|
|
75
49
|
init_esbuild_shims();
|
|
76
50
|
|
|
51
|
+
// packages/channels/base/dist/paths.js
|
|
52
|
+
init_esbuild_shims();
|
|
53
|
+
import * as path from "node:path";
|
|
54
|
+
import * as os from "node:os";
|
|
55
|
+
function resolvePath(dir) {
|
|
56
|
+
let resolved = dir;
|
|
57
|
+
if (resolved === "~" || resolved.startsWith("~/") || resolved.startsWith("~\\")) {
|
|
58
|
+
const relativeSegments = resolved === "~" ? [] : resolved.slice(2).split(/[/\\]+/).filter(Boolean);
|
|
59
|
+
resolved = path.join(os.homedir(), ...relativeSegments);
|
|
60
|
+
}
|
|
61
|
+
if (!path.isAbsolute(resolved)) {
|
|
62
|
+
resolved = path.resolve(resolved);
|
|
63
|
+
}
|
|
64
|
+
return resolved;
|
|
65
|
+
}
|
|
66
|
+
__name(resolvePath, "resolvePath");
|
|
67
|
+
function getGlobalQwenDir() {
|
|
68
|
+
const envDir = process.env["QWEN_HOME"];
|
|
69
|
+
if (envDir) {
|
|
70
|
+
return resolvePath(envDir);
|
|
71
|
+
}
|
|
72
|
+
const homeDir = os.homedir();
|
|
73
|
+
return homeDir ? path.join(homeDir, ".qwen") : path.join(os.tmpdir(), ".qwen");
|
|
74
|
+
}
|
|
75
|
+
__name(getGlobalQwenDir, "getGlobalQwenDir");
|
|
76
|
+
|
|
77
77
|
// packages/channels/base/dist/AcpBridge.js
|
|
78
78
|
init_esbuild_shims();
|
|
79
79
|
import { spawn } from "node:child_process";
|
|
@@ -361,15 +361,23 @@ var AcpBridge = class extends EventEmitter {
|
|
|
361
361
|
async prompt(sessionId, text, options) {
|
|
362
362
|
const conn = this.ensureConnection();
|
|
363
363
|
const chunks = [];
|
|
364
|
+
let slashCommandOutput = "";
|
|
364
365
|
const onChunk = /* @__PURE__ */ __name((sid, chunk) => {
|
|
365
366
|
if (sid === sessionId)
|
|
366
367
|
chunks.push(chunk);
|
|
367
368
|
}, "onChunk");
|
|
368
|
-
const
|
|
369
|
+
const onSlashCommandOutput = /* @__PURE__ */ __name((sid, chunk) => {
|
|
369
370
|
if (sid === sessionId)
|
|
371
|
+
slashCommandOutput = chunk;
|
|
372
|
+
}, "onSlashCommandOutput");
|
|
373
|
+
const clearChunks = /* @__PURE__ */ __name((sid) => {
|
|
374
|
+
if (sid === sessionId) {
|
|
370
375
|
chunks.length = 0;
|
|
376
|
+
slashCommandOutput = "";
|
|
377
|
+
}
|
|
371
378
|
}, "clearChunks");
|
|
372
379
|
this.on("textChunk", onChunk);
|
|
380
|
+
this.on("slashCommandOutput", onSlashCommandOutput);
|
|
373
381
|
this.on("responseBoundary", clearChunks);
|
|
374
382
|
const prompt = [];
|
|
375
383
|
if (options?.imageBase64 && options.imageMimeType) {
|
|
@@ -387,9 +395,10 @@ var AcpBridge = class extends EventEmitter {
|
|
|
387
395
|
});
|
|
388
396
|
} finally {
|
|
389
397
|
this.off("textChunk", onChunk);
|
|
398
|
+
this.off("slashCommandOutput", onSlashCommandOutput);
|
|
390
399
|
this.off("responseBoundary", clearChunks);
|
|
391
400
|
}
|
|
392
|
-
return chunks.join("");
|
|
401
|
+
return chunks.join("") || slashCommandOutput;
|
|
393
402
|
}
|
|
394
403
|
async cancelSession(sessionId) {
|
|
395
404
|
const conn = this.ensureConnection();
|
|
@@ -432,9 +441,13 @@ var AcpBridge = class extends EventEmitter {
|
|
|
432
441
|
const type = update["sessionUpdate"];
|
|
433
442
|
switch (type) {
|
|
434
443
|
case "agent_message_chunk": {
|
|
444
|
+
const meta = update["_meta"];
|
|
445
|
+
if (typeof meta?.["parentToolCallId"] === "string") {
|
|
446
|
+
break;
|
|
447
|
+
}
|
|
435
448
|
const content = update["content"];
|
|
436
449
|
if (content?.type === "text" && content.text) {
|
|
437
|
-
this.emit("textChunk", sessionId, content.text);
|
|
450
|
+
this.emit(meta?.["source"] === "slash_command" ? "slashCommandOutput" : "textChunk", sessionId, content.text);
|
|
438
451
|
}
|
|
439
452
|
break;
|
|
440
453
|
}
|
|
@@ -707,6 +720,7 @@ var DaemonChannelBridge = class extends EventEmitter2 {
|
|
|
707
720
|
}
|
|
708
721
|
options;
|
|
709
722
|
sessions = /* @__PURE__ */ new Map();
|
|
723
|
+
sessionBindingTokens = /* @__PURE__ */ new Map();
|
|
710
724
|
eventControllers = /* @__PURE__ */ new Map();
|
|
711
725
|
requestToSession = /* @__PURE__ */ new Map();
|
|
712
726
|
respondedRequestToSession = /* @__PURE__ */ new Map();
|
|
@@ -715,6 +729,7 @@ var DaemonChannelBridge = class extends EventEmitter2 {
|
|
|
715
729
|
availableCommandsBySession = /* @__PURE__ */ new Map();
|
|
716
730
|
turnBarriers = /* @__PURE__ */ new Map();
|
|
717
731
|
connected = false;
|
|
732
|
+
lifecycleGeneration = 0;
|
|
718
733
|
latestAvailableCommandsSessionId;
|
|
719
734
|
lastError;
|
|
720
735
|
constructor(options) {
|
|
@@ -750,17 +765,22 @@ var DaemonChannelBridge = class extends EventEmitter2 {
|
|
|
750
765
|
async start() {
|
|
751
766
|
this.connected = true;
|
|
752
767
|
}
|
|
753
|
-
async newSession(cwd, options) {
|
|
768
|
+
async newSession(cwd, options, bindingToken) {
|
|
769
|
+
const lifecycleGeneration = this.lifecycleGeneration;
|
|
754
770
|
const session = await this.options.sessionFactory({
|
|
755
771
|
workspaceCwd: cwd || this.options.cwd,
|
|
756
772
|
modelServiceId: this.options.modelServiceId,
|
|
757
773
|
sessionScope: this.options.sessionScope ?? "thread",
|
|
758
774
|
...options?.approvalMode ? { approvalMode: options.approvalMode } : {}
|
|
759
775
|
});
|
|
760
|
-
this.
|
|
776
|
+
if (lifecycleGeneration !== this.lifecycleGeneration) {
|
|
777
|
+
await this.rejectStaleSession(session);
|
|
778
|
+
}
|
|
779
|
+
this.attachSession(session, bindingToken);
|
|
761
780
|
return session.sessionId;
|
|
762
781
|
}
|
|
763
|
-
async loadSession(sessionId, cwd, options) {
|
|
782
|
+
async loadSession(sessionId, cwd, options, bindingToken) {
|
|
783
|
+
const lifecycleGeneration = this.lifecycleGeneration;
|
|
764
784
|
const session = await this.options.sessionFactory({
|
|
765
785
|
workspaceCwd: cwd || this.options.cwd,
|
|
766
786
|
modelServiceId: this.options.modelServiceId,
|
|
@@ -768,10 +788,16 @@ var DaemonChannelBridge = class extends EventEmitter2 {
|
|
|
768
788
|
sessionScope: this.options.sessionScope ?? "thread",
|
|
769
789
|
...options?.approvalMode ? { approvalMode: options.approvalMode } : {}
|
|
770
790
|
});
|
|
791
|
+
if (lifecycleGeneration !== this.lifecycleGeneration) {
|
|
792
|
+
await this.rejectStaleSession(session);
|
|
793
|
+
}
|
|
771
794
|
if (session.sessionId !== sessionId) {
|
|
795
|
+
void this.releaseSessionClient(session).catch((error) => {
|
|
796
|
+
this.lastError = error;
|
|
797
|
+
});
|
|
772
798
|
throw new Error(`Daemon returned session ${session.sessionId} while loading ${sessionId}`);
|
|
773
799
|
}
|
|
774
|
-
this.attachSession(session);
|
|
800
|
+
this.attachSession(session, bindingToken);
|
|
775
801
|
return session.sessionId;
|
|
776
802
|
}
|
|
777
803
|
async prompt(sessionId, text, options) {
|
|
@@ -788,14 +814,21 @@ var DaemonChannelBridge = class extends EventEmitter2 {
|
|
|
788
814
|
}
|
|
789
815
|
controllers.add(controller);
|
|
790
816
|
const chunks = [];
|
|
817
|
+
let slashCommandOutput = "";
|
|
791
818
|
const onChunk = /* @__PURE__ */ __name((sid, chunk) => {
|
|
792
819
|
if (sid === sessionId) {
|
|
793
820
|
chunks.push(chunk);
|
|
794
821
|
}
|
|
795
822
|
}, "onChunk");
|
|
823
|
+
const onSlashCommandOutput = /* @__PURE__ */ __name((sid, chunk) => {
|
|
824
|
+
if (sid === sessionId) {
|
|
825
|
+
slashCommandOutput = chunk;
|
|
826
|
+
}
|
|
827
|
+
}, "onSlashCommandOutput");
|
|
796
828
|
const clearChunks = /* @__PURE__ */ __name((sid) => {
|
|
797
829
|
if (sid === sessionId) {
|
|
798
830
|
chunks.length = 0;
|
|
831
|
+
slashCommandOutput = "";
|
|
799
832
|
}
|
|
800
833
|
}, "clearChunks");
|
|
801
834
|
const onSessionDied = /* @__PURE__ */ __name((info) => {
|
|
@@ -804,6 +837,7 @@ var DaemonChannelBridge = class extends EventEmitter2 {
|
|
|
804
837
|
}
|
|
805
838
|
}, "onSessionDied");
|
|
806
839
|
this.on("textChunk", onChunk);
|
|
840
|
+
this.on("slashCommandOutput", onSlashCommandOutput);
|
|
807
841
|
this.on("responseBoundary", clearChunks);
|
|
808
842
|
this.on("sessionDied", onSessionDied);
|
|
809
843
|
const turnBarrier = this.createTurnBarrier(sessionId);
|
|
@@ -822,7 +856,7 @@ var DaemonChannelBridge = class extends EventEmitter2 {
|
|
|
822
856
|
turnBarrier,
|
|
823
857
|
new Promise((resolve2) => setTimeout(resolve2, 0))
|
|
824
858
|
]);
|
|
825
|
-
const textResult = chunks.join("");
|
|
859
|
+
const textResult = chunks.join("") || slashCommandOutput;
|
|
826
860
|
this.emit("promptComplete", {
|
|
827
861
|
sessionId,
|
|
828
862
|
text: textResult,
|
|
@@ -832,6 +866,7 @@ var DaemonChannelBridge = class extends EventEmitter2 {
|
|
|
832
866
|
} finally {
|
|
833
867
|
this.clearTurnBarrier(sessionId);
|
|
834
868
|
this.off("textChunk", onChunk);
|
|
869
|
+
this.off("slashCommandOutput", onSlashCommandOutput);
|
|
835
870
|
this.off("responseBoundary", clearChunks);
|
|
836
871
|
this.off("sessionDied", onSessionDied);
|
|
837
872
|
this.activePrompts.delete(sessionId);
|
|
@@ -855,6 +890,25 @@ var DaemonChannelBridge = class extends EventEmitter2 {
|
|
|
855
890
|
this.activePrompts.delete(sessionId);
|
|
856
891
|
await session.cancel();
|
|
857
892
|
}
|
|
893
|
+
async discardSession(sessionId, expectedBindingToken) {
|
|
894
|
+
if (expectedBindingToken !== void 0 && this.sessionBindingTokens.get(sessionId) !== expectedBindingToken) {
|
|
895
|
+
return;
|
|
896
|
+
}
|
|
897
|
+
const session = this.removeSessionBinding(sessionId);
|
|
898
|
+
if (!session)
|
|
899
|
+
return;
|
|
900
|
+
await this.releaseSessionClient(session);
|
|
901
|
+
}
|
|
902
|
+
async releaseSessionClient(session) {
|
|
903
|
+
if (session.detach) {
|
|
904
|
+
try {
|
|
905
|
+
await session.detach();
|
|
906
|
+
return;
|
|
907
|
+
} catch {
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
await session.cancel();
|
|
911
|
+
}
|
|
858
912
|
async setSessionModel(sessionId, modelId) {
|
|
859
913
|
return await this.ensureSession(sessionId).setModel(modelId);
|
|
860
914
|
}
|
|
@@ -885,6 +939,7 @@ var DaemonChannelBridge = class extends EventEmitter2 {
|
|
|
885
939
|
}
|
|
886
940
|
}
|
|
887
941
|
stop() {
|
|
942
|
+
this.lifecycleGeneration++;
|
|
888
943
|
for (const sessionId of Array.from(this.sessions.keys())) {
|
|
889
944
|
const session = this.sessions.get(sessionId);
|
|
890
945
|
if (session) {
|
|
@@ -892,7 +947,7 @@ var DaemonChannelBridge = class extends EventEmitter2 {
|
|
|
892
947
|
this.lastError = error;
|
|
893
948
|
});
|
|
894
949
|
}
|
|
895
|
-
this.dropSession(sessionId, "bridge_stopped");
|
|
950
|
+
this.dropSession(sessionId, "bridge_stopped", false);
|
|
896
951
|
}
|
|
897
952
|
this.latestAvailableCommandsSessionId = void 0;
|
|
898
953
|
this.connected = false;
|
|
@@ -900,15 +955,29 @@ var DaemonChannelBridge = class extends EventEmitter2 {
|
|
|
900
955
|
get isConnected() {
|
|
901
956
|
return this.connected;
|
|
902
957
|
}
|
|
903
|
-
attachSession(session) {
|
|
904
|
-
|
|
905
|
-
|
|
958
|
+
attachSession(session, bindingToken) {
|
|
959
|
+
const replacedSession = this.removeSessionBinding(session.sessionId);
|
|
960
|
+
if (replacedSession) {
|
|
961
|
+
void this.releaseSessionClient(replacedSession).catch((error) => {
|
|
962
|
+
this.lastError = error;
|
|
963
|
+
});
|
|
964
|
+
this.emit("sessionDied", {
|
|
965
|
+
sessionId: session.sessionId,
|
|
966
|
+
reason: "session_replaced"
|
|
967
|
+
});
|
|
906
968
|
}
|
|
907
969
|
this.sessions.set(session.sessionId, session);
|
|
970
|
+
this.sessionBindingTokens.set(session.sessionId, bindingToken);
|
|
908
971
|
const controller = new AbortController();
|
|
909
972
|
this.eventControllers.set(session.sessionId, controller);
|
|
910
973
|
void this.pumpEvents(session, controller.signal);
|
|
911
974
|
}
|
|
975
|
+
async rejectStaleSession(session) {
|
|
976
|
+
void this.releaseSessionClient(session).catch((error) => {
|
|
977
|
+
this.lastError = error;
|
|
978
|
+
});
|
|
979
|
+
throw new Error("Daemon channel bridge stopped during session creation");
|
|
980
|
+
}
|
|
912
981
|
ensureSession(sessionId) {
|
|
913
982
|
const session = this.sessions.get(sessionId);
|
|
914
983
|
if (!session) {
|
|
@@ -944,6 +1013,9 @@ var DaemonChannelBridge = class extends EventEmitter2 {
|
|
|
944
1013
|
handleEvent(session, event) {
|
|
945
1014
|
switch (event.type) {
|
|
946
1015
|
case "session_update":
|
|
1016
|
+
if (isRecord(event.data) && typeof event.data["sessionId"] === "string" && event.data["sessionId"] !== session.sessionId) {
|
|
1017
|
+
break;
|
|
1018
|
+
}
|
|
947
1019
|
this.handleSessionUpdate(session.sessionId, event.data);
|
|
948
1020
|
break;
|
|
949
1021
|
case "permission_request":
|
|
@@ -987,9 +1059,13 @@ var DaemonChannelBridge = class extends EventEmitter2 {
|
|
|
987
1059
|
const type = getString(update["sessionUpdate"]);
|
|
988
1060
|
switch (type) {
|
|
989
1061
|
case "agent_message_chunk": {
|
|
1062
|
+
const meta = isRecord(update["_meta"]) ? update["_meta"] : void 0;
|
|
1063
|
+
if (typeof meta?.["parentToolCallId"] === "string") {
|
|
1064
|
+
break;
|
|
1065
|
+
}
|
|
990
1066
|
const text = getTextContent(update["content"]);
|
|
991
1067
|
if (text) {
|
|
992
|
-
this.emit("textChunk", sessionId, text);
|
|
1068
|
+
this.emit(meta?.["source"] === "slash_command" ? "slashCommandOutput" : "textChunk", sessionId, text);
|
|
993
1069
|
}
|
|
994
1070
|
break;
|
|
995
1071
|
}
|
|
@@ -1123,14 +1199,26 @@ var DaemonChannelBridge = class extends EventEmitter2 {
|
|
|
1123
1199
|
handleSessionDied(sessionId, data) {
|
|
1124
1200
|
this.dropSession(sessionId, this.getStringField(data, "reason", "session_died"));
|
|
1125
1201
|
}
|
|
1126
|
-
dropSession(sessionId, reason) {
|
|
1127
|
-
|
|
1202
|
+
dropSession(sessionId, reason, releaseClient = true) {
|
|
1203
|
+
const session = this.removeSessionBinding(sessionId);
|
|
1204
|
+
if (!session)
|
|
1128
1205
|
return;
|
|
1206
|
+
if (releaseClient) {
|
|
1207
|
+
void this.releaseSessionClient(session).catch((error) => {
|
|
1208
|
+
this.lastError = error;
|
|
1209
|
+
});
|
|
1129
1210
|
}
|
|
1211
|
+
this.emit("sessionDied", { sessionId, reason });
|
|
1212
|
+
}
|
|
1213
|
+
removeSessionBinding(sessionId) {
|
|
1214
|
+
const session = this.sessions.get(sessionId);
|
|
1215
|
+
if (!session)
|
|
1216
|
+
return void 0;
|
|
1130
1217
|
this.resolveTurnBarrier(sessionId);
|
|
1131
1218
|
this.eventControllers.get(sessionId)?.abort();
|
|
1132
1219
|
this.eventControllers.delete(sessionId);
|
|
1133
1220
|
this.sessions.delete(sessionId);
|
|
1221
|
+
this.sessionBindingTokens.delete(sessionId);
|
|
1134
1222
|
this.abortActivePrompts(sessionId);
|
|
1135
1223
|
this.activePrompts.delete(sessionId);
|
|
1136
1224
|
this.availableCommandsBySession.delete(sessionId);
|
|
@@ -1147,7 +1235,7 @@ var DaemonChannelBridge = class extends EventEmitter2 {
|
|
|
1147
1235
|
this.respondedRequestToSession.delete(requestId);
|
|
1148
1236
|
}
|
|
1149
1237
|
}
|
|
1150
|
-
|
|
1238
|
+
return session;
|
|
1151
1239
|
}
|
|
1152
1240
|
getStringField(data, field, fallback) {
|
|
1153
1241
|
return isRecord(data) && typeof data[field] === "string" ? data[field] : fallback;
|
|
@@ -1295,7 +1383,7 @@ var BlockStreamer = class {
|
|
|
1295
1383
|
|
|
1296
1384
|
// packages/channels/base/dist/ChannelBase.js
|
|
1297
1385
|
init_esbuild_shims();
|
|
1298
|
-
import { basename, join as
|
|
1386
|
+
import { basename, join as join5 } from "node:path";
|
|
1299
1387
|
|
|
1300
1388
|
// packages/channels/base/dist/GroupGate.js
|
|
1301
1389
|
init_esbuild_shims();
|
|
@@ -1770,7 +1858,8 @@ __name(generateCode, "generateCode");
|
|
|
1770
1858
|
|
|
1771
1859
|
// packages/channels/base/dist/SessionRouter.js
|
|
1772
1860
|
init_esbuild_shims();
|
|
1773
|
-
import { existsSync as existsSync3, readFileSync as readFileSync3,
|
|
1861
|
+
import { chmodSync as chmodSync2, existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync3, renameSync as renameSync2, rmSync, unlinkSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
1862
|
+
import { dirname as dirname2, join as join4 } from "node:path";
|
|
1774
1863
|
import process2 from "node:process";
|
|
1775
1864
|
var SessionRouter = class {
|
|
1776
1865
|
static {
|
|
@@ -1784,17 +1873,22 @@ var SessionRouter = class {
|
|
|
1784
1873
|
// session ID → cwd
|
|
1785
1874
|
creatingSessions = /* @__PURE__ */ new Map();
|
|
1786
1875
|
sessionLoadWindows = /* @__PURE__ */ new Set();
|
|
1876
|
+
liveSessionIds = /* @__PURE__ */ new Set();
|
|
1877
|
+
routeTokens = /* @__PURE__ */ new Map();
|
|
1878
|
+
lifecycleGeneration = 0;
|
|
1787
1879
|
bridge;
|
|
1788
1880
|
defaultCwd;
|
|
1789
1881
|
defaultScope;
|
|
1790
1882
|
channelScopes = /* @__PURE__ */ new Map();
|
|
1791
1883
|
channelApprovalModes = /* @__PURE__ */ new Map();
|
|
1792
1884
|
persistPath;
|
|
1793
|
-
|
|
1885
|
+
recoveryMode;
|
|
1886
|
+
constructor(bridge, defaultCwd, scope = "user", persistPath, options = {}) {
|
|
1794
1887
|
this.bridge = bridge;
|
|
1795
1888
|
this.defaultCwd = defaultCwd;
|
|
1796
1889
|
this.defaultScope = scope;
|
|
1797
1890
|
this.persistPath = persistPath;
|
|
1891
|
+
this.recoveryMode = options.recoveryMode ?? "eager";
|
|
1798
1892
|
}
|
|
1799
1893
|
/** Replace the bridge instance (used after crash recovery restart). */
|
|
1800
1894
|
setBridge(bridge) {
|
|
@@ -1829,60 +1923,168 @@ var SessionRouter = class {
|
|
|
1829
1923
|
}
|
|
1830
1924
|
async resolve(channelName, senderId, chatId, threadId, cwd, isGroup, options) {
|
|
1831
1925
|
const key = this.routingKey(channelName, senderId, chatId, options?.routingThreadId ?? threadId);
|
|
1832
|
-
|
|
1926
|
+
const input = {
|
|
1927
|
+
channelName,
|
|
1928
|
+
senderId,
|
|
1929
|
+
chatId,
|
|
1930
|
+
threadId,
|
|
1931
|
+
cwd: cwd || this.defaultCwd,
|
|
1932
|
+
isGroup
|
|
1933
|
+
};
|
|
1934
|
+
let failedWaits = 0;
|
|
1833
1935
|
for (; ; ) {
|
|
1834
1936
|
const existing = this.toSession.get(key);
|
|
1835
|
-
if (existing) {
|
|
1937
|
+
if (existing && this.isLive(existing)) {
|
|
1836
1938
|
this.promoteTargetToGroup(existing, isGroup);
|
|
1837
1939
|
return existing;
|
|
1838
1940
|
}
|
|
1839
1941
|
const creating = this.creatingSessions.get(key);
|
|
1840
1942
|
if (creating) {
|
|
1841
1943
|
try {
|
|
1842
|
-
const sessionId = await creating;
|
|
1944
|
+
const sessionId = await creating.promise;
|
|
1945
|
+
try {
|
|
1946
|
+
this.assertOperationResultCurrent(key, sessionId, creating);
|
|
1947
|
+
} catch (error) {
|
|
1948
|
+
this.scheduleDiscardInvalidatedSession(sessionId, creating);
|
|
1949
|
+
throw error;
|
|
1950
|
+
}
|
|
1843
1951
|
this.promoteTargetToGroup(sessionId, isGroup);
|
|
1844
1952
|
return sessionId;
|
|
1845
|
-
} catch (
|
|
1953
|
+
} catch (error) {
|
|
1954
|
+
if (creating.invalidationError) {
|
|
1955
|
+
throw creating.invalidationError;
|
|
1956
|
+
}
|
|
1846
1957
|
if (this.creatingSessions.get(key) === creating) {
|
|
1847
1958
|
this.creatingSessions.delete(key);
|
|
1848
1959
|
}
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1960
|
+
this.releaseRouteToken(key, creating);
|
|
1961
|
+
failedWaits++;
|
|
1962
|
+
if (failedWaits > 3)
|
|
1963
|
+
throw error;
|
|
1853
1964
|
continue;
|
|
1854
1965
|
}
|
|
1855
1966
|
}
|
|
1856
|
-
const
|
|
1857
|
-
|
|
1858
|
-
|
|
1967
|
+
const operation = this.createSessionOperation(key, {
|
|
1968
|
+
channelName: input.channelName,
|
|
1969
|
+
senderId: input.senderId,
|
|
1970
|
+
chatId: input.chatId,
|
|
1971
|
+
threadId: input.threadId,
|
|
1972
|
+
isGroup: input.isGroup
|
|
1973
|
+
}, (currentOperation) => existing ? this.loadOrReplaceSession(key, existing, input, currentOperation) : this.createAndStoreSession(key, input, currentOperation));
|
|
1974
|
+
this.creatingSessions.set(key, operation);
|
|
1975
|
+
try {
|
|
1976
|
+
const sessionId = await operation.promise;
|
|
1859
1977
|
try {
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
this.
|
|
1863
|
-
|
|
1864
|
-
senderId,
|
|
1865
|
-
chatId,
|
|
1866
|
-
threadId,
|
|
1867
|
-
isGroup
|
|
1868
|
-
});
|
|
1869
|
-
this.toCwd.set(sessionId, sessionCwd);
|
|
1870
|
-
this.persist();
|
|
1871
|
-
return sessionId;
|
|
1872
|
-
} finally {
|
|
1873
|
-
this.endSessionLoad(loadWindow);
|
|
1978
|
+
this.assertOperationResultCurrent(key, sessionId, operation);
|
|
1979
|
+
} catch (error) {
|
|
1980
|
+
this.scheduleDiscardInvalidatedSession(sessionId, operation);
|
|
1981
|
+
throw error;
|
|
1874
1982
|
}
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
try {
|
|
1878
|
-
return await created;
|
|
1983
|
+
this.promoteTargetToGroup(sessionId, isGroup);
|
|
1984
|
+
return sessionId;
|
|
1879
1985
|
} finally {
|
|
1880
|
-
if (this.creatingSessions.get(key) ===
|
|
1986
|
+
if (this.creatingSessions.get(key) === operation) {
|
|
1881
1987
|
this.creatingSessions.delete(key);
|
|
1882
1988
|
}
|
|
1989
|
+
this.releaseRouteToken(key, operation);
|
|
1883
1990
|
}
|
|
1884
1991
|
}
|
|
1885
1992
|
}
|
|
1993
|
+
isLive(sessionId) {
|
|
1994
|
+
return this.recoveryMode === "eager" || this.liveSessionIds.has(sessionId);
|
|
1995
|
+
}
|
|
1996
|
+
async createAndStoreSession(key, input, operation) {
|
|
1997
|
+
const loadWindow = this.beginSessionLoad();
|
|
1998
|
+
try {
|
|
1999
|
+
const sessionId = await this.createLiveSession(input.cwd, loadWindow, key, this.sessionOptions(input.channelName), operation);
|
|
2000
|
+
try {
|
|
2001
|
+
this.assertOperationCurrent(operation);
|
|
2002
|
+
} catch (error) {
|
|
2003
|
+
this.scheduleDiscardInvalidatedSession(sessionId, operation);
|
|
2004
|
+
throw error;
|
|
2005
|
+
}
|
|
2006
|
+
this.toSession.set(key, sessionId);
|
|
2007
|
+
this.toTarget.set(sessionId, {
|
|
2008
|
+
channelName: input.channelName,
|
|
2009
|
+
senderId: input.senderId,
|
|
2010
|
+
chatId: input.chatId,
|
|
2011
|
+
threadId: input.threadId,
|
|
2012
|
+
isGroup: input.isGroup
|
|
2013
|
+
});
|
|
2014
|
+
this.toCwd.set(sessionId, input.cwd);
|
|
2015
|
+
this.liveSessionIds.add(sessionId);
|
|
2016
|
+
this.persist();
|
|
2017
|
+
return sessionId;
|
|
2018
|
+
} finally {
|
|
2019
|
+
this.endSessionLoad(loadWindow);
|
|
2020
|
+
}
|
|
2021
|
+
}
|
|
2022
|
+
async loadOrReplaceSession(key, savedSessionId, input, operation) {
|
|
2023
|
+
const savedCwd = this.toCwd.get(savedSessionId) ?? input.cwd;
|
|
2024
|
+
const loadWindow = this.beginSessionLoad();
|
|
2025
|
+
try {
|
|
2026
|
+
try {
|
|
2027
|
+
const loadedSessionId = await this.bridge.loadSession(savedSessionId, savedCwd, this.sessionOptions(input.channelName), operation);
|
|
2028
|
+
try {
|
|
2029
|
+
this.assertOperationCurrent(operation);
|
|
2030
|
+
if (this.toSession.get(key) !== savedSessionId) {
|
|
2031
|
+
this.invalidateOperation(operation);
|
|
2032
|
+
this.assertOperationCurrent(operation);
|
|
2033
|
+
}
|
|
2034
|
+
} catch (error) {
|
|
2035
|
+
this.scheduleDiscardInvalidatedSession(loadedSessionId, operation);
|
|
2036
|
+
throw error;
|
|
2037
|
+
}
|
|
2038
|
+
if (typeof loadedSessionId !== "string" || loadedSessionId.length === 0 || loadWindow.delete(loadedSessionId)) {
|
|
2039
|
+
throw new Error("Invalid or dead restored session ID");
|
|
2040
|
+
}
|
|
2041
|
+
if (loadedSessionId !== savedSessionId) {
|
|
2042
|
+
const target = this.toTarget.get(savedSessionId);
|
|
2043
|
+
this.deleteByKey(key);
|
|
2044
|
+
this.toSession.set(key, loadedSessionId);
|
|
2045
|
+
if (target)
|
|
2046
|
+
this.toTarget.set(loadedSessionId, target);
|
|
2047
|
+
this.toCwd.set(loadedSessionId, savedCwd);
|
|
2048
|
+
this.persist();
|
|
2049
|
+
}
|
|
2050
|
+
this.liveSessionIds.add(loadedSessionId);
|
|
2051
|
+
return loadedSessionId;
|
|
2052
|
+
} catch (loadError) {
|
|
2053
|
+
this.assertOperationCurrent(operation);
|
|
2054
|
+
try {
|
|
2055
|
+
const replacement = await this.createLiveSession(input.cwd, loadWindow, key, this.sessionOptions(input.channelName), operation);
|
|
2056
|
+
try {
|
|
2057
|
+
this.assertOperationCurrent(operation);
|
|
2058
|
+
} catch (error) {
|
|
2059
|
+
this.scheduleDiscardInvalidatedSession(replacement, operation);
|
|
2060
|
+
throw error;
|
|
2061
|
+
}
|
|
2062
|
+
this.deleteByKey(key);
|
|
2063
|
+
this.toSession.set(key, replacement);
|
|
2064
|
+
this.toTarget.set(replacement, {
|
|
2065
|
+
channelName: input.channelName,
|
|
2066
|
+
senderId: input.senderId,
|
|
2067
|
+
chatId: input.chatId,
|
|
2068
|
+
threadId: input.threadId,
|
|
2069
|
+
isGroup: input.isGroup
|
|
2070
|
+
});
|
|
2071
|
+
this.toCwd.set(replacement, input.cwd);
|
|
2072
|
+
this.liveSessionIds.add(replacement);
|
|
2073
|
+
this.persist();
|
|
2074
|
+
process2.stderr.write(`[SessionRouter] Replaced unavailable session ${sanitizeLogText(savedSessionId, 128)} for key ${sanitizeLogText(key, 256)} after load failed: ${sanitizeLogText(loadError instanceof Error ? loadError.message : String(loadError), 512)}
|
|
2075
|
+
`);
|
|
2076
|
+
return replacement;
|
|
2077
|
+
} catch (createError) {
|
|
2078
|
+
this.assertOperationCurrent(operation);
|
|
2079
|
+
process2.stderr.write(`[SessionRouter] Failed to load session ${sanitizeLogText(savedSessionId, 128)} for key ${sanitizeLogText(key, 256)} (${sanitizeLogText(loadError instanceof Error ? loadError.message : String(loadError), 512)}) and failed to create a replacement (${sanitizeLogText(createError instanceof Error ? createError.message : String(createError), 512)})
|
|
2080
|
+
`);
|
|
2081
|
+
throw createError;
|
|
2082
|
+
}
|
|
2083
|
+
}
|
|
2084
|
+
} finally {
|
|
2085
|
+
this.endSessionLoad(loadWindow);
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
1886
2088
|
getTarget(sessionId) {
|
|
1887
2089
|
return this.toTarget.get(sessionId);
|
|
1888
2090
|
}
|
|
@@ -1912,6 +2114,7 @@ var SessionRouter = class {
|
|
|
1912
2114
|
const scope = this.channelScopes.get(channelName) || this.defaultScope;
|
|
1913
2115
|
if (chatId) {
|
|
1914
2116
|
const key = this.routingKey(channelName, senderId, chatId, threadId);
|
|
2117
|
+
this.invalidateRouteOperation(key);
|
|
1915
2118
|
const sessionId = this.deleteByKey(key);
|
|
1916
2119
|
if (sessionId)
|
|
1917
2120
|
removedIds.push(sessionId);
|
|
@@ -1921,11 +2124,17 @@ var SessionRouter = class {
|
|
|
1921
2124
|
for (const [k, mappedSessionId] of [...this.toSession.entries()]) {
|
|
1922
2125
|
const target = this.toTarget.get(mappedSessionId);
|
|
1923
2126
|
if (target?.channelName === channelName && target.senderId === senderId) {
|
|
2127
|
+
this.invalidateRouteOperation(k);
|
|
1924
2128
|
const sessionId = this.deleteByKey(k);
|
|
1925
2129
|
if (sessionId)
|
|
1926
2130
|
removedIds.push(sessionId);
|
|
1927
2131
|
}
|
|
1928
2132
|
}
|
|
2133
|
+
for (const [key, operation] of [...this.creatingSessions]) {
|
|
2134
|
+
if (operation.target.channelName === channelName && operation.target.senderId === senderId) {
|
|
2135
|
+
this.invalidateRouteOperation(key);
|
|
2136
|
+
}
|
|
2137
|
+
}
|
|
1929
2138
|
}
|
|
1930
2139
|
if (removedIds.length > 0)
|
|
1931
2140
|
this.persist();
|
|
@@ -1936,6 +2145,7 @@ var SessionRouter = class {
|
|
|
1936
2145
|
let removed = false;
|
|
1937
2146
|
for (const [key, mappedSessionId] of [...this.toSession.entries()]) {
|
|
1938
2147
|
if (mappedSessionId === sessionId) {
|
|
2148
|
+
this.invalidateRouteOperation(key);
|
|
1939
2149
|
this.toSession.delete(key);
|
|
1940
2150
|
removed = true;
|
|
1941
2151
|
}
|
|
@@ -1946,6 +2156,7 @@ var SessionRouter = class {
|
|
|
1946
2156
|
if (this.toCwd.delete(sessionId)) {
|
|
1947
2157
|
removed = true;
|
|
1948
2158
|
}
|
|
2159
|
+
this.liveSessionIds.delete(sessionId);
|
|
1949
2160
|
if (!removed && this.sessionLoadWindows.size > 0) {
|
|
1950
2161
|
for (const loadWindow of this.sessionLoadWindows) {
|
|
1951
2162
|
loadWindow.add(sessionId);
|
|
@@ -1956,6 +2167,17 @@ var SessionRouter = class {
|
|
|
1956
2167
|
}
|
|
1957
2168
|
return removed;
|
|
1958
2169
|
}
|
|
2170
|
+
handleSessionDied(sessionId) {
|
|
2171
|
+
if (this.recoveryMode === "eager") {
|
|
2172
|
+
return this.removeSessionId(sessionId);
|
|
2173
|
+
}
|
|
2174
|
+
const known = this.toTarget.has(sessionId);
|
|
2175
|
+
this.liveSessionIds.delete(sessionId);
|
|
2176
|
+
for (const loadWindow of this.sessionLoadWindows) {
|
|
2177
|
+
loadWindow.add(sessionId);
|
|
2178
|
+
}
|
|
2179
|
+
return known;
|
|
2180
|
+
}
|
|
1959
2181
|
deleteByKey(key) {
|
|
1960
2182
|
const sessionId = this.toSession.get(key);
|
|
1961
2183
|
if (!sessionId)
|
|
@@ -1963,6 +2185,7 @@ var SessionRouter = class {
|
|
|
1963
2185
|
this.toSession.delete(key);
|
|
1964
2186
|
this.toTarget.delete(sessionId);
|
|
1965
2187
|
this.toCwd.delete(sessionId);
|
|
2188
|
+
this.liveSessionIds.delete(sessionId);
|
|
1966
2189
|
return sessionId;
|
|
1967
2190
|
}
|
|
1968
2191
|
promoteTargetToGroup(sessionId, isGroup) {
|
|
@@ -1985,45 +2208,69 @@ var SessionRouter = class {
|
|
|
1985
2208
|
}
|
|
1986
2209
|
return entries;
|
|
1987
2210
|
}
|
|
2211
|
+
restoreRoutes() {
|
|
2212
|
+
if (this.recoveryMode !== "lazy") {
|
|
2213
|
+
throw new Error("restoreRoutes requires lazy recovery mode");
|
|
2214
|
+
}
|
|
2215
|
+
const persisted = this.readPersistedEntries();
|
|
2216
|
+
if (!persisted)
|
|
2217
|
+
return { restored: 0, dropped: 0 };
|
|
2218
|
+
this.dispose();
|
|
2219
|
+
let restored = 0;
|
|
2220
|
+
for (const [key, entry] of Object.entries(persisted.entries)) {
|
|
2221
|
+
this.toSession.set(key, entry.sessionId);
|
|
2222
|
+
this.toTarget.set(entry.sessionId, entry.target);
|
|
2223
|
+
this.toCwd.set(entry.sessionId, entry.cwd);
|
|
2224
|
+
restored++;
|
|
2225
|
+
}
|
|
2226
|
+
if (persisted.dropped > 0)
|
|
2227
|
+
this.persist();
|
|
2228
|
+
return { restored, dropped: persisted.dropped };
|
|
2229
|
+
}
|
|
1988
2230
|
/**
|
|
1989
2231
|
* Restore session mappings from a previous bridge.
|
|
1990
2232
|
* Called after bridge restart — attempts loadSession for each saved mapping.
|
|
1991
2233
|
* Failed loads are dropped (new session on next message).
|
|
1992
2234
|
*/
|
|
1993
2235
|
async restoreSessions() {
|
|
1994
|
-
const
|
|
1995
|
-
if (!
|
|
1996
|
-
return { restored: 0, failed: 0 };
|
|
1997
|
-
}
|
|
1998
|
-
let entries;
|
|
1999
|
-
try {
|
|
2000
|
-
entries = JSON.parse(readFileSync3(persistPath, "utf-8"));
|
|
2001
|
-
} catch (err) {
|
|
2002
|
-
const reason = err instanceof Error ? err.message : String(err);
|
|
2003
|
-
process2.stderr.write(`[SessionRouter] Corrupted persist file at ${sanitizeLogText(persistPath, 1024)}: ${sanitizeLogText(reason, 512)}
|
|
2004
|
-
`);
|
|
2236
|
+
const persisted = this.readPersistedEntries();
|
|
2237
|
+
if (!persisted)
|
|
2005
2238
|
return { restored: 0, failed: 0 };
|
|
2006
|
-
|
|
2239
|
+
const entries = persisted.entries;
|
|
2240
|
+
const restoreGeneration = this.lifecycleGeneration;
|
|
2007
2241
|
let restored = 0;
|
|
2008
2242
|
let failed = 0;
|
|
2009
|
-
let changed =
|
|
2243
|
+
let changed = persisted.dropped > 0;
|
|
2010
2244
|
const reservations = /* @__PURE__ */ new Map();
|
|
2245
|
+
for (const key of persisted.droppedKeys) {
|
|
2246
|
+
this.deleteByKey(key);
|
|
2247
|
+
}
|
|
2011
2248
|
for (const key of Object.keys(entries)) {
|
|
2012
2249
|
this.deleteByKey(key);
|
|
2013
2250
|
const reservation = this.createSessionReservation();
|
|
2014
2251
|
reservation.promise.catch(() => void 0);
|
|
2015
|
-
this.
|
|
2016
|
-
|
|
2252
|
+
const operation = this.createSessionOperation(key, entries[key].target, () => reservation.promise);
|
|
2253
|
+
operation.promise.catch(() => void 0);
|
|
2254
|
+
this.creatingSessions.set(key, operation);
|
|
2255
|
+
reservations.set(key, { reservation, operation });
|
|
2017
2256
|
}
|
|
2018
2257
|
const loadWindow = this.beginSessionLoad();
|
|
2019
2258
|
try {
|
|
2020
2259
|
for (const [key, entry] of Object.entries(entries)) {
|
|
2021
|
-
const
|
|
2022
|
-
if (!
|
|
2260
|
+
const reserved = reservations.get(key);
|
|
2261
|
+
if (!reserved)
|
|
2023
2262
|
continue;
|
|
2263
|
+
const { reservation, operation } = reserved;
|
|
2024
2264
|
try {
|
|
2265
|
+
this.assertOperationCurrent(operation);
|
|
2025
2266
|
const options = this.sessionOptions(entry.target.channelName);
|
|
2026
|
-
const sessionId =
|
|
2267
|
+
const sessionId = await this.bridge.loadSession(entry.sessionId, entry.cwd, options, operation);
|
|
2268
|
+
try {
|
|
2269
|
+
this.assertOperationCurrent(operation);
|
|
2270
|
+
} catch (error) {
|
|
2271
|
+
this.scheduleDiscardInvalidatedSession(sessionId, operation);
|
|
2272
|
+
throw error;
|
|
2273
|
+
}
|
|
2027
2274
|
if (typeof sessionId !== "string" || sessionId.length === 0) {
|
|
2028
2275
|
throw new Error("Invalid restored session ID");
|
|
2029
2276
|
}
|
|
@@ -2046,26 +2293,36 @@ var SessionRouter = class {
|
|
|
2046
2293
|
failed++;
|
|
2047
2294
|
changed = true;
|
|
2048
2295
|
} finally {
|
|
2049
|
-
if (this.creatingSessions.get(key) ===
|
|
2296
|
+
if (this.creatingSessions.get(key) === operation) {
|
|
2050
2297
|
this.creatingSessions.delete(key);
|
|
2051
2298
|
}
|
|
2299
|
+
this.releaseRouteToken(key, operation);
|
|
2052
2300
|
}
|
|
2053
2301
|
}
|
|
2054
2302
|
} finally {
|
|
2055
2303
|
this.endSessionLoad(loadWindow);
|
|
2056
2304
|
}
|
|
2057
|
-
if (changed) {
|
|
2305
|
+
if (changed && restoreGeneration === this.lifecycleGeneration) {
|
|
2058
2306
|
this.persist();
|
|
2059
2307
|
}
|
|
2060
2308
|
return { restored, failed };
|
|
2061
2309
|
}
|
|
2062
|
-
|
|
2063
|
-
|
|
2310
|
+
dispose() {
|
|
2311
|
+
this.lifecycleGeneration++;
|
|
2312
|
+
for (const operation of this.creatingSessions.values()) {
|
|
2313
|
+
this.invalidateOperation(operation);
|
|
2314
|
+
}
|
|
2064
2315
|
this.toSession.clear();
|
|
2065
2316
|
this.toTarget.clear();
|
|
2066
2317
|
this.toCwd.clear();
|
|
2067
2318
|
this.creatingSessions.clear();
|
|
2068
2319
|
this.sessionLoadWindows.clear();
|
|
2320
|
+
this.liveSessionIds.clear();
|
|
2321
|
+
this.routeTokens.clear();
|
|
2322
|
+
}
|
|
2323
|
+
/** Clear in-memory state and delete persist file. Used on clean shutdown. */
|
|
2324
|
+
clearAll() {
|
|
2325
|
+
this.dispose();
|
|
2069
2326
|
if (this.persistPath && existsSync3(this.persistPath)) {
|
|
2070
2327
|
try {
|
|
2071
2328
|
unlinkSync(this.persistPath);
|
|
@@ -2073,30 +2330,105 @@ var SessionRouter = class {
|
|
|
2073
2330
|
}
|
|
2074
2331
|
}
|
|
2075
2332
|
}
|
|
2333
|
+
readPersistedEntries() {
|
|
2334
|
+
const persistPath = this.persistPath;
|
|
2335
|
+
if (!persistPath || !existsSync3(persistPath))
|
|
2336
|
+
return void 0;
|
|
2337
|
+
let parsed;
|
|
2338
|
+
try {
|
|
2339
|
+
parsed = JSON.parse(readFileSync3(persistPath, "utf-8"));
|
|
2340
|
+
} catch (error) {
|
|
2341
|
+
const quarantinePath = `${persistPath}.corrupt-${Date.now()}`;
|
|
2342
|
+
try {
|
|
2343
|
+
renameSync2(persistPath, quarantinePath);
|
|
2344
|
+
} catch {
|
|
2345
|
+
}
|
|
2346
|
+
process2.stderr.write(`[SessionRouter] Corrupted persist file at ${sanitizeLogText(persistPath, 1024)}: ${sanitizeLogText(error instanceof Error ? error.message : String(error), 512)}
|
|
2347
|
+
`);
|
|
2348
|
+
return void 0;
|
|
2349
|
+
}
|
|
2350
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
2351
|
+
const quarantinePath = `${persistPath}.corrupt-${Date.now()}`;
|
|
2352
|
+
try {
|
|
2353
|
+
renameSync2(persistPath, quarantinePath);
|
|
2354
|
+
} catch {
|
|
2355
|
+
}
|
|
2356
|
+
process2.stderr.write(`[SessionRouter] Invalid route store at ${sanitizeLogText(persistPath, 1024)}: expected an object
|
|
2357
|
+
`);
|
|
2358
|
+
return void 0;
|
|
2359
|
+
}
|
|
2360
|
+
const entries = {};
|
|
2361
|
+
const droppedKeys = [];
|
|
2362
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
2363
|
+
if (this.isPersistedEntry(value))
|
|
2364
|
+
entries[key] = value;
|
|
2365
|
+
else
|
|
2366
|
+
droppedKeys.push(key);
|
|
2367
|
+
}
|
|
2368
|
+
return { entries, dropped: droppedKeys.length, droppedKeys };
|
|
2369
|
+
}
|
|
2370
|
+
isPersistedEntry(value) {
|
|
2371
|
+
if (typeof value !== "object" || value === null)
|
|
2372
|
+
return false;
|
|
2373
|
+
const entry = value;
|
|
2374
|
+
const target = entry["target"];
|
|
2375
|
+
if (typeof target !== "object" || target === null)
|
|
2376
|
+
return false;
|
|
2377
|
+
const typedTarget = target;
|
|
2378
|
+
return typeof entry["sessionId"] === "string" && entry["sessionId"].length > 0 && typeof entry["cwd"] === "string" && entry["cwd"].length > 0 && typeof typedTarget["channelName"] === "string" && typeof typedTarget["senderId"] === "string" && typeof typedTarget["chatId"] === "string" && (typedTarget["threadId"] === void 0 || typeof typedTarget["threadId"] === "string") && (typedTarget["isGroup"] === void 0 || typeof typedTarget["isGroup"] === "boolean");
|
|
2379
|
+
}
|
|
2076
2380
|
persist() {
|
|
2077
2381
|
if (!this.persistPath)
|
|
2078
2382
|
return;
|
|
2079
2383
|
const data = {};
|
|
2080
2384
|
for (const [key, sessionId] of this.toSession) {
|
|
2081
2385
|
const target = this.toTarget.get(sessionId);
|
|
2082
|
-
if (target)
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
}
|
|
2386
|
+
if (!target)
|
|
2387
|
+
continue;
|
|
2388
|
+
data[key] = {
|
|
2389
|
+
sessionId,
|
|
2390
|
+
target,
|
|
2391
|
+
cwd: this.toCwd.get(sessionId) ?? this.defaultCwd
|
|
2392
|
+
};
|
|
2089
2393
|
}
|
|
2394
|
+
const dir = dirname2(this.persistPath);
|
|
2395
|
+
const tempPath = join4(dir, `${Date.now()}-${process2.pid}-${Math.random().toString(16).slice(2)}.tmp`);
|
|
2090
2396
|
try {
|
|
2091
|
-
|
|
2092
|
-
|
|
2397
|
+
mkdirSync3(dir, { recursive: true, mode: 448 });
|
|
2398
|
+
try {
|
|
2399
|
+
chmodSync2(dir, 448);
|
|
2400
|
+
} catch {
|
|
2401
|
+
}
|
|
2402
|
+
writeFileSync3(tempPath, JSON.stringify(data, null, 2), {
|
|
2403
|
+
encoding: "utf-8",
|
|
2404
|
+
mode: 384
|
|
2405
|
+
});
|
|
2406
|
+
renameSync2(tempPath, this.persistPath);
|
|
2407
|
+
try {
|
|
2408
|
+
chmodSync2(this.persistPath, 384);
|
|
2409
|
+
} catch {
|
|
2410
|
+
}
|
|
2411
|
+
} catch (error) {
|
|
2412
|
+
process2.stderr.write(`[SessionRouter] Failed to persist routes at ${sanitizeLogText(this.persistPath, 1024)}: ${sanitizeLogText(error instanceof Error ? error.message : String(error), 512)}
|
|
2413
|
+
`);
|
|
2414
|
+
} finally {
|
|
2415
|
+
try {
|
|
2416
|
+
rmSync(tempPath, { force: true });
|
|
2417
|
+
} catch {
|
|
2418
|
+
}
|
|
2093
2419
|
}
|
|
2094
2420
|
}
|
|
2095
|
-
async createLiveSession(cwd, loadWindow, routingKey, options) {
|
|
2421
|
+
async createLiveSession(cwd, loadWindow, routingKey, options, operation) {
|
|
2096
2422
|
const maxAttempts = 2;
|
|
2097
2423
|
let lastDeadSessionId;
|
|
2098
2424
|
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
2099
|
-
const sessionId =
|
|
2425
|
+
const sessionId = await this.bridge.newSession(cwd, options, operation);
|
|
2426
|
+
try {
|
|
2427
|
+
this.assertOperationCurrent(operation);
|
|
2428
|
+
} catch (error) {
|
|
2429
|
+
this.scheduleDiscardInvalidatedSession(sessionId, operation);
|
|
2430
|
+
throw error;
|
|
2431
|
+
}
|
|
2100
2432
|
if (typeof sessionId !== "string" || sessionId.length === 0) {
|
|
2101
2433
|
throw new Error("Invalid session ID from bridge");
|
|
2102
2434
|
}
|
|
@@ -2112,6 +2444,65 @@ var SessionRouter = class {
|
|
|
2112
2444
|
this.sessionLoadWindows.add(loadWindow);
|
|
2113
2445
|
return loadWindow;
|
|
2114
2446
|
}
|
|
2447
|
+
createSessionOperation(key, target, run) {
|
|
2448
|
+
let routeToken = this.routeTokens.get(key);
|
|
2449
|
+
if (!routeToken) {
|
|
2450
|
+
routeToken = {};
|
|
2451
|
+
this.routeTokens.set(key, routeToken);
|
|
2452
|
+
}
|
|
2453
|
+
const operation = {
|
|
2454
|
+
promise: Promise.resolve(""),
|
|
2455
|
+
target,
|
|
2456
|
+
lifecycleGeneration: this.lifecycleGeneration,
|
|
2457
|
+
routeToken
|
|
2458
|
+
};
|
|
2459
|
+
operation.promise = Promise.resolve().then(() => run(operation)).catch((error) => {
|
|
2460
|
+
this.assertOperationCurrent(operation);
|
|
2461
|
+
throw error;
|
|
2462
|
+
});
|
|
2463
|
+
return operation;
|
|
2464
|
+
}
|
|
2465
|
+
invalidateRouteOperation(key) {
|
|
2466
|
+
this.routeTokens.delete(key);
|
|
2467
|
+
const operation = this.creatingSessions.get(key);
|
|
2468
|
+
if (!operation)
|
|
2469
|
+
return;
|
|
2470
|
+
this.invalidateOperation(operation);
|
|
2471
|
+
this.creatingSessions.delete(key);
|
|
2472
|
+
}
|
|
2473
|
+
invalidateOperation(operation) {
|
|
2474
|
+
operation.invalidationError ??= new Error("Session route operation was invalidated");
|
|
2475
|
+
}
|
|
2476
|
+
assertOperationCurrent(operation) {
|
|
2477
|
+
if (operation.lifecycleGeneration !== this.lifecycleGeneration) {
|
|
2478
|
+
this.invalidateOperation(operation);
|
|
2479
|
+
}
|
|
2480
|
+
if (operation.invalidationError) {
|
|
2481
|
+
throw operation.invalidationError;
|
|
2482
|
+
}
|
|
2483
|
+
}
|
|
2484
|
+
assertOperationResultCurrent(key, sessionId, operation) {
|
|
2485
|
+
if (operation.routeToken !== this.routeTokens.get(key)) {
|
|
2486
|
+
this.invalidateOperation(operation);
|
|
2487
|
+
}
|
|
2488
|
+
if (this.toSession.get(key) !== sessionId) {
|
|
2489
|
+
this.invalidateOperation(operation);
|
|
2490
|
+
}
|
|
2491
|
+
this.assertOperationCurrent(operation);
|
|
2492
|
+
}
|
|
2493
|
+
releaseRouteToken(key, operation) {
|
|
2494
|
+
if (this.routeTokens.get(key) === operation.routeToken && !this.toSession.has(key) && !this.creatingSessions.has(key)) {
|
|
2495
|
+
this.routeTokens.delete(key);
|
|
2496
|
+
}
|
|
2497
|
+
}
|
|
2498
|
+
scheduleDiscardInvalidatedSession(sessionId, operation) {
|
|
2499
|
+
if ([...this.toSession.values()].includes(sessionId))
|
|
2500
|
+
return;
|
|
2501
|
+
try {
|
|
2502
|
+
void this.bridge.discardSession?.(sessionId, operation).catch(() => void 0);
|
|
2503
|
+
} catch {
|
|
2504
|
+
}
|
|
2505
|
+
}
|
|
2115
2506
|
createSessionReservation() {
|
|
2116
2507
|
let resolveReservation;
|
|
2117
2508
|
let rejectReservation;
|
|
@@ -2750,7 +3141,7 @@ var ChannelBase = class {
|
|
|
2750
3141
|
this.memoryScope = Object.freeze(this.resolveMemoryScope(name, config));
|
|
2751
3142
|
this.channelMemory = options?.channelMemory;
|
|
2752
3143
|
this.memoryIntentClassifier = options?.memoryIntentClassifier;
|
|
2753
|
-
this.groupHistory = new GroupHistoryStore(options?.groupHistoryPath ??
|
|
3144
|
+
this.groupHistory = new GroupHistoryStore(options?.groupHistoryPath ?? join5(getGlobalQwenDir(), "channels", `${encodeURIComponent(name)}-group-history.jsonl`));
|
|
2754
3145
|
this.loopController = options?.loopController;
|
|
2755
3146
|
this.groupGate = new GroupGate(config.groupPolicy, config.groups);
|
|
2756
3147
|
this.dmGate = new DmGate(config.dmPolicy);
|
|
@@ -3444,7 +3835,7 @@ ${sanitizePromptText(job.prompt)}`;
|
|
|
3444
3835
|
onToolCall(_chatId, _event) {
|
|
3445
3836
|
}
|
|
3446
3837
|
onSessionDied(sessionId) {
|
|
3447
|
-
this.router.
|
|
3838
|
+
this.router.handleSessionDied(sessionId);
|
|
3448
3839
|
this.instructedSessions.delete(sessionId);
|
|
3449
3840
|
this.removePendingPermissionsForSession(sessionId);
|
|
3450
3841
|
}
|
|
@@ -3492,13 +3883,16 @@ ${sanitizePromptText(job.prompt)}`;
|
|
|
3492
3883
|
*/
|
|
3493
3884
|
onResponseBoundary(_chatId, _sessionId) {
|
|
3494
3885
|
}
|
|
3886
|
+
async sendResponseMessage(chatId, text, _sessionId) {
|
|
3887
|
+
await this.sendMessage(chatId, text);
|
|
3888
|
+
}
|
|
3495
3889
|
/**
|
|
3496
3890
|
* Called when the agent's full response is ready.
|
|
3497
3891
|
* Override to customize delivery (e.g., finalize an AI card).
|
|
3498
|
-
* Default:
|
|
3892
|
+
* Default: sends the full response text.
|
|
3499
3893
|
*/
|
|
3500
|
-
async onResponseComplete(chatId, fullText,
|
|
3501
|
-
await this.
|
|
3894
|
+
async onResponseComplete(chatId, fullText, sessionId) {
|
|
3895
|
+
await this.sendResponseMessage(chatId, fullText, sessionId);
|
|
3502
3896
|
}
|
|
3503
3897
|
/**
|
|
3504
3898
|
* Register a slash command handler. Subclasses can call this to add
|
|
@@ -4909,12 +5303,14 @@ ${promptToSend}`;
|
|
|
4909
5303
|
minChars: this.config.blockStreamingChunk?.minChars ?? 400,
|
|
4910
5304
|
maxChars: this.config.blockStreamingChunk?.maxChars ?? 1e3,
|
|
4911
5305
|
idleMs: this.config.blockStreamingCoalesce?.idleMs ?? 1500,
|
|
4912
|
-
send: /* @__PURE__ */ __name((text) => this.
|
|
5306
|
+
send: /* @__PURE__ */ __name((text) => this.sendResponseMessage(envelope.chatId, text, sessionId), "send")
|
|
4913
5307
|
}) : null;
|
|
4914
5308
|
promptState.stopStreaming = () => streamer?.stop();
|
|
4915
5309
|
const heldChunks = [];
|
|
5310
|
+
let hasStreamedText = false;
|
|
4916
5311
|
const releaseHeldChunks = /* @__PURE__ */ __name(() => {
|
|
4917
5312
|
for (const held of heldChunks.splice(0)) {
|
|
5313
|
+
hasStreamedText = true;
|
|
4918
5314
|
this.emitTaskLifecycle({
|
|
4919
5315
|
...this.lifecycleBase(envelope.chatId, sessionId, envelope.messageId),
|
|
4920
5316
|
type: "text_chunk",
|
|
@@ -4938,6 +5334,7 @@ ${promptToSend}`;
|
|
|
4938
5334
|
return;
|
|
4939
5335
|
}
|
|
4940
5336
|
heldChunks.length = 0;
|
|
5337
|
+
hasStreamedText = false;
|
|
4941
5338
|
this.onResponseBoundary(envelope.chatId, sessionId);
|
|
4942
5339
|
streamer?.stop();
|
|
4943
5340
|
}, "onResponseBoundary");
|
|
@@ -4956,6 +5353,9 @@ ${promptToSend}`;
|
|
|
4956
5353
|
if (!promptState.cancelled && response) {
|
|
4957
5354
|
promptState.deliveryStarted = true;
|
|
4958
5355
|
if (streamer) {
|
|
5356
|
+
if (!hasStreamedText) {
|
|
5357
|
+
streamer.push(response);
|
|
5358
|
+
}
|
|
4959
5359
|
await streamer.flush();
|
|
4960
5360
|
} else {
|
|
4961
5361
|
await this.onResponseComplete(envelope.chatId, response, sessionId);
|