@qwen-code/qwen-code 0.19.9 → 0.19.10-nightly.20260715.c538bd70d
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 +8 -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-LOOBDOTZ.js} +31 -31
- package/chunks/{StandaloneSessionPicker-WS4GXYOG.js → StandaloneSessionPicker-76CLZSH2.js} +51 -49
- package/chunks/{acpAgent-5FWSOZL5.js → acpAgent-DFJOK7EB.js} +567 -482
- package/chunks/{agent-HOLHB3RT.js → agent-OJQWXNHP.js} +26 -26
- package/chunks/{agent-headless-SXL6H56A.js → agent-headless-ND7GOORY.js} +26 -26
- package/chunks/{anthropicContentGenerator-L73TO3DB.js → anthropicContentGenerator-56U3YCP2.js} +5 -5
- package/chunks/{artifact-tool-U7IRTLIV.js → artifact-tool-MIZLXBLF.js} +2 -2
- package/chunks/{askUserQuestion-2DLUUZZG.js → askUserQuestion-XMJVPNWM.js} +2 -2
- package/chunks/{bridge-BCJQ7BBB.js → bridge-SNJK2JLK.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-YSFB4HUU.js +418 -0
- package/chunks/channel-worker-supervisor-QCKIOYZD.js +20 -0
- package/chunks/{chunk-CCDMCZPP.js → chunk-26UABK2C.js} +1 -1
- package/chunks/{chunk-LXNEJD34.js → chunk-2FO5GFKZ.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-CLFKOZEK.js → chunk-3XULHBC7.js} +1 -1
- package/chunks/chunk-4QZADKJS.js +34 -0
- package/chunks/{chunk-E2IY465S.js → chunk-4UDHAJFV.js} +10 -10
- package/chunks/{chunk-5U27BZ72.js → chunk-55SAYASQ.js} +190 -77
- package/chunks/chunk-5HBA2Z7V.js +28 -0
- package/chunks/{chunk-ZJE7NSL3.js → chunk-5M6IDOMF.js} +34 -97
- package/chunks/{chunk-HVY356M2.js → chunk-5SQ55XJZ.js} +3 -3
- package/chunks/{chunk-EAXLGSFP.js → chunk-6GRAQNTY.js} +8 -8
- package/chunks/{chunk-K434OPES.js → chunk-6WPJRYLZ.js} +3 -3
- package/chunks/{chunk-VWPVHAMO.js → chunk-7DXHIMXL.js} +5 -1
- package/chunks/{chunk-J4TSQ5EQ.js → chunk-7NFB7LBQ.js} +8 -1
- package/chunks/{chunk-5SFOMFG4.js → chunk-7R4DPSRA.js} +36 -2
- package/chunks/{chunk-W2UIXQDL.js → chunk-7STBROEV.js} +1 -1
- package/chunks/{chunk-BMGVRZN4.js → chunk-AETEZU4U.js} +1 -1
- package/chunks/{chunk-HPDUL5MF.js → chunk-AGZWN4WV.js} +1 -1
- package/chunks/{chunk-RDJSGHZE.js → chunk-ALGGS7UH.js} +1 -38
- package/chunks/{chunk-GWHYEOV2.js → chunk-ARKANCNX.js} +2 -1
- package/chunks/{chunk-34Z3U5RQ.js → chunk-AU4R7ACM.js} +518 -114
- package/chunks/{channel-worker-supervisor-WSOAAYUO.js → chunk-B7MFJBKE.js} +67 -35
- package/chunks/{chunk-524RQP4Q.js → chunk-B7NUUEXC.js} +10 -4
- package/chunks/{chunk-MC23XKFE.js → chunk-BLPMRN4B.js} +3 -3
- package/chunks/{chunk-A3XKDTSH.js → chunk-BRRKAUGR.js} +4 -4
- package/chunks/{chunk-W3JHSWRP.js → chunk-BUPLOPUA.js} +4 -4
- package/chunks/{chunk-3VAGG5T5.js → chunk-BYOOK22F.js} +121 -16
- package/chunks/{chunk-EMDMPBJ4.js → chunk-C47ENMZJ.js} +3 -3
- package/chunks/{chunk-3AHXV67U.js → chunk-C5TVXLJZ.js} +1 -1
- package/chunks/{chunk-X6TJ3YZV.js → chunk-CGT5TQIZ.js} +159 -57
- package/chunks/{chunk-4C5BQ2D2.js → chunk-CQQD7MDG.js} +82 -12
- package/chunks/{chunk-KKNMOEZH.js → chunk-E2UVIFI2.js} +185 -398
- package/chunks/{chunk-P67PFTUT.js → chunk-EPY4ZEU6.js} +4 -4
- package/chunks/{chunk-6PESIEKJ.js → chunk-EZSRHWGS.js} +68 -6
- package/chunks/{chunk-4GORAUCN.js → chunk-F333XEAU.js} +1 -1
- package/chunks/{chunk-YLV3XXFB.js → chunk-FBU7WRZI.js} +17 -1
- package/chunks/{chunk-Q6I5QHMH.js → chunk-FGTCZJOD.js} +1 -1
- package/chunks/{chunk-LK7KUE55.js → chunk-FSA7ERJ2.js} +1 -1
- package/chunks/{chunk-B4G2WOFA.js → chunk-FTU55ZZ7.js} +3 -3
- package/chunks/{chunk-EGYZ275M.js → chunk-GCD7PEDZ.js} +4 -4
- package/chunks/{chunk-SJHDYNHF.js → chunk-GDQQRV43.js} +3 -3
- package/chunks/{chunk-3BTRNWWD.js → chunk-GOXKNSDZ.js} +1 -64
- package/chunks/{chunk-GZRTYZ2R.js → chunk-GQKWT45X.js} +154 -1
- package/chunks/chunk-GYTKQYDB.js +23 -0
- package/chunks/{chunk-YVEDCAUE.js → chunk-HGT6JR3U.js} +19 -0
- package/chunks/{chunk-N3EMS75V.js → chunk-HKM2TEF7.js} +1268 -1233
- package/chunks/chunk-IDS7MSUP.js +74 -0
- package/chunks/{chunk-PVZM22CK.js → chunk-INKAZNYC.js} +5 -5
- package/chunks/{chunk-3G7CIHVV.js → chunk-IOQ75R4R.js} +4 -4
- package/chunks/{chunk-AURZZYMD.js → chunk-IQOOJSPR.js} +4 -4
- package/chunks/{chunk-AKIVHSJR.js → chunk-J4UQXGVL.js} +111 -93
- package/chunks/{chunk-VTU57BWZ.js → chunk-JEKOCLRN.js} +1 -1
- package/chunks/{chunk-B5ORX3FG.js → chunk-JGUT3LWZ.js} +6 -1
- package/chunks/{chunk-PDZ7MBDG.js → chunk-JIQHT2O6.js} +27 -6
- package/chunks/{chunk-XUOOWUZS.js → chunk-JPAH76WA.js} +1 -1
- package/chunks/{chunk-BAPGSC7U.js → chunk-K4LG6TVJ.js} +23 -9
- package/chunks/chunk-KET3M4K4.js +493 -0
- package/chunks/{chunk-ORBGV7NJ.js → chunk-KKRTYONM.js} +6 -4
- package/chunks/{chunk-SCGXUJBT.js → chunk-KPA5QGN2.js} +3 -3
- package/chunks/{chunk-IAVB3HM3.js → chunk-KSO42X3Z.js} +13 -0
- package/chunks/{chunk-4QLQE5WJ.js → chunk-L5U3ELZX.js} +1 -1
- package/chunks/{chunk-77XJ3SWN.js → chunk-LIUEXYPL.js} +5 -5
- package/chunks/{chunk-4ZVWQHEQ.js → chunk-LQIDP6K5.js} +1 -1
- package/chunks/{chunk-34MW4KTI.js → chunk-LT5CRUA5.js} +2 -2
- package/chunks/{chunk-DC5Z3DU6.js → chunk-LXLTBIDP.js} +43 -6
- package/chunks/{chunk-VA4KQY6V.js → chunk-MEK7CQJR.js} +3 -3
- package/chunks/{chunk-KHUQZZJ6.js → chunk-MO7O5722.js} +370 -36
- package/chunks/chunk-MR3PXB6E.js +48 -0
- package/chunks/{chunk-PODM4SZ4.js → chunk-MV52C5MA.js} +5 -5
- package/chunks/{chunk-WL4L7EZH.js → chunk-OA4JVLSA.js} +27 -1
- package/chunks/{chunk-X4NKFGFJ.js → chunk-OJAMDVF5.js} +0 -15
- package/chunks/{chunk-BZIFY5TF.js → chunk-OKAIGAYW.js} +3 -3
- package/chunks/{chunk-ECNYL4AA.js → chunk-OPNPGO6D.js} +1 -1
- package/chunks/{chunk-3SJSQXNS.js → chunk-PEJWA3QQ.js} +12 -8
- package/chunks/{chunk-MXL5UP4X.js → chunk-Q6TUALBE.js} +1 -1
- package/chunks/{chunk-QYMQSECS.js → chunk-QAW7PIHT.js} +2 -2
- package/chunks/{chunk-5HOMWMCL.js → chunk-QEDYXCLG.js} +4167 -1338
- package/chunks/chunk-QNNTA7IX.js +91 -0
- package/chunks/{chunk-D2GFWEXB.js → chunk-QNT5T4Q2.js} +6 -6
- package/chunks/{chunk-CUMMSHH6.js → chunk-R5XLNDE2.js} +1 -1
- package/chunks/{chunk-LUODI7WD.js → chunk-RCEEXIOO.js} +6 -4
- package/chunks/{chunk-WQUQVGTF.js → chunk-RQWDLG6Z.js} +183 -96
- package/chunks/{chunk-XYQSMABS.js → chunk-SLCVZX6F.js} +4 -4
- package/chunks/{chunk-CEA3E3JB.js → chunk-SPJQO2CE.js} +2 -2
- package/chunks/{chunk-JSG7ZSBC.js → chunk-TQBODCFD.js} +1 -1
- package/chunks/chunk-TV6K2FB4.js +224 -0
- package/chunks/{chunk-5XUCZNSY.js → chunk-TYLOFD2U.js} +1 -1
- package/chunks/{chunk-CNEIYWSA.js → chunk-UKWAQ7AV.js} +5 -5
- package/chunks/{chunk-7PU4FYLG.js → chunk-US4YQT62.js} +4 -4
- package/chunks/{chunk-Q4YQW46J.js → chunk-UYPPCIJQ.js} +36 -18
- package/chunks/{chunk-YAUFFXDS.js → chunk-UZKG7HFG.js} +12 -11
- package/chunks/{chunk-GWLSNBG4.js → chunk-VQLRHJKL.js} +30 -26
- package/chunks/{chunk-L6P4KPHR.js → chunk-VRUHAVZS.js} +59 -39
- package/chunks/{chunk-HKMAENAO.js → chunk-W2U4RJJU.js} +8 -6
- package/chunks/{chunk-ATAKVRIF.js → chunk-WDSCTLAB.js} +7 -7
- package/chunks/{chunk-ZLXQN2QS.js → chunk-WIEO4CWB.js} +1 -1
- package/chunks/{chunk-OQ4DRIOA.js → chunk-WJOC24IW.js} +2 -2
- package/chunks/{chunk-J3JA76CF.js → chunk-WTNZ6DXB.js} +1 -1
- package/chunks/{chunk-NVYTCB5Z.js → chunk-XCR44EEA.js} +14589 -13980
- package/chunks/{chunk-TDEXZKMT.js → chunk-Y66VOBRP.js} +2 -2
- package/chunks/{chunk-CC2ITGCF.js → chunk-YHN5SUIJ.js} +49 -6
- package/chunks/{chunk-D5SKC4YG.js → chunk-ZBAROUR6.js} +41 -13
- package/chunks/{chunk-U2NNEY4R.js → chunk-ZEEVKDO7.js} +1 -1
- package/chunks/{chunk-5VXNZWGF.js → chunk-ZLOHB76C.js} +1 -1
- package/chunks/{chunk-JZETEN3Z.js → chunk-ZNCLTRNU.js} +3 -3
- package/chunks/{chunk-TO6QE22P.js → chunk-ZP4ZZJJG.js} +26 -22
- package/chunks/{chunk-UOZWKTQG.js → chunk-ZPAHLFZU.js} +2 -2
- package/chunks/{chunk-XLA62MYB.js → chunk-ZTXZ7FM4.js} +2 -2
- package/chunks/{computer-use-HM37RX6A.js → computer-use-DRETHEQF.js} +26 -26
- package/chunks/{config-utils-NV2SVGPB.js → config-utils-XSHOMMK4.js} +3 -2
- package/chunks/{contextCommand-OF5SFGH2.js → contextCommand-7YJUW23J.js} +28 -28
- package/chunks/{create-sub-session-INX7TXJI.js → create-sub-session-EAB2U5XW.js} +2 -2
- package/chunks/{create-sub-session-KPRT7ECJ.js → create-sub-session-L5HOZAEL.js} +26 -26
- package/chunks/{cron-create-AMBKGZX6.js → cron-create-GMVKSXZT.js} +4 -4
- package/chunks/{cron-delete-LRU4OJYG.js → cron-delete-VDZKUAVK.js} +4 -4
- package/chunks/{cron-list-WVP2JXER.js → cron-list-UG7C7RAR.js} +4 -4
- package/chunks/{daemon-ARHTSTXP.js → daemon-MI5HF26N.js} +603 -62
- package/chunks/{daemon-status-provider-B2UTZUJ2.js → daemon-status-provider-2D47GOJT.js} +36 -36
- package/chunks/{de-EBJN3OVN.js → de-2VCDRDGU.js} +4 -1
- package/chunks/{dist-WKPOYU7O.js → dist-IEXZC5ZR.js} +1 -1
- package/chunks/{dist-XKU3ABM5.js → dist-PQK4GCKA.js} +1 -1
- package/chunks/{dist-VHV4EVHG.js → dist-U75JK3PF.js} +1 -1
- package/chunks/{dist-R7LN5AZE.js → dist-VXO7QBON.js} +2 -2
- package/chunks/{dist-PNVLTKTL.js → dist-WH4TZSH3.js} +158 -4
- package/chunks/{dist-QYCAEZIT.js → dist-X2ABIW5R.js} +5 -1
- package/chunks/{earlyInputCapture-3VTHRC4C.js → earlyInputCapture-OJQPGCSX.js} +27 -27
- package/chunks/{edit-VNI4NJ73.js → edit-LZOAFLT2.js} +27 -27
- package/chunks/{en-5A6LA7RK.js → en-NJCA3TAA.js} +5 -1
- package/chunks/{enter-worktree-IYYBKPZT.js → enter-worktree-VL2TCGI5.js} +26 -26
- package/chunks/{enterPlanMode-GMC5FD5A.js → enterPlanMode-QGHBHZWI.js} +42 -27
- package/chunks/{environment-5HSSRMJ7.js → environment-2G5IC2EU.js} +30 -29
- package/chunks/{errors-HMFCJJ7P.js → errors-7QNQDNI2.js} +28 -28
- package/chunks/{exit-worktree-6BHCMP5G.js → exit-worktree-5V3X2MRH.js} +26 -26
- package/chunks/{exitPlanMode-CJW7G74W.js → exitPlanMode-XDPNQB4H.js} +26 -26
- package/chunks/{fast-path-FRDMDVHG.js → fast-path-NNSD4BVZ.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-RKDUWGXJ.js} +139 -76
- package/chunks/{geminiContentGenerator-J7YNZDYP.js → geminiContentGenerator-V7QGHXVF.js} +4 -4
- package/chunks/{glob-BRCSGFOT.js → glob-ZNQUUOTS.js} +28 -27
- package/chunks/{grep-EE2DUOSY.js → grep-NYIGLM7R.js} +26 -26
- package/chunks/{handleAutoUpdate-5NWTLR67.js → handleAutoUpdate-UBQ4IQXY.js} +30 -30
- package/chunks/{i18n-BASPENNQ.js → i18n-5T3S6SGP.js} +27 -27
- package/chunks/initializer-TJED246Q.js +73 -0
- package/chunks/{installationInfo-W6V4DT7W.js → installationInfo-OTEU7FKR.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-6OHS7MFJ.js +76 -0
- package/chunks/loadedSettingsAdapter-5456XIYG.js +70 -0
- package/chunks/{loop-wakeup-WX7BLWWP.js → loop-wakeup-C4EXLYVA.js} +5 -5
- package/chunks/{ls-ZB2BDP6T.js → ls-2OUTG3IZ.js} +4 -4
- package/chunks/{lsp-V5DN4YUJ.js → lsp-4VMNXZW6.js} +2 -2
- package/chunks/mcp-NOWRPFKY.js +70 -0
- package/chunks/{monitor-X5Z3H4FY.js → monitor-CVDZO3IZ.js} +26 -26
- package/chunks/nonInteractiveCli-UGI7Y43E.js +129 -0
- package/chunks/{notebook-edit-TRM2QIJK.js → notebook-edit-NWIA5TEJ.js} +27 -27
- package/chunks/{openaiContentGenerator-AAYONPMF.js → openaiContentGenerator-KJONBBJO.js} +12 -12
- package/chunks/{pidfile-D4I4FTVA.js → pidfile-L3TGXMTF.js} +27 -27
- package/chunks/{pt-2C6YCSHL.js → pt-TFZO5Y6T.js} +4 -1
- package/chunks/{qwenContentGenerator-K3HZ2H76.js → qwenContentGenerator-GXUZB5SJ.js} +28 -28
- package/chunks/{qwenOAuth2-PJQ27GSO.js → qwenOAuth2-LEYOU7RU.js} +5 -5
- package/chunks/{read-file-7SZSIZOL.js → read-file-I4OUZXTA.js} +8 -8
- package/chunks/{read-mcp-resource-SM5DA4RG.js → read-mcp-resource-JUFHCKSC.js} +2 -2
- package/chunks/{record-artifact-4XKZX3UW.js → record-artifact-DWSMBXYY.js} +2 -2
- package/chunks/{ripGrep-YNPFVCZP.js → ripGrep-XLCXANIO.js} +26 -26
- package/chunks/{ru-6BBHVZZV.js → ru-4L4LFHIT.js} +4 -1
- package/chunks/{run-qwen-serve-DMWV5N6L.js → run-qwen-serve-R6SBP6YS.js} +1232 -371
- package/chunks/{runtime-57WWRVHN.js → runtime-U3S33YUQ.js} +42 -37
- package/chunks/{scheduler-YBLGWSIL.js → scheduler-65QCIELP.js} +26 -26
- package/chunks/{send-message-F36YD6KQ.js → send-message-JZ752NWD.js} +3 -3
- package/chunks/{serve-R63NK3CV.js → serve-PSPOFCOD.js} +36 -34
- package/chunks/{server-Z22GCAXP.js → server-6P5ZB56O.js} +5561 -1377
- package/chunks/{session-HKAAI7BN.js → session-ILLOYW75.js} +298 -98
- package/chunks/{settings-3EYN66GK.js → settings-RMUJGYIK.js} +34 -32
- package/chunks/{shell-6YXINTWJ.js → shell-65GTAN5Q.js} +28 -26
- package/chunks/{skill-OO57P4X6.js → skill-L76U3YCX.js} +10 -10
- package/chunks/{spawnChannel-JD7G4VU6.js → spawnChannel-LXIGZ4EM.js} +28 -28
- package/chunks/{src-G5UPLZSZ.js → src-DWZT2X3Z.js} +87 -27
- package/chunks/{standalone-update-OB7F4JPZ.js → standalone-update-F6SRKPSD.js} +28 -28
- package/chunks/{startInteractiveUI-73EGLIIH.js → startInteractiveUI-UEJQP7S3.js} +730 -397
- package/chunks/{syntheticOutput-34H7LGA7.js → syntheticOutput-LELY6HAI.js} +3 -3
- package/chunks/{task-create-FRGOEIKY.js → task-create-QY3BIMNM.js} +8 -7
- package/chunks/{task-list-OW766BXZ.js → task-list-D2U47WBJ.js} +6 -5
- package/chunks/{task-stop-SIR5SNBN.js → task-stop-N6E5IYLH.js} +2 -2
- package/chunks/{task-update-YRA532MT.js → task-update-HJCQILLB.js} +8 -7
- package/chunks/{team-create-PECAAPXK.js → team-create-4QBZVOGN.js} +26 -26
- package/chunks/{team-delete-6OSECUZC.js → team-delete-RCWYDRF4.js} +6 -5
- package/chunks/{team-plan-approval-L6F434RY.js → team-plan-approval-BK4CIOFV.js} +26 -26
- package/chunks/{theme-manager-ZG4RY6GU.js → theme-manager-5F2IGW6E.js} +27 -27
- package/chunks/{todoWrite-YDMFEV4G.js → todoWrite-FKCGATPJ.js} +4 -4
- package/chunks/{tool-search-THVIWAPB.js → tool-search-J2ESO33H.js} +9 -9
- package/chunks/{total-session-admission-JOKNRIIA.js → total-session-admission-U4LZ5QTQ.js} +33 -33
- package/chunks/tree-sitter-YJVE2ZUK.js +2980 -0
- package/chunks/{trustedFolders-EOGT3UVS.js → trustedFolders-TIDOXCJA.js} +29 -28
- package/chunks/types-ML3TRJQ5.js +16 -0
- package/chunks/{updateCheck-2KYEYVSB.js → updateCheck-VRVR26FI.js} +29 -29
- package/chunks/{validateNonInterActiveAuth-EN6ZQSR2.js → validateNonInterActiveAuth-UGKYAVLG.js} +75 -71
- package/chunks/{version-3UEA6ZIR.js → version-7HR6VZAT.js} +1 -1
- package/chunks/{web-fetch-PAAEQKBW.js → web-fetch-QGODBB6S.js} +5 -5
- package/chunks/{workflow-QCCCMYP3.js → workflow-EDQAITEW.js} +27 -27
- package/chunks/workspace-providers-status-27UGAK77.js +73 -0
- package/chunks/workspace-registration-store-5H7577YQ.js +27 -0
- package/chunks/{workspace-registry-24QFLQYH.js → workspace-registry-F3THGAXC.js} +33 -33
- package/chunks/workspace-service-4JSAQAHP.js +86 -0
- package/chunks/workspace-skills-status-5JTWZHZU.js +72 -0
- package/chunks/{write-file-I3MUDRIE.js → write-file-UY6XCZZM.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-CObt_TK9.js} +1 -1
- package/web-shell/assets/{architectureDiagram-3BPJPVTR-B-At37J_.js → architectureDiagram-3BPJPVTR-B7aiJ6CK.js} +1 -1
- package/web-shell/assets/{blockDiagram-GPEHLZMM-B51wjcU7.js → blockDiagram-GPEHLZMM-BSK2CrID.js} +1 -1
- package/web-shell/assets/{c4Diagram-AAUBKEIU-xBK7BAwN.js → c4Diagram-AAUBKEIU-Bhx2p7T_.js} +1 -1
- package/web-shell/assets/channel-BBaLq8MV.js +1 -0
- package/web-shell/assets/{chunk-2J33WTMH-xKmLg7Yr.js → chunk-2J33WTMH-c3Hzv0Ni.js} +1 -1
- package/web-shell/assets/{chunk-4BX2VUAB-BfkdKZCM.js → chunk-4BX2VUAB-DNXaK7ZF.js} +1 -1
- package/web-shell/assets/{chunk-55IACEB6-DT713sZf.js → chunk-55IACEB6-BXjvDj_i.js} +1 -1
- package/web-shell/assets/{chunk-727SXJPM-CYEeAamv.js → chunk-727SXJPM-B6CaKFp-.js} +1 -1
- package/web-shell/assets/{chunk-AQP2D5EJ-DBN-5CFd.js → chunk-AQP2D5EJ-tij6Mz9B.js} +1 -1
- package/web-shell/assets/{chunk-FMBD7UC4-CGZKk4PH.js → chunk-FMBD7UC4-DdlsGk2h.js} +1 -1
- package/web-shell/assets/{chunk-ND2GUHAM-qQbC2O-y.js → chunk-ND2GUHAM-CdgGZSHE.js} +1 -1
- package/web-shell/assets/{chunk-QZHKN3VN-B3zeXwsX.js → chunk-QZHKN3VN-D8oJn1C0.js} +1 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-B2ZK6sWE.js +1 -0
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-B2ZK6sWE.js +1 -0
- package/web-shell/assets/{cose-bilkent-S5V4N54A-BKsl1Wvy.js → cose-bilkent-S5V4N54A-BUVmNp1Y.js} +1 -1
- package/web-shell/assets/{dagre-BM42HDAG-CuuuLiBK.js → dagre-BM42HDAG-CO4q310O.js} +1 -1
- package/web-shell/assets/{diagram-2AECGRRQ-CG4_eKiV.js → diagram-2AECGRRQ-C6gFvWkg.js} +1 -1
- package/web-shell/assets/{diagram-5GNKFQAL-DSFTmZB1.js → diagram-5GNKFQAL-NG2I_c0h.js} +1 -1
- package/web-shell/assets/{diagram-KO2AKTUF-BxwlEHn8.js → diagram-KO2AKTUF-DFKMS6I9.js} +1 -1
- package/web-shell/assets/{diagram-LMA3HP47-BUAg-jMG.js → diagram-LMA3HP47-BiElfsfP.js} +1 -1
- package/web-shell/assets/{diagram-OG6HWLK6-BFM2jlO5.js → diagram-OG6HWLK6-zLWDYUqu.js} +1 -1
- package/web-shell/assets/{erDiagram-TEJ5UH35-CerbFPa2.js → erDiagram-TEJ5UH35-DoVaazhK.js} +1 -1
- package/web-shell/assets/{flowDiagram-I6XJVG4X-BNeZz5Zz.js → flowDiagram-I6XJVG4X-0RLz-mXg.js} +1 -1
- package/web-shell/assets/{ganttDiagram-6RSMTGT7-CTOogLaM.js → ganttDiagram-6RSMTGT7-C-eX1A39.js} +3 -3
- package/web-shell/assets/{gitGraphDiagram-PVQCEYII-yxSFkXPj.js → gitGraphDiagram-PVQCEYII-BauQu1Bu.js} +1 -1
- package/web-shell/assets/index-3uAT3ehO.css +5 -0
- package/web-shell/assets/index-CVHa2QH7.js +3 -0
- package/web-shell/assets/index-D1KigWat.js +1128 -0
- package/web-shell/assets/{infoDiagram-5YYISTIA-DYdAUevm.js → infoDiagram-5YYISTIA-C800cFvZ.js} +1 -1
- package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-CNuijZ90.js → ishikawaDiagram-YF4QCWOH-CFK1Jk6e.js} +1 -1
- package/web-shell/assets/{journeyDiagram-JHISSGLW-BTyiuonf.js → journeyDiagram-JHISSGLW-Cjx0WAC4.js} +1 -1
- package/web-shell/assets/{kanban-definition-UN3LZRKU-DPJo0Uow.js → kanban-definition-UN3LZRKU-DWMDHbiv.js} +1 -1
- package/web-shell/assets/{linear-C8wKCbIC.js → linear-vpW4FrZs.js} +1 -1
- package/web-shell/assets/{mermaid.core-BV5o7nW5.js → mermaid.core-DsHRUnDd.js} +5 -5
- package/web-shell/assets/{mindmap-definition-RKZ34NQL-BtLcBmSt.js → mindmap-definition-RKZ34NQL-D3Eb1cAK.js} +1 -1
- package/web-shell/assets/{pieDiagram-4H26LBE5-C22J7A9Q.js → pieDiagram-4H26LBE5-Cr2-6sWt.js} +1 -1
- package/web-shell/assets/{quadrantDiagram-W4KKPZXB-DSL10wiL.js → quadrantDiagram-W4KKPZXB-Yd7yUgVp.js} +1 -1
- package/web-shell/assets/{requirementDiagram-4Y6WPE33-feqh0UpX.js → requirementDiagram-4Y6WPE33-BE6SprL8.js} +1 -1
- package/web-shell/assets/{sankeyDiagram-5OEKKPKP-Z4OVaWaZ.js → sankeyDiagram-5OEKKPKP-DzkuMK8d.js} +1 -1
- package/web-shell/assets/{sequenceDiagram-3UESZ5HK-DIluIcb1.js → sequenceDiagram-3UESZ5HK-wD9A3Dhi.js} +1 -1
- package/web-shell/assets/{stateDiagram-AJRCARHV-hlhnuoYH.js → stateDiagram-AJRCARHV-BOp5q1Nm.js} +1 -1
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-BDsWUmPG.js +1 -0
- package/web-shell/assets/{timeline-definition-PNZ67QCA-Dqf_CqgL.js → timeline-definition-PNZ67QCA-Btc08sUA.js} +1 -1
- package/web-shell/assets/{vennDiagram-CIIHVFJN-DD2QhaTX.js → vennDiagram-CIIHVFJN-Bv6upsOA.js} +1 -1
- package/web-shell/assets/{wardley-L42UT6IY-B2uI85U_.js → wardley-L42UT6IY-D-XamnCK.js} +1 -1
- package/web-shell/assets/{wardleyDiagram-YWT4CUSO-U1aJX71g.js → wardleyDiagram-YWT4CUSO-BbP_5Wfp.js} +1 -1
- package/web-shell/assets/{xychartDiagram-2RQKCTM6-C0ODHUee.js → xychartDiagram-2RQKCTM6-CO5Hh28b.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
|
}
|
|
@@ -1004,6 +1080,10 @@ var DaemonChannelBridge = class extends EventEmitter2 {
|
|
|
1004
1080
|
case "tool_call_update": {
|
|
1005
1081
|
const toolCallId = getString(update["toolCallId"]);
|
|
1006
1082
|
const kind = getString(update["kind"]);
|
|
1083
|
+
const meta = isRecord(update["_meta"]) ? update["_meta"] : void 0;
|
|
1084
|
+
if (!kind && toolCallId && getString(update["status"]) === "in_progress" && meta?.["shellProgress"] !== void 0) {
|
|
1085
|
+
break;
|
|
1086
|
+
}
|
|
1007
1087
|
if (!toolCallId || !kind) {
|
|
1008
1088
|
this.emitProtocolError(`Malformed daemon ${type} event`, update);
|
|
1009
1089
|
break;
|
|
@@ -1123,14 +1203,26 @@ var DaemonChannelBridge = class extends EventEmitter2 {
|
|
|
1123
1203
|
handleSessionDied(sessionId, data) {
|
|
1124
1204
|
this.dropSession(sessionId, this.getStringField(data, "reason", "session_died"));
|
|
1125
1205
|
}
|
|
1126
|
-
dropSession(sessionId, reason) {
|
|
1127
|
-
|
|
1206
|
+
dropSession(sessionId, reason, releaseClient = true) {
|
|
1207
|
+
const session = this.removeSessionBinding(sessionId);
|
|
1208
|
+
if (!session)
|
|
1128
1209
|
return;
|
|
1210
|
+
if (releaseClient) {
|
|
1211
|
+
void this.releaseSessionClient(session).catch((error) => {
|
|
1212
|
+
this.lastError = error;
|
|
1213
|
+
});
|
|
1129
1214
|
}
|
|
1215
|
+
this.emit("sessionDied", { sessionId, reason });
|
|
1216
|
+
}
|
|
1217
|
+
removeSessionBinding(sessionId) {
|
|
1218
|
+
const session = this.sessions.get(sessionId);
|
|
1219
|
+
if (!session)
|
|
1220
|
+
return void 0;
|
|
1130
1221
|
this.resolveTurnBarrier(sessionId);
|
|
1131
1222
|
this.eventControllers.get(sessionId)?.abort();
|
|
1132
1223
|
this.eventControllers.delete(sessionId);
|
|
1133
1224
|
this.sessions.delete(sessionId);
|
|
1225
|
+
this.sessionBindingTokens.delete(sessionId);
|
|
1134
1226
|
this.abortActivePrompts(sessionId);
|
|
1135
1227
|
this.activePrompts.delete(sessionId);
|
|
1136
1228
|
this.availableCommandsBySession.delete(sessionId);
|
|
@@ -1147,7 +1239,7 @@ var DaemonChannelBridge = class extends EventEmitter2 {
|
|
|
1147
1239
|
this.respondedRequestToSession.delete(requestId);
|
|
1148
1240
|
}
|
|
1149
1241
|
}
|
|
1150
|
-
|
|
1242
|
+
return session;
|
|
1151
1243
|
}
|
|
1152
1244
|
getStringField(data, field, fallback) {
|
|
1153
1245
|
return isRecord(data) && typeof data[field] === "string" ? data[field] : fallback;
|
|
@@ -1295,7 +1387,7 @@ var BlockStreamer = class {
|
|
|
1295
1387
|
|
|
1296
1388
|
// packages/channels/base/dist/ChannelBase.js
|
|
1297
1389
|
init_esbuild_shims();
|
|
1298
|
-
import { basename, join as
|
|
1390
|
+
import { basename, join as join5 } from "node:path";
|
|
1299
1391
|
|
|
1300
1392
|
// packages/channels/base/dist/GroupGate.js
|
|
1301
1393
|
init_esbuild_shims();
|
|
@@ -1770,7 +1862,8 @@ __name(generateCode, "generateCode");
|
|
|
1770
1862
|
|
|
1771
1863
|
// packages/channels/base/dist/SessionRouter.js
|
|
1772
1864
|
init_esbuild_shims();
|
|
1773
|
-
import { existsSync as existsSync3, readFileSync as readFileSync3,
|
|
1865
|
+
import { chmodSync as chmodSync2, existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync3, renameSync as renameSync2, rmSync, unlinkSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
1866
|
+
import { dirname as dirname2, join as join4 } from "node:path";
|
|
1774
1867
|
import process2 from "node:process";
|
|
1775
1868
|
var SessionRouter = class {
|
|
1776
1869
|
static {
|
|
@@ -1784,17 +1877,22 @@ var SessionRouter = class {
|
|
|
1784
1877
|
// session ID → cwd
|
|
1785
1878
|
creatingSessions = /* @__PURE__ */ new Map();
|
|
1786
1879
|
sessionLoadWindows = /* @__PURE__ */ new Set();
|
|
1880
|
+
liveSessionIds = /* @__PURE__ */ new Set();
|
|
1881
|
+
routeTokens = /* @__PURE__ */ new Map();
|
|
1882
|
+
lifecycleGeneration = 0;
|
|
1787
1883
|
bridge;
|
|
1788
1884
|
defaultCwd;
|
|
1789
1885
|
defaultScope;
|
|
1790
1886
|
channelScopes = /* @__PURE__ */ new Map();
|
|
1791
1887
|
channelApprovalModes = /* @__PURE__ */ new Map();
|
|
1792
1888
|
persistPath;
|
|
1793
|
-
|
|
1889
|
+
recoveryMode;
|
|
1890
|
+
constructor(bridge, defaultCwd, scope = "user", persistPath, options = {}) {
|
|
1794
1891
|
this.bridge = bridge;
|
|
1795
1892
|
this.defaultCwd = defaultCwd;
|
|
1796
1893
|
this.defaultScope = scope;
|
|
1797
1894
|
this.persistPath = persistPath;
|
|
1895
|
+
this.recoveryMode = options.recoveryMode ?? "eager";
|
|
1798
1896
|
}
|
|
1799
1897
|
/** Replace the bridge instance (used after crash recovery restart). */
|
|
1800
1898
|
setBridge(bridge) {
|
|
@@ -1829,60 +1927,168 @@ var SessionRouter = class {
|
|
|
1829
1927
|
}
|
|
1830
1928
|
async resolve(channelName, senderId, chatId, threadId, cwd, isGroup, options) {
|
|
1831
1929
|
const key = this.routingKey(channelName, senderId, chatId, options?.routingThreadId ?? threadId);
|
|
1832
|
-
|
|
1930
|
+
const input = {
|
|
1931
|
+
channelName,
|
|
1932
|
+
senderId,
|
|
1933
|
+
chatId,
|
|
1934
|
+
threadId,
|
|
1935
|
+
cwd: cwd || this.defaultCwd,
|
|
1936
|
+
isGroup
|
|
1937
|
+
};
|
|
1938
|
+
let failedWaits = 0;
|
|
1833
1939
|
for (; ; ) {
|
|
1834
1940
|
const existing = this.toSession.get(key);
|
|
1835
|
-
if (existing) {
|
|
1941
|
+
if (existing && this.isLive(existing)) {
|
|
1836
1942
|
this.promoteTargetToGroup(existing, isGroup);
|
|
1837
1943
|
return existing;
|
|
1838
1944
|
}
|
|
1839
1945
|
const creating = this.creatingSessions.get(key);
|
|
1840
1946
|
if (creating) {
|
|
1841
1947
|
try {
|
|
1842
|
-
const sessionId = await creating;
|
|
1948
|
+
const sessionId = await creating.promise;
|
|
1949
|
+
try {
|
|
1950
|
+
this.assertOperationResultCurrent(key, sessionId, creating);
|
|
1951
|
+
} catch (error) {
|
|
1952
|
+
this.scheduleDiscardInvalidatedSession(sessionId, creating);
|
|
1953
|
+
throw error;
|
|
1954
|
+
}
|
|
1843
1955
|
this.promoteTargetToGroup(sessionId, isGroup);
|
|
1844
1956
|
return sessionId;
|
|
1845
|
-
} catch (
|
|
1957
|
+
} catch (error) {
|
|
1958
|
+
if (creating.invalidationError) {
|
|
1959
|
+
throw creating.invalidationError;
|
|
1960
|
+
}
|
|
1846
1961
|
if (this.creatingSessions.get(key) === creating) {
|
|
1847
1962
|
this.creatingSessions.delete(key);
|
|
1848
1963
|
}
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1964
|
+
this.releaseRouteToken(key, creating);
|
|
1965
|
+
failedWaits++;
|
|
1966
|
+
if (failedWaits > 3)
|
|
1967
|
+
throw error;
|
|
1853
1968
|
continue;
|
|
1854
1969
|
}
|
|
1855
1970
|
}
|
|
1856
|
-
const
|
|
1857
|
-
|
|
1858
|
-
|
|
1971
|
+
const operation = this.createSessionOperation(key, {
|
|
1972
|
+
channelName: input.channelName,
|
|
1973
|
+
senderId: input.senderId,
|
|
1974
|
+
chatId: input.chatId,
|
|
1975
|
+
threadId: input.threadId,
|
|
1976
|
+
isGroup: input.isGroup
|
|
1977
|
+
}, (currentOperation) => existing ? this.loadOrReplaceSession(key, existing, input, currentOperation) : this.createAndStoreSession(key, input, currentOperation));
|
|
1978
|
+
this.creatingSessions.set(key, operation);
|
|
1979
|
+
try {
|
|
1980
|
+
const sessionId = await operation.promise;
|
|
1859
1981
|
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);
|
|
1982
|
+
this.assertOperationResultCurrent(key, sessionId, operation);
|
|
1983
|
+
} catch (error) {
|
|
1984
|
+
this.scheduleDiscardInvalidatedSession(sessionId, operation);
|
|
1985
|
+
throw error;
|
|
1874
1986
|
}
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
try {
|
|
1878
|
-
return await created;
|
|
1987
|
+
this.promoteTargetToGroup(sessionId, isGroup);
|
|
1988
|
+
return sessionId;
|
|
1879
1989
|
} finally {
|
|
1880
|
-
if (this.creatingSessions.get(key) ===
|
|
1990
|
+
if (this.creatingSessions.get(key) === operation) {
|
|
1881
1991
|
this.creatingSessions.delete(key);
|
|
1882
1992
|
}
|
|
1993
|
+
this.releaseRouteToken(key, operation);
|
|
1883
1994
|
}
|
|
1884
1995
|
}
|
|
1885
1996
|
}
|
|
1997
|
+
isLive(sessionId) {
|
|
1998
|
+
return this.recoveryMode === "eager" || this.liveSessionIds.has(sessionId);
|
|
1999
|
+
}
|
|
2000
|
+
async createAndStoreSession(key, input, operation) {
|
|
2001
|
+
const loadWindow = this.beginSessionLoad();
|
|
2002
|
+
try {
|
|
2003
|
+
const sessionId = await this.createLiveSession(input.cwd, loadWindow, key, this.sessionOptions(input.channelName), operation);
|
|
2004
|
+
try {
|
|
2005
|
+
this.assertOperationCurrent(operation);
|
|
2006
|
+
} catch (error) {
|
|
2007
|
+
this.scheduleDiscardInvalidatedSession(sessionId, operation);
|
|
2008
|
+
throw error;
|
|
2009
|
+
}
|
|
2010
|
+
this.toSession.set(key, sessionId);
|
|
2011
|
+
this.toTarget.set(sessionId, {
|
|
2012
|
+
channelName: input.channelName,
|
|
2013
|
+
senderId: input.senderId,
|
|
2014
|
+
chatId: input.chatId,
|
|
2015
|
+
threadId: input.threadId,
|
|
2016
|
+
isGroup: input.isGroup
|
|
2017
|
+
});
|
|
2018
|
+
this.toCwd.set(sessionId, input.cwd);
|
|
2019
|
+
this.liveSessionIds.add(sessionId);
|
|
2020
|
+
this.persist();
|
|
2021
|
+
return sessionId;
|
|
2022
|
+
} finally {
|
|
2023
|
+
this.endSessionLoad(loadWindow);
|
|
2024
|
+
}
|
|
2025
|
+
}
|
|
2026
|
+
async loadOrReplaceSession(key, savedSessionId, input, operation) {
|
|
2027
|
+
const savedCwd = this.toCwd.get(savedSessionId) ?? input.cwd;
|
|
2028
|
+
const loadWindow = this.beginSessionLoad();
|
|
2029
|
+
try {
|
|
2030
|
+
try {
|
|
2031
|
+
const loadedSessionId = await this.bridge.loadSession(savedSessionId, savedCwd, this.sessionOptions(input.channelName), operation);
|
|
2032
|
+
try {
|
|
2033
|
+
this.assertOperationCurrent(operation);
|
|
2034
|
+
if (this.toSession.get(key) !== savedSessionId) {
|
|
2035
|
+
this.invalidateOperation(operation);
|
|
2036
|
+
this.assertOperationCurrent(operation);
|
|
2037
|
+
}
|
|
2038
|
+
} catch (error) {
|
|
2039
|
+
this.scheduleDiscardInvalidatedSession(loadedSessionId, operation);
|
|
2040
|
+
throw error;
|
|
2041
|
+
}
|
|
2042
|
+
if (typeof loadedSessionId !== "string" || loadedSessionId.length === 0 || loadWindow.delete(loadedSessionId)) {
|
|
2043
|
+
throw new Error("Invalid or dead restored session ID");
|
|
2044
|
+
}
|
|
2045
|
+
if (loadedSessionId !== savedSessionId) {
|
|
2046
|
+
const target = this.toTarget.get(savedSessionId);
|
|
2047
|
+
this.deleteByKey(key);
|
|
2048
|
+
this.toSession.set(key, loadedSessionId);
|
|
2049
|
+
if (target)
|
|
2050
|
+
this.toTarget.set(loadedSessionId, target);
|
|
2051
|
+
this.toCwd.set(loadedSessionId, savedCwd);
|
|
2052
|
+
this.persist();
|
|
2053
|
+
}
|
|
2054
|
+
this.liveSessionIds.add(loadedSessionId);
|
|
2055
|
+
return loadedSessionId;
|
|
2056
|
+
} catch (loadError) {
|
|
2057
|
+
this.assertOperationCurrent(operation);
|
|
2058
|
+
try {
|
|
2059
|
+
const replacement = await this.createLiveSession(input.cwd, loadWindow, key, this.sessionOptions(input.channelName), operation);
|
|
2060
|
+
try {
|
|
2061
|
+
this.assertOperationCurrent(operation);
|
|
2062
|
+
} catch (error) {
|
|
2063
|
+
this.scheduleDiscardInvalidatedSession(replacement, operation);
|
|
2064
|
+
throw error;
|
|
2065
|
+
}
|
|
2066
|
+
this.deleteByKey(key);
|
|
2067
|
+
this.toSession.set(key, replacement);
|
|
2068
|
+
this.toTarget.set(replacement, {
|
|
2069
|
+
channelName: input.channelName,
|
|
2070
|
+
senderId: input.senderId,
|
|
2071
|
+
chatId: input.chatId,
|
|
2072
|
+
threadId: input.threadId,
|
|
2073
|
+
isGroup: input.isGroup
|
|
2074
|
+
});
|
|
2075
|
+
this.toCwd.set(replacement, input.cwd);
|
|
2076
|
+
this.liveSessionIds.add(replacement);
|
|
2077
|
+
this.persist();
|
|
2078
|
+
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)}
|
|
2079
|
+
`);
|
|
2080
|
+
return replacement;
|
|
2081
|
+
} catch (createError) {
|
|
2082
|
+
this.assertOperationCurrent(operation);
|
|
2083
|
+
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)})
|
|
2084
|
+
`);
|
|
2085
|
+
throw createError;
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
2088
|
+
} finally {
|
|
2089
|
+
this.endSessionLoad(loadWindow);
|
|
2090
|
+
}
|
|
2091
|
+
}
|
|
1886
2092
|
getTarget(sessionId) {
|
|
1887
2093
|
return this.toTarget.get(sessionId);
|
|
1888
2094
|
}
|
|
@@ -1912,6 +2118,7 @@ var SessionRouter = class {
|
|
|
1912
2118
|
const scope = this.channelScopes.get(channelName) || this.defaultScope;
|
|
1913
2119
|
if (chatId) {
|
|
1914
2120
|
const key = this.routingKey(channelName, senderId, chatId, threadId);
|
|
2121
|
+
this.invalidateRouteOperation(key);
|
|
1915
2122
|
const sessionId = this.deleteByKey(key);
|
|
1916
2123
|
if (sessionId)
|
|
1917
2124
|
removedIds.push(sessionId);
|
|
@@ -1921,11 +2128,17 @@ var SessionRouter = class {
|
|
|
1921
2128
|
for (const [k, mappedSessionId] of [...this.toSession.entries()]) {
|
|
1922
2129
|
const target = this.toTarget.get(mappedSessionId);
|
|
1923
2130
|
if (target?.channelName === channelName && target.senderId === senderId) {
|
|
2131
|
+
this.invalidateRouteOperation(k);
|
|
1924
2132
|
const sessionId = this.deleteByKey(k);
|
|
1925
2133
|
if (sessionId)
|
|
1926
2134
|
removedIds.push(sessionId);
|
|
1927
2135
|
}
|
|
1928
2136
|
}
|
|
2137
|
+
for (const [key, operation] of [...this.creatingSessions]) {
|
|
2138
|
+
if (operation.target.channelName === channelName && operation.target.senderId === senderId) {
|
|
2139
|
+
this.invalidateRouteOperation(key);
|
|
2140
|
+
}
|
|
2141
|
+
}
|
|
1929
2142
|
}
|
|
1930
2143
|
if (removedIds.length > 0)
|
|
1931
2144
|
this.persist();
|
|
@@ -1936,6 +2149,7 @@ var SessionRouter = class {
|
|
|
1936
2149
|
let removed = false;
|
|
1937
2150
|
for (const [key, mappedSessionId] of [...this.toSession.entries()]) {
|
|
1938
2151
|
if (mappedSessionId === sessionId) {
|
|
2152
|
+
this.invalidateRouteOperation(key);
|
|
1939
2153
|
this.toSession.delete(key);
|
|
1940
2154
|
removed = true;
|
|
1941
2155
|
}
|
|
@@ -1946,6 +2160,7 @@ var SessionRouter = class {
|
|
|
1946
2160
|
if (this.toCwd.delete(sessionId)) {
|
|
1947
2161
|
removed = true;
|
|
1948
2162
|
}
|
|
2163
|
+
this.liveSessionIds.delete(sessionId);
|
|
1949
2164
|
if (!removed && this.sessionLoadWindows.size > 0) {
|
|
1950
2165
|
for (const loadWindow of this.sessionLoadWindows) {
|
|
1951
2166
|
loadWindow.add(sessionId);
|
|
@@ -1956,6 +2171,17 @@ var SessionRouter = class {
|
|
|
1956
2171
|
}
|
|
1957
2172
|
return removed;
|
|
1958
2173
|
}
|
|
2174
|
+
handleSessionDied(sessionId) {
|
|
2175
|
+
if (this.recoveryMode === "eager") {
|
|
2176
|
+
return this.removeSessionId(sessionId);
|
|
2177
|
+
}
|
|
2178
|
+
const known = this.toTarget.has(sessionId);
|
|
2179
|
+
this.liveSessionIds.delete(sessionId);
|
|
2180
|
+
for (const loadWindow of this.sessionLoadWindows) {
|
|
2181
|
+
loadWindow.add(sessionId);
|
|
2182
|
+
}
|
|
2183
|
+
return known;
|
|
2184
|
+
}
|
|
1959
2185
|
deleteByKey(key) {
|
|
1960
2186
|
const sessionId = this.toSession.get(key);
|
|
1961
2187
|
if (!sessionId)
|
|
@@ -1963,6 +2189,7 @@ var SessionRouter = class {
|
|
|
1963
2189
|
this.toSession.delete(key);
|
|
1964
2190
|
this.toTarget.delete(sessionId);
|
|
1965
2191
|
this.toCwd.delete(sessionId);
|
|
2192
|
+
this.liveSessionIds.delete(sessionId);
|
|
1966
2193
|
return sessionId;
|
|
1967
2194
|
}
|
|
1968
2195
|
promoteTargetToGroup(sessionId, isGroup) {
|
|
@@ -1985,45 +2212,69 @@ var SessionRouter = class {
|
|
|
1985
2212
|
}
|
|
1986
2213
|
return entries;
|
|
1987
2214
|
}
|
|
2215
|
+
restoreRoutes() {
|
|
2216
|
+
if (this.recoveryMode !== "lazy") {
|
|
2217
|
+
throw new Error("restoreRoutes requires lazy recovery mode");
|
|
2218
|
+
}
|
|
2219
|
+
const persisted = this.readPersistedEntries();
|
|
2220
|
+
if (!persisted)
|
|
2221
|
+
return { restored: 0, dropped: 0 };
|
|
2222
|
+
this.dispose();
|
|
2223
|
+
let restored = 0;
|
|
2224
|
+
for (const [key, entry] of Object.entries(persisted.entries)) {
|
|
2225
|
+
this.toSession.set(key, entry.sessionId);
|
|
2226
|
+
this.toTarget.set(entry.sessionId, entry.target);
|
|
2227
|
+
this.toCwd.set(entry.sessionId, entry.cwd);
|
|
2228
|
+
restored++;
|
|
2229
|
+
}
|
|
2230
|
+
if (persisted.dropped > 0)
|
|
2231
|
+
this.persist();
|
|
2232
|
+
return { restored, dropped: persisted.dropped };
|
|
2233
|
+
}
|
|
1988
2234
|
/**
|
|
1989
2235
|
* Restore session mappings from a previous bridge.
|
|
1990
2236
|
* Called after bridge restart — attempts loadSession for each saved mapping.
|
|
1991
2237
|
* Failed loads are dropped (new session on next message).
|
|
1992
2238
|
*/
|
|
1993
2239
|
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
|
-
`);
|
|
2240
|
+
const persisted = this.readPersistedEntries();
|
|
2241
|
+
if (!persisted)
|
|
2005
2242
|
return { restored: 0, failed: 0 };
|
|
2006
|
-
|
|
2243
|
+
const entries = persisted.entries;
|
|
2244
|
+
const restoreGeneration = this.lifecycleGeneration;
|
|
2007
2245
|
let restored = 0;
|
|
2008
2246
|
let failed = 0;
|
|
2009
|
-
let changed =
|
|
2247
|
+
let changed = persisted.dropped > 0;
|
|
2010
2248
|
const reservations = /* @__PURE__ */ new Map();
|
|
2249
|
+
for (const key of persisted.droppedKeys) {
|
|
2250
|
+
this.deleteByKey(key);
|
|
2251
|
+
}
|
|
2011
2252
|
for (const key of Object.keys(entries)) {
|
|
2012
2253
|
this.deleteByKey(key);
|
|
2013
2254
|
const reservation = this.createSessionReservation();
|
|
2014
2255
|
reservation.promise.catch(() => void 0);
|
|
2015
|
-
this.
|
|
2016
|
-
|
|
2256
|
+
const operation = this.createSessionOperation(key, entries[key].target, () => reservation.promise);
|
|
2257
|
+
operation.promise.catch(() => void 0);
|
|
2258
|
+
this.creatingSessions.set(key, operation);
|
|
2259
|
+
reservations.set(key, { reservation, operation });
|
|
2017
2260
|
}
|
|
2018
2261
|
const loadWindow = this.beginSessionLoad();
|
|
2019
2262
|
try {
|
|
2020
2263
|
for (const [key, entry] of Object.entries(entries)) {
|
|
2021
|
-
const
|
|
2022
|
-
if (!
|
|
2264
|
+
const reserved = reservations.get(key);
|
|
2265
|
+
if (!reserved)
|
|
2023
2266
|
continue;
|
|
2267
|
+
const { reservation, operation } = reserved;
|
|
2024
2268
|
try {
|
|
2269
|
+
this.assertOperationCurrent(operation);
|
|
2025
2270
|
const options = this.sessionOptions(entry.target.channelName);
|
|
2026
|
-
const sessionId =
|
|
2271
|
+
const sessionId = await this.bridge.loadSession(entry.sessionId, entry.cwd, options, operation);
|
|
2272
|
+
try {
|
|
2273
|
+
this.assertOperationCurrent(operation);
|
|
2274
|
+
} catch (error) {
|
|
2275
|
+
this.scheduleDiscardInvalidatedSession(sessionId, operation);
|
|
2276
|
+
throw error;
|
|
2277
|
+
}
|
|
2027
2278
|
if (typeof sessionId !== "string" || sessionId.length === 0) {
|
|
2028
2279
|
throw new Error("Invalid restored session ID");
|
|
2029
2280
|
}
|
|
@@ -2046,26 +2297,36 @@ var SessionRouter = class {
|
|
|
2046
2297
|
failed++;
|
|
2047
2298
|
changed = true;
|
|
2048
2299
|
} finally {
|
|
2049
|
-
if (this.creatingSessions.get(key) ===
|
|
2300
|
+
if (this.creatingSessions.get(key) === operation) {
|
|
2050
2301
|
this.creatingSessions.delete(key);
|
|
2051
2302
|
}
|
|
2303
|
+
this.releaseRouteToken(key, operation);
|
|
2052
2304
|
}
|
|
2053
2305
|
}
|
|
2054
2306
|
} finally {
|
|
2055
2307
|
this.endSessionLoad(loadWindow);
|
|
2056
2308
|
}
|
|
2057
|
-
if (changed) {
|
|
2309
|
+
if (changed && restoreGeneration === this.lifecycleGeneration) {
|
|
2058
2310
|
this.persist();
|
|
2059
2311
|
}
|
|
2060
2312
|
return { restored, failed };
|
|
2061
2313
|
}
|
|
2062
|
-
|
|
2063
|
-
|
|
2314
|
+
dispose() {
|
|
2315
|
+
this.lifecycleGeneration++;
|
|
2316
|
+
for (const operation of this.creatingSessions.values()) {
|
|
2317
|
+
this.invalidateOperation(operation);
|
|
2318
|
+
}
|
|
2064
2319
|
this.toSession.clear();
|
|
2065
2320
|
this.toTarget.clear();
|
|
2066
2321
|
this.toCwd.clear();
|
|
2067
2322
|
this.creatingSessions.clear();
|
|
2068
2323
|
this.sessionLoadWindows.clear();
|
|
2324
|
+
this.liveSessionIds.clear();
|
|
2325
|
+
this.routeTokens.clear();
|
|
2326
|
+
}
|
|
2327
|
+
/** Clear in-memory state and delete persist file. Used on clean shutdown. */
|
|
2328
|
+
clearAll() {
|
|
2329
|
+
this.dispose();
|
|
2069
2330
|
if (this.persistPath && existsSync3(this.persistPath)) {
|
|
2070
2331
|
try {
|
|
2071
2332
|
unlinkSync(this.persistPath);
|
|
@@ -2073,30 +2334,105 @@ var SessionRouter = class {
|
|
|
2073
2334
|
}
|
|
2074
2335
|
}
|
|
2075
2336
|
}
|
|
2337
|
+
readPersistedEntries() {
|
|
2338
|
+
const persistPath = this.persistPath;
|
|
2339
|
+
if (!persistPath || !existsSync3(persistPath))
|
|
2340
|
+
return void 0;
|
|
2341
|
+
let parsed;
|
|
2342
|
+
try {
|
|
2343
|
+
parsed = JSON.parse(readFileSync3(persistPath, "utf-8"));
|
|
2344
|
+
} catch (error) {
|
|
2345
|
+
const quarantinePath = `${persistPath}.corrupt-${Date.now()}`;
|
|
2346
|
+
try {
|
|
2347
|
+
renameSync2(persistPath, quarantinePath);
|
|
2348
|
+
} catch {
|
|
2349
|
+
}
|
|
2350
|
+
process2.stderr.write(`[SessionRouter] Corrupted persist file at ${sanitizeLogText(persistPath, 1024)}: ${sanitizeLogText(error instanceof Error ? error.message : String(error), 512)}
|
|
2351
|
+
`);
|
|
2352
|
+
return void 0;
|
|
2353
|
+
}
|
|
2354
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
2355
|
+
const quarantinePath = `${persistPath}.corrupt-${Date.now()}`;
|
|
2356
|
+
try {
|
|
2357
|
+
renameSync2(persistPath, quarantinePath);
|
|
2358
|
+
} catch {
|
|
2359
|
+
}
|
|
2360
|
+
process2.stderr.write(`[SessionRouter] Invalid route store at ${sanitizeLogText(persistPath, 1024)}: expected an object
|
|
2361
|
+
`);
|
|
2362
|
+
return void 0;
|
|
2363
|
+
}
|
|
2364
|
+
const entries = {};
|
|
2365
|
+
const droppedKeys = [];
|
|
2366
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
2367
|
+
if (this.isPersistedEntry(value))
|
|
2368
|
+
entries[key] = value;
|
|
2369
|
+
else
|
|
2370
|
+
droppedKeys.push(key);
|
|
2371
|
+
}
|
|
2372
|
+
return { entries, dropped: droppedKeys.length, droppedKeys };
|
|
2373
|
+
}
|
|
2374
|
+
isPersistedEntry(value) {
|
|
2375
|
+
if (typeof value !== "object" || value === null)
|
|
2376
|
+
return false;
|
|
2377
|
+
const entry = value;
|
|
2378
|
+
const target = entry["target"];
|
|
2379
|
+
if (typeof target !== "object" || target === null)
|
|
2380
|
+
return false;
|
|
2381
|
+
const typedTarget = target;
|
|
2382
|
+
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");
|
|
2383
|
+
}
|
|
2076
2384
|
persist() {
|
|
2077
2385
|
if (!this.persistPath)
|
|
2078
2386
|
return;
|
|
2079
2387
|
const data = {};
|
|
2080
2388
|
for (const [key, sessionId] of this.toSession) {
|
|
2081
2389
|
const target = this.toTarget.get(sessionId);
|
|
2082
|
-
if (target)
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
}
|
|
2390
|
+
if (!target)
|
|
2391
|
+
continue;
|
|
2392
|
+
data[key] = {
|
|
2393
|
+
sessionId,
|
|
2394
|
+
target,
|
|
2395
|
+
cwd: this.toCwd.get(sessionId) ?? this.defaultCwd
|
|
2396
|
+
};
|
|
2089
2397
|
}
|
|
2398
|
+
const dir = dirname2(this.persistPath);
|
|
2399
|
+
const tempPath = join4(dir, `${Date.now()}-${process2.pid}-${Math.random().toString(16).slice(2)}.tmp`);
|
|
2090
2400
|
try {
|
|
2091
|
-
|
|
2092
|
-
|
|
2401
|
+
mkdirSync3(dir, { recursive: true, mode: 448 });
|
|
2402
|
+
try {
|
|
2403
|
+
chmodSync2(dir, 448);
|
|
2404
|
+
} catch {
|
|
2405
|
+
}
|
|
2406
|
+
writeFileSync3(tempPath, JSON.stringify(data, null, 2), {
|
|
2407
|
+
encoding: "utf-8",
|
|
2408
|
+
mode: 384
|
|
2409
|
+
});
|
|
2410
|
+
renameSync2(tempPath, this.persistPath);
|
|
2411
|
+
try {
|
|
2412
|
+
chmodSync2(this.persistPath, 384);
|
|
2413
|
+
} catch {
|
|
2414
|
+
}
|
|
2415
|
+
} catch (error) {
|
|
2416
|
+
process2.stderr.write(`[SessionRouter] Failed to persist routes at ${sanitizeLogText(this.persistPath, 1024)}: ${sanitizeLogText(error instanceof Error ? error.message : String(error), 512)}
|
|
2417
|
+
`);
|
|
2418
|
+
} finally {
|
|
2419
|
+
try {
|
|
2420
|
+
rmSync(tempPath, { force: true });
|
|
2421
|
+
} catch {
|
|
2422
|
+
}
|
|
2093
2423
|
}
|
|
2094
2424
|
}
|
|
2095
|
-
async createLiveSession(cwd, loadWindow, routingKey, options) {
|
|
2425
|
+
async createLiveSession(cwd, loadWindow, routingKey, options, operation) {
|
|
2096
2426
|
const maxAttempts = 2;
|
|
2097
2427
|
let lastDeadSessionId;
|
|
2098
2428
|
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
2099
|
-
const sessionId =
|
|
2429
|
+
const sessionId = await this.bridge.newSession(cwd, options, operation);
|
|
2430
|
+
try {
|
|
2431
|
+
this.assertOperationCurrent(operation);
|
|
2432
|
+
} catch (error) {
|
|
2433
|
+
this.scheduleDiscardInvalidatedSession(sessionId, operation);
|
|
2434
|
+
throw error;
|
|
2435
|
+
}
|
|
2100
2436
|
if (typeof sessionId !== "string" || sessionId.length === 0) {
|
|
2101
2437
|
throw new Error("Invalid session ID from bridge");
|
|
2102
2438
|
}
|
|
@@ -2112,6 +2448,65 @@ var SessionRouter = class {
|
|
|
2112
2448
|
this.sessionLoadWindows.add(loadWindow);
|
|
2113
2449
|
return loadWindow;
|
|
2114
2450
|
}
|
|
2451
|
+
createSessionOperation(key, target, run) {
|
|
2452
|
+
let routeToken = this.routeTokens.get(key);
|
|
2453
|
+
if (!routeToken) {
|
|
2454
|
+
routeToken = {};
|
|
2455
|
+
this.routeTokens.set(key, routeToken);
|
|
2456
|
+
}
|
|
2457
|
+
const operation = {
|
|
2458
|
+
promise: Promise.resolve(""),
|
|
2459
|
+
target,
|
|
2460
|
+
lifecycleGeneration: this.lifecycleGeneration,
|
|
2461
|
+
routeToken
|
|
2462
|
+
};
|
|
2463
|
+
operation.promise = Promise.resolve().then(() => run(operation)).catch((error) => {
|
|
2464
|
+
this.assertOperationCurrent(operation);
|
|
2465
|
+
throw error;
|
|
2466
|
+
});
|
|
2467
|
+
return operation;
|
|
2468
|
+
}
|
|
2469
|
+
invalidateRouteOperation(key) {
|
|
2470
|
+
this.routeTokens.delete(key);
|
|
2471
|
+
const operation = this.creatingSessions.get(key);
|
|
2472
|
+
if (!operation)
|
|
2473
|
+
return;
|
|
2474
|
+
this.invalidateOperation(operation);
|
|
2475
|
+
this.creatingSessions.delete(key);
|
|
2476
|
+
}
|
|
2477
|
+
invalidateOperation(operation) {
|
|
2478
|
+
operation.invalidationError ??= new Error("Session route operation was invalidated");
|
|
2479
|
+
}
|
|
2480
|
+
assertOperationCurrent(operation) {
|
|
2481
|
+
if (operation.lifecycleGeneration !== this.lifecycleGeneration) {
|
|
2482
|
+
this.invalidateOperation(operation);
|
|
2483
|
+
}
|
|
2484
|
+
if (operation.invalidationError) {
|
|
2485
|
+
throw operation.invalidationError;
|
|
2486
|
+
}
|
|
2487
|
+
}
|
|
2488
|
+
assertOperationResultCurrent(key, sessionId, operation) {
|
|
2489
|
+
if (operation.routeToken !== this.routeTokens.get(key)) {
|
|
2490
|
+
this.invalidateOperation(operation);
|
|
2491
|
+
}
|
|
2492
|
+
if (this.toSession.get(key) !== sessionId) {
|
|
2493
|
+
this.invalidateOperation(operation);
|
|
2494
|
+
}
|
|
2495
|
+
this.assertOperationCurrent(operation);
|
|
2496
|
+
}
|
|
2497
|
+
releaseRouteToken(key, operation) {
|
|
2498
|
+
if (this.routeTokens.get(key) === operation.routeToken && !this.toSession.has(key) && !this.creatingSessions.has(key)) {
|
|
2499
|
+
this.routeTokens.delete(key);
|
|
2500
|
+
}
|
|
2501
|
+
}
|
|
2502
|
+
scheduleDiscardInvalidatedSession(sessionId, operation) {
|
|
2503
|
+
if ([...this.toSession.values()].includes(sessionId))
|
|
2504
|
+
return;
|
|
2505
|
+
try {
|
|
2506
|
+
void this.bridge.discardSession?.(sessionId, operation).catch(() => void 0);
|
|
2507
|
+
} catch {
|
|
2508
|
+
}
|
|
2509
|
+
}
|
|
2115
2510
|
createSessionReservation() {
|
|
2116
2511
|
let resolveReservation;
|
|
2117
2512
|
let rejectReservation;
|
|
@@ -2750,7 +3145,7 @@ var ChannelBase = class {
|
|
|
2750
3145
|
this.memoryScope = Object.freeze(this.resolveMemoryScope(name, config));
|
|
2751
3146
|
this.channelMemory = options?.channelMemory;
|
|
2752
3147
|
this.memoryIntentClassifier = options?.memoryIntentClassifier;
|
|
2753
|
-
this.groupHistory = new GroupHistoryStore(options?.groupHistoryPath ??
|
|
3148
|
+
this.groupHistory = new GroupHistoryStore(options?.groupHistoryPath ?? join5(getGlobalQwenDir(), "channels", `${encodeURIComponent(name)}-group-history.jsonl`));
|
|
2754
3149
|
this.loopController = options?.loopController;
|
|
2755
3150
|
this.groupGate = new GroupGate(config.groupPolicy, config.groups);
|
|
2756
3151
|
this.dmGate = new DmGate(config.dmPolicy);
|
|
@@ -3444,7 +3839,7 @@ ${sanitizePromptText(job.prompt)}`;
|
|
|
3444
3839
|
onToolCall(_chatId, _event) {
|
|
3445
3840
|
}
|
|
3446
3841
|
onSessionDied(sessionId) {
|
|
3447
|
-
this.router.
|
|
3842
|
+
this.router.handleSessionDied(sessionId);
|
|
3448
3843
|
this.instructedSessions.delete(sessionId);
|
|
3449
3844
|
this.removePendingPermissionsForSession(sessionId);
|
|
3450
3845
|
}
|
|
@@ -3492,13 +3887,16 @@ ${sanitizePromptText(job.prompt)}`;
|
|
|
3492
3887
|
*/
|
|
3493
3888
|
onResponseBoundary(_chatId, _sessionId) {
|
|
3494
3889
|
}
|
|
3890
|
+
async sendResponseMessage(chatId, text, _sessionId) {
|
|
3891
|
+
await this.sendMessage(chatId, text);
|
|
3892
|
+
}
|
|
3495
3893
|
/**
|
|
3496
3894
|
* Called when the agent's full response is ready.
|
|
3497
3895
|
* Override to customize delivery (e.g., finalize an AI card).
|
|
3498
|
-
* Default:
|
|
3896
|
+
* Default: sends the full response text.
|
|
3499
3897
|
*/
|
|
3500
|
-
async onResponseComplete(chatId, fullText,
|
|
3501
|
-
await this.
|
|
3898
|
+
async onResponseComplete(chatId, fullText, sessionId) {
|
|
3899
|
+
await this.sendResponseMessage(chatId, fullText, sessionId);
|
|
3502
3900
|
}
|
|
3503
3901
|
/**
|
|
3504
3902
|
* Register a slash command handler. Subclasses can call this to add
|
|
@@ -4909,12 +5307,14 @@ ${promptToSend}`;
|
|
|
4909
5307
|
minChars: this.config.blockStreamingChunk?.minChars ?? 400,
|
|
4910
5308
|
maxChars: this.config.blockStreamingChunk?.maxChars ?? 1e3,
|
|
4911
5309
|
idleMs: this.config.blockStreamingCoalesce?.idleMs ?? 1500,
|
|
4912
|
-
send: /* @__PURE__ */ __name((text) => this.
|
|
5310
|
+
send: /* @__PURE__ */ __name((text) => this.sendResponseMessage(envelope.chatId, text, sessionId), "send")
|
|
4913
5311
|
}) : null;
|
|
4914
5312
|
promptState.stopStreaming = () => streamer?.stop();
|
|
4915
5313
|
const heldChunks = [];
|
|
5314
|
+
let hasStreamedText = false;
|
|
4916
5315
|
const releaseHeldChunks = /* @__PURE__ */ __name(() => {
|
|
4917
5316
|
for (const held of heldChunks.splice(0)) {
|
|
5317
|
+
hasStreamedText = true;
|
|
4918
5318
|
this.emitTaskLifecycle({
|
|
4919
5319
|
...this.lifecycleBase(envelope.chatId, sessionId, envelope.messageId),
|
|
4920
5320
|
type: "text_chunk",
|
|
@@ -4938,6 +5338,7 @@ ${promptToSend}`;
|
|
|
4938
5338
|
return;
|
|
4939
5339
|
}
|
|
4940
5340
|
heldChunks.length = 0;
|
|
5341
|
+
hasStreamedText = false;
|
|
4941
5342
|
this.onResponseBoundary(envelope.chatId, sessionId);
|
|
4942
5343
|
streamer?.stop();
|
|
4943
5344
|
}, "onResponseBoundary");
|
|
@@ -4956,6 +5357,9 @@ ${promptToSend}`;
|
|
|
4956
5357
|
if (!promptState.cancelled && response) {
|
|
4957
5358
|
promptState.deliveryStarted = true;
|
|
4958
5359
|
if (streamer) {
|
|
5360
|
+
if (!hasStreamedText) {
|
|
5361
|
+
streamer.push(response);
|
|
5362
|
+
}
|
|
4959
5363
|
await streamer.flush();
|
|
4960
5364
|
} else {
|
|
4961
5365
|
await this.onResponseComplete(envelope.chatId, response, sessionId);
|