@qwen-code/qwen-code 0.19.8 → 0.19.9-preview.0
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/SKILL.md +1 -0
- package/bundled/qc-helper/docs/configuration/auth.md +40 -55
- package/bundled/qc-helper/docs/configuration/model-providers.md +224 -218
- package/bundled/qc-helper/docs/configuration/settings.md +68 -51
- package/bundled/qc-helper/docs/features/_meta.ts +1 -0
- package/bundled/qc-helper/docs/features/channels/dingtalk.md +12 -2
- package/bundled/qc-helper/docs/features/channels/overview.md +82 -7
- package/bundled/qc-helper/docs/features/channels/wecom.md +6 -0
- package/bundled/qc-helper/docs/features/code-review.md +109 -41
- package/bundled/qc-helper/docs/features/commands.md +45 -44
- package/bundled/qc-helper/docs/features/computer-use.md +77 -0
- 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/features/tool-use-summaries.md +19 -23
- package/bundled/qc-helper/docs/integration-vscode.md +2 -2
- package/bundled/qc-helper/docs/qwen-serve.md +66 -23
- package/bundled/qc-helper/docs/reference/keyboard-shortcuts.md +2 -2
- package/bundled/review/DESIGN.md +303 -46
- package/bundled/review/SKILL.md +670 -165
- package/chunks/MaxSizedBox-BEVSAWZ6.js +70 -0
- package/chunks/{StandaloneSessionPicker-EYRGH6PJ.js → StandaloneSessionPicker-2DA2MDDE.js} +81 -79
- package/chunks/{acpAgent-GRFTTRHW.js → acpAgent-G3WJU3PS.js} +1318 -465
- package/chunks/agent-DD3WSHXE.js +68 -0
- package/chunks/agent-headless-MHI7U2CU.js +62 -0
- package/chunks/{anthropicContentGenerator-CPF22MA7.js → anthropicContentGenerator-56U3YCP2.js} +187 -31
- package/chunks/{artifact-tool-D233YJFH.js → artifact-tool-MIZLXBLF.js} +5 -5
- package/chunks/{askUserQuestion-MKL5ZTMC.js → askUserQuestion-XMJVPNWM.js} +6 -6
- package/chunks/bridge-HKEWPNB5.js +78 -0
- package/chunks/{ca-MKD32FQL.js → ca-C2JTT2N5.js} +68 -6
- 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-2FMQQXMM.js +38 -0
- package/chunks/{chunk-CSOTA7KX.js → chunk-2FO5GFKZ.js} +2 -2
- package/chunks/{chunk-QQDPRDVW.js → chunk-2HRYPZT5.js} +1 -1
- package/chunks/{chunk-UXEW557D.js → chunk-2J4ZWME4.js} +3 -3
- package/chunks/{chunk-P3XEEI3X.js → chunk-2TQXXQMI.js} +36 -7
- package/chunks/{chunk-GSHQYYIV.js → chunk-2UW5RFRP.js} +6 -26
- package/chunks/{chunk-6IAWPIQ6.js → chunk-2W3OOD4W.js} +5 -3
- package/chunks/{chunk-2PSWA5ID.js → chunk-2X56YUSZ.js} +1 -1
- package/chunks/{chunk-NQKLOAVJ.js → chunk-2Z5UX4KI.js} +2 -2
- package/chunks/chunk-3MX7D6QN.js +516 -0
- package/chunks/{chunk-EEN2TKST.js → chunk-43RXPU5Q.js} +2 -2
- package/chunks/{chunk-55ZMG67I.js → chunk-4LD5APFL.js} +4 -4
- package/chunks/{chunk-WF4FAXDL.js → chunk-4QZ3XHWE.js} +62 -62
- package/chunks/chunk-4QZADKJS.js +34 -0
- package/chunks/{chunk-UIDXQNMV.js → chunk-4WGODMVR.js} +1 -1
- package/chunks/{chunk-E6US47KI.js → chunk-4WKAA4KS.js} +1 -1
- package/chunks/{chunk-TI3BWD4D.js → chunk-54UZQ57N.js} +39 -19
- package/chunks/{chunk-3GONHQOA.js → chunk-57OAHC2Y.js} +1 -1
- package/chunks/{chunk-JZSY4WP3.js → chunk-5DTTYNB7.js} +1 -1
- package/chunks/chunk-5HBA2Z7V.js +28 -0
- package/chunks/{chunk-SKAZWEV5.js → chunk-5M6IDOMF.js} +35 -98
- package/chunks/{chunk-A4BMJM77.js → chunk-5O2XNYP6.js} +1 -0
- package/chunks/{chunk-FQNC62B2.js → chunk-5VHASII5.js} +11 -11
- package/chunks/{chunk-GO6LNQXT.js → chunk-6AM5D4ME.js} +1 -1
- package/chunks/{chunk-BJBWRCSK.js → chunk-6H67XLET.js} +1 -1
- package/chunks/{chunk-O7FIRWJV.js → chunk-6JPDCEDB.js} +3 -3
- package/chunks/{chunk-3UP777ZS.js → chunk-6RLROE6G.js} +1 -1
- package/chunks/{chunk-GN3F6PIU.js → chunk-6WPJRYLZ.js} +5 -5
- package/chunks/{chunk-ZERZSAZL.js → chunk-75DOP5OR.js} +2 -2
- package/chunks/chunk-7DKX4A5Z.js +91 -0
- package/chunks/{chunk-M7S4GK5Z.js → chunk-7IDCQ35Q.js} +147 -30
- package/chunks/{chunk-22MNNNXE.js → chunk-7NFB7LBQ.js} +11 -3
- package/chunks/{chunk-ZL5HN75Q.js → chunk-7R4DPSRA.js} +37 -3
- package/chunks/{chunk-VZ7HY3YU.js → chunk-7STBROEV.js} +3 -3
- package/chunks/{chunk-SAIILPQ3.js → chunk-7X7TEQNX.js} +5 -3
- package/chunks/{chunk-RMLZAUWH.js → chunk-A3U2TQUL.js} +10 -12
- package/chunks/{chunk-IRJWHZWU.js → chunk-A4UCTEB5.js} +2 -2
- package/chunks/{chunk-BOBRZZKD.js → chunk-A7W4GQRW.js} +5 -5
- package/chunks/{chunk-O33TBKDC.js → chunk-AAUZBE5Y.js} +155 -19
- package/chunks/{chunk-SQ2UATK7.js → chunk-ADLYZJYZ.js} +11 -11
- package/chunks/{chunk-QYUE6W3T.js → chunk-ALGGS7UH.js} +2 -39
- package/chunks/{chunk-WMPVYQ4P.js → chunk-ARKANCNX.js} +3 -2
- package/chunks/{chunk-IBY3Q3HG.js → chunk-AU4R7ACM.js} +967 -181
- package/chunks/{channel-worker-supervisor-NZQUOEFJ.js → chunk-B7MFJBKE.js} +190 -34
- package/chunks/{chunk-HW4N45EE.js → chunk-B7NUUEXC.js} +38 -11
- package/chunks/{chunk-3B26UVCX.js → chunk-BLPMRN4B.js} +39 -10
- package/chunks/{chunk-ZN5T4BHI.js → chunk-BPZALHVR.js} +2 -2
- package/chunks/{chunk-BVYU3ZTI.js → chunk-BXT6PQ73.js} +1020 -942
- package/chunks/{chunk-OFEVLU4C.js → chunk-CARU2RR2.js} +1 -1
- package/chunks/{chunk-HDOH3QYE.js → chunk-CEGKYZDB.js} +2 -2
- package/chunks/{chunk-GLE2YUPU.js → chunk-COH43MRJ.js} +1 -1
- package/chunks/{chunk-E5A7LHNN.js → chunk-CPBF7KYF.js} +1 -1
- package/chunks/{chunk-UWCTAVOD.js → chunk-CR3C7WXL.js} +1 -1
- package/chunks/{chunk-IWKSG2AR.js → chunk-CXAOG665.js} +1 -1
- package/chunks/{chunk-64WXLC72.js → chunk-DJ2GSRLV.js} +1 -1
- package/chunks/{chunk-QN5NZ3UQ.js → chunk-DMTGGOSA.js} +2 -2
- package/chunks/{chunk-27BHARDE.js → chunk-DMVA55W5.js} +2124 -30
- package/chunks/{chunk-JPALE3PA.js → chunk-DQCCLVQK.js} +6 -6
- package/chunks/{chunk-X2XNQQJI.js → chunk-E2UVIFI2.js} +186 -399
- package/chunks/{chunk-KHDZHZMH.js → chunk-E5Z2AVNV.js} +1 -1
- package/chunks/{chunk-E7EMCSUG.js → chunk-EAHMOXLL.js} +64 -42
- package/chunks/{chunk-VGGOPZUL.js → chunk-EJ3KGYWL.js} +36 -8
- package/chunks/{chunk-DIWVZ3VM.js → chunk-ERTHKDKN.js} +5 -5
- package/chunks/{chunk-UX6OTBVD.js → chunk-EX5OULP3.js} +2 -2
- package/chunks/{chunk-5MBO76SL.js → chunk-F333XEAU.js} +3 -3
- package/chunks/{chunk-OACJLMLD.js → chunk-FBU7WRZI.js} +18 -2
- package/chunks/{chunk-5IFG2VC4.js → chunk-FCMNKVXT.js} +1 -1
- package/chunks/chunk-FEOBU3FA.js +253 -0
- package/chunks/{chunk-LAXNEOBG.js → chunk-FI2WSOWX.js} +19 -3
- package/chunks/{chunk-E7KNELIZ.js → chunk-FSA7ERJ2.js} +2 -2
- package/chunks/{chunk-44NROQYV.js → chunk-GDQQRV43.js} +4 -4
- package/chunks/{chunk-ZE6E424U.js → chunk-GN5HJJBO.js} +2 -2
- package/chunks/{chunk-O2YT7VB4.js → chunk-GOXKNSDZ.js} +2 -65
- package/chunks/{chunk-V35MD7KN.js → chunk-GRC5HGPI.js} +1 -1
- package/chunks/{chunk-ON3JA3RU.js → chunk-GTENQOEJ.js} +7 -9
- package/chunks/{chunk-S6RLAIUR.js → chunk-GYTKQYDB.js} +1 -1
- package/chunks/{chunk-A2X3KLC3.js → chunk-GZXCZHCT.js} +3 -3
- package/chunks/{chunk-K5PGHDBN.js → chunk-H6XPXXMH.js} +1 -1
- package/chunks/{chunk-PMFULMLX.js → chunk-HCJTURZD.js} +2262 -384
- package/chunks/chunk-HGG2RRXD.js +445 -0
- package/chunks/{chunk-II73RK2S.js → chunk-HGT6JR3U.js} +20 -1
- package/chunks/{chunk-DICGXFAI.js → chunk-HJCVNZLQ.js} +11 -9
- package/chunks/{chunk-3GNOQZDC.js → chunk-HJUDVNCO.js} +17663 -14877
- package/chunks/{chunk-AYNCLGTW.js → chunk-HRUGYOJN.js} +8 -51
- package/chunks/{chunk-KYMBIKIW.js → chunk-HTHUX2T5.js} +1 -1
- package/chunks/{chunk-LQ7TMOCE.js → chunk-HTO4JFDZ.js} +1 -1
- package/chunks/{chunk-BUZ6HGL4.js → chunk-HWTL6MPR.js} +357 -59
- package/chunks/chunk-IDS7MSUP.js +74 -0
- package/chunks/{chunk-4CGOWHKM.js → chunk-J4MOFEOK.js} +2 -2
- package/chunks/chunk-JCD4FM7K.js +296 -0
- package/chunks/{chunk-22IFUCVR.js → chunk-JESCGQM3.js} +1 -1
- package/chunks/{chunk-JZHIQJOE.js → chunk-JGO6RFI2.js} +6 -6
- package/chunks/{chunk-X3YGAX7V.js → chunk-JGUT3LWZ.js} +9 -2
- package/chunks/{chunk-JRQ7EVGE.js → chunk-JW7OOJC6.js} +2 -2
- package/chunks/{chunk-OQXDAMKY.js → chunk-KF5MMGG4.js} +8 -8
- package/chunks/{chunk-42XGFRJS.js → chunk-KKRTYONM.js} +8 -6
- package/chunks/{chunk-GGQQA4JW.js → chunk-KSO42X3Z.js} +15 -2
- package/chunks/{chunk-MRO43B25.js → chunk-KW7NOTN6.js} +1 -1
- package/chunks/{chunk-54YZOP7P.js → chunk-L573Z2QZ.js} +11894 -5190
- package/chunks/{chunk-TLWA7TPR.js → chunk-L5U3ELZX.js} +2 -2
- package/chunks/{chunk-YHKAK72D.js → chunk-LHEOLOXU.js} +251 -63
- package/chunks/{chunk-H6EMK6QK.js → chunk-LQIDP6K5.js} +11913 -5207
- package/chunks/{chunk-I6WGFJJ3.js → chunk-LSEJG6AM.js} +73 -19
- package/chunks/{chunk-MZ7BABX3.js → chunk-LXLTBIDP.js} +44 -7
- package/chunks/{chunk-HLKG6CZN.js → chunk-M5GB774H.js} +1 -1
- package/chunks/{chunk-JCH35JB3.js → chunk-MKK4XGLF.js} +2 -2
- package/chunks/{chunk-YKZIAK7C.js → chunk-MO7O5722.js} +424 -40
- package/chunks/chunk-MR3PXB6E.js +48 -0
- package/chunks/{chunk-A5JOJ77H.js → chunk-MRYWYBQ4.js} +38 -15
- package/chunks/{chunk-332PWN27.js → chunk-NHDKSOEY.js} +1 -1
- package/chunks/{chunk-TSPB77TG.js → chunk-NRAFASYX.js} +1016 -2967
- package/chunks/{chunk-BMFMJINR.js → chunk-OA4JVLSA.js} +28 -2
- package/chunks/{chunk-P7M4GA57.js → chunk-OCPBI7J5.js} +1 -1
- package/chunks/chunk-OJAMDVF5.js +66 -0
- package/chunks/{chunk-IJRL2S3D.js → chunk-OKAIGAYW.js} +6 -6
- package/chunks/{chunk-FBET5XZ2.js → chunk-PEJWA3QQ.js} +29 -10
- package/chunks/{chunk-L4AMBVQG.js → chunk-PMKW35AT.js} +54 -22
- package/chunks/{chunk-AGHU5VRK.js → chunk-PZL23GTM.js} +1 -1
- package/chunks/{chunk-PC4ZXHU2.js → chunk-Q6TUALBE.js} +3 -3
- package/chunks/{chunk-FXGLL2HL.js → chunk-Q7YDKOGY.js} +1 -1
- package/chunks/{chunk-XOHNA2S6.js → chunk-QAW7PIHT.js} +3 -3
- package/chunks/{chunk-XYR5RUA5.js → chunk-QE2WJ7FS.js} +10 -3
- package/chunks/{chunk-LGFAYIKX.js → chunk-QHTIBUWB.js} +1 -1
- package/chunks/{chunk-P3MYAZBY.js → chunk-QMGX2KO2.js} +1 -1
- package/chunks/{chunk-Z3I3QJK3.js → chunk-QRUIS3DN.js} +1 -1
- package/chunks/{chunk-ITOGNELQ.js → chunk-QSWDGAIC.js} +2 -2
- package/chunks/{chunk-PUVCVELY.js → chunk-QUJOI7SR.js} +70 -8
- package/chunks/{chunk-GHOTR7HL.js → chunk-QUPXZXLV.js} +1 -1
- package/chunks/{chunk-6VK6FIMQ.js → chunk-R5D5JOAM.js} +415 -379
- package/chunks/{chunk-CD6USWHZ.js → chunk-R5XLNDE2.js} +2 -2
- package/chunks/{chunk-W7EEOR7D.js → chunk-RCEEXIOO.js} +8 -6
- package/chunks/{chunk-TLRYABYP.js → chunk-RKUWKYED.js} +1 -1
- package/chunks/{chunk-RNBYOUGV.js → chunk-RXFQM6FQ.js} +1 -1
- package/chunks/{chunk-QXPI7FEC.js → chunk-S3TWXGKA.js} +4 -4
- package/chunks/{chunk-2EM7ECZD.js → chunk-SMSFWUFY.js} +309 -80
- package/chunks/{chunk-FV7425LN.js → chunk-SPJQO2CE.js} +18 -5
- package/chunks/{chunk-MLZQVCF3.js → chunk-SZRN75WQ.js} +1 -1
- package/chunks/{chunk-7RYW5LQV.js → chunk-T2NCM2ET.js} +2 -2
- package/chunks/{chunk-Z2Z3GUXZ.js → chunk-TB6UDU4T.js} +1 -1
- package/chunks/{chunk-EXPMGZZV.js → chunk-TEGEBB2I.js} +1 -1
- package/chunks/{chunk-MX2YXRER.js → chunk-TJTKSVIV.js} +1 -1
- package/chunks/{chunk-CCGOFQV3.js → chunk-TQBODCFD.js} +8 -7
- package/chunks/chunk-TV6K2FB4.js +224 -0
- package/chunks/{chunk-H6BD2ELD.js → chunk-TYAMGABM.js} +2 -2
- package/chunks/{chunk-QYNNN7BK.js → chunk-TYLOFD2U.js} +2 -2
- package/chunks/{chunk-VRDMOSQS.js → chunk-UDXSXLER.js} +2 -2
- package/chunks/{chunk-DHOLNQLC.js → chunk-UFDX27PL.js} +60 -40
- package/chunks/{chunk-WHJQ3JUS.js → chunk-UGN6CTNZ.js} +10 -10
- package/chunks/{chunk-CHB5SLZZ.js → chunk-UNLRKDMW.js} +4 -4
- package/chunks/{chunk-CJCKDMWO.js → chunk-URK542T4.js} +1 -1
- package/chunks/{chunk-AHNXYU4O.js → chunk-V6WHFGST.js} +1 -1
- package/chunks/{chunk-ZTQ26VBE.js → chunk-VDDGDZMA.js} +1 -1
- package/chunks/{chunk-BOBOCR5H.js → chunk-VEETSXYX.js} +4 -4
- package/chunks/{chunk-OMX7CUOE.js → chunk-VGC4I5JJ.js} +1 -1
- package/chunks/{chunk-43W4YSO6.js → chunk-VJNBRRZG.js} +2 -2
- package/chunks/{chunk-WQTHLB5T.js → chunk-VKS7EIOA.js} +7 -7
- package/chunks/{chunk-J7RCB6N5.js → chunk-VVDNGM6X.js} +2 -2
- package/chunks/{chunk-ER3BKOLB.js → chunk-W7FJ3N32.js} +1 -1
- package/chunks/{chunk-3HX5LZ6R.js → chunk-WBL3FJEU.js} +2 -2
- package/chunks/{chunk-7LTB54MK.js → chunk-WIEO4CWB.js} +2 -2
- package/chunks/chunk-WMC6HH7Y.js +493 -0
- package/chunks/{chunk-FEJ2FZ3U.js → chunk-WTNZ6DXB.js} +2 -2
- package/chunks/{chunk-L46XKEGM.js → chunk-X6ODDESK.js} +5 -8
- package/chunks/chunk-XDPYM5DE.js +71 -0
- package/chunks/{chunk-3RW4AZJV.js → chunk-XFSFZCM5.js} +1 -1
- package/chunks/{chunk-2MPVVENX.js → chunk-XU457J4V.js} +2 -2
- package/chunks/{chunk-SIUQ3YYX.js → chunk-XVNQMZ2I.js} +1 -1
- package/chunks/{chunk-SYCJMSIJ.js → chunk-XWRJCPHC.js} +1 -1
- package/chunks/{chunk-SUAKHHK7.js → chunk-Y66VOBRP.js} +3 -3
- package/chunks/chunk-YAF2MQZ6.js +19 -0
- package/chunks/chunk-YHN5SUIJ.js +219 -0
- package/chunks/{chunk-BR4QREVK.js → chunk-YQ3U5MUC.js} +1 -1
- package/chunks/{chunk-Y6Z2O3WR.js → chunk-YUZI3WAC.js} +1 -1
- package/chunks/{chunk-YDOXPLYL.js → chunk-ZA74ZTQU.js} +4564 -1326
- package/chunks/{chunk-DCZWC4PF.js → chunk-ZGE3222J.js} +5 -5
- package/chunks/chunk-ZP4ZZJJG.js +448 -0
- package/chunks/{chunk-AHNJGLFV.js → chunk-ZPAHLFZU.js} +3 -3
- package/chunks/cli-entry-path-4VJ3Y6T2.js +10 -0
- package/chunks/{computer-use-WMY3UOBX.js → computer-use-SHA6C3ES.js} +50 -50
- package/chunks/config-utils-XSHOMMK4.js +24 -0
- package/chunks/contextCommand-HOAF5LUC.js +68 -0
- package/chunks/create-sub-session-EAB2U5XW.js +207 -0
- package/chunks/create-sub-session-WJOWBFEP.js +375 -0
- package/chunks/{cron-create-JSXEIPVS.js → cron-create-GMVKSXZT.js} +9 -9
- package/chunks/{cron-delete-OIFVEPGU.js → cron-delete-VDZKUAVK.js} +7 -7
- package/chunks/{cron-list-D4ZX4IOE.js → cron-list-UG7C7RAR.js} +14 -10
- package/chunks/{daemon-WPAENEBW.js → daemon-MI5HF26N.js} +1074 -61
- package/chunks/daemon-status-provider-KFL3LRTP.js +76 -0
- package/chunks/{de-ZFPPQVSF.js → de-2VCDRDGU.js} +68 -6
- package/chunks/{devtools-FM6GJPYG.js → devtools-4QFYJT6U.js} +3 -3
- package/chunks/{dist-O2IRTRPP.js → dist-IEXZC5ZR.js} +10 -10
- package/chunks/{dist-SCFLLYMK.js → dist-PQK4GCKA.js} +12 -11
- package/chunks/{dist-63IS3ZMI.js → dist-PZV5RKM6.js} +4 -4
- package/chunks/{dist-E6UANPIM.js → dist-U75JK3PF.js} +1011 -197
- package/chunks/{dist-H2AEJCZ5.js → dist-VXO7QBON.js} +5 -5
- package/chunks/{dist-Z34QPAQW.js → dist-WH4TZSH3.js} +529 -79
- package/chunks/{dist-BEXOZXLQ.js → dist-X2ABIW5R.js} +36 -15
- package/chunks/earlyInputCapture-PKAQJMIP.js +69 -0
- package/chunks/{edit-OTYWAXGP.js → edit-6TXLYHJ2.js} +51 -51
- package/chunks/{en-N4EPZAQI.js → en-NJCA3TAA.js} +78 -6
- package/chunks/{enter-worktree-HNYBDVCX.js → enter-worktree-ZTILGPJX.js} +50 -50
- package/chunks/{enterPlanMode-CJCNGT63.js → enterPlanMode-62HRAMCH.js} +66 -51
- package/chunks/environment-OYA3ZVEL.js +89 -0
- package/chunks/errors-BFXOUUUR.js +75 -0
- package/chunks/{exit-worktree-DUUKOE3X.js → exit-worktree-HHJ5M6MV.js} +50 -50
- package/chunks/{exitPlanMode-AMMSXOAJ.js → exitPlanMode-M3SWHCL7.js} +51 -51
- package/chunks/{fast-path-OV6NIP3K.js → fast-path-3VMPLM74.js} +8 -8
- package/chunks/{fast-path-settings-7RIFI3PK.js → fast-path-settings-DAOVFADC.js} +8 -6
- package/chunks/{fileFromPath-IBEHA3CO.js → fileFromPath-UDALK7FM.js} +3 -3
- package/chunks/{fr-5WWMY53B.js → fr-5F3E7WKD.js} +68 -6
- package/chunks/{gemini-NQ3WWBKB.js → gemini-ZCGVYOJL.js} +181 -110
- package/chunks/{geminiContentGenerator-CDUNEJQE.js → geminiContentGenerator-XBYBAIDQ.js} +9 -9
- package/chunks/{getMachineId-bsd-4CASPIU4.js → getMachineId-bsd-EXV7SWPA.js} +3 -3
- package/chunks/{getMachineId-darwin-HPQPEMZR.js → getMachineId-darwin-IUOMFXU3.js} +3 -3
- package/chunks/{getMachineId-linux-AUARKYHL.js → getMachineId-linux-K7XJYFHL.js} +2 -2
- package/chunks/{getMachineId-unsupported-S32ZDA2T.js → getMachineId-unsupported-EA5FDRJ6.js} +2 -2
- package/chunks/{getMachineId-win-4EFLHYIJ.js → getMachineId-win-KBA6RAI5.js} +3 -3
- package/chunks/{glob-ROV3YS4R.js → glob-UOEYQNHN.js} +97 -75
- package/chunks/{grep-NRITKDCD.js → grep-OQM3CH7W.js} +50 -50
- package/chunks/handleAutoUpdate-ORBYVJHZ.js +69 -0
- package/chunks/i18n-NBP574CO.js +84 -0
- package/chunks/initializer-CWD7TCCD.js +73 -0
- package/chunks/installationInfo-CHPDUPWC.js +65 -0
- package/chunks/{ja-CUHZOLEJ.js → ja-66J6B53L.js} +69 -7
- package/chunks/{keychain-token-storage-UJV5XP4Z.js → keychain-token-storage-AU22CQI6.js} +4 -4
- package/chunks/{kittyProtocolDetector-OJRCJLIU.js → kittyProtocolDetector-HCNNKJTI.js} +2 -2
- package/chunks/list-ZTTO362W.js +76 -0
- package/chunks/loadedSettingsAdapter-V4ZTRKUO.js +70 -0
- package/chunks/{loop-wakeup-OHWEMFP5.js → loop-wakeup-C4EXLYVA.js} +10 -10
- package/chunks/{lowlight-FYAAUU5J.js → lowlight-J2OZNPCA.js} +1 -1
- package/chunks/{ls-7MFU2QYW.js → ls-2OUTG3IZ.js} +6 -6
- package/chunks/{lsp-XHDTPTGV.js → lsp-4VMNXZW6.js} +4 -4
- package/chunks/mcp-UH5PSGIK.js +70 -0
- package/chunks/{monitor-FL2ZO33W.js → monitor-F4NYEU5J.js} +50 -50
- package/chunks/{multipart-parser-AJ4WASWR.js → multipart-parser-AWZKXSQN.js} +3 -3
- package/chunks/nonInteractiveCli-7IHPXVNH.js +129 -0
- package/chunks/{notebook-edit-6PULTHL5.js → notebook-edit-HPDXNGQH.js} +51 -51
- package/chunks/openaiContentGenerator-OBDNNOE2.js +56 -0
- package/chunks/pidfile-AUMGYIOK.js +73 -0
- package/chunks/{pt-OLYN42DS.js → pt-TFZO5Y6T.js} +68 -6
- package/chunks/{qwenContentGenerator-NX2E7PB7.js → qwenContentGenerator-LH2U2YRG.js} +52 -52
- package/chunks/{qwenOAuth2-ZV7YLMND.js → qwenOAuth2-LEYOU7RU.js} +9 -9
- package/chunks/read-file-HUUFBLEO.js +30 -0
- package/chunks/{read-mcp-resource-CNQHBSJM.js → read-mcp-resource-JUFHCKSC.js} +5 -5
- package/chunks/{read-package-up-ER5OJUGP.js → read-package-up-TCM6I7S2.js} +2 -2
- package/chunks/{record-artifact-SQ2OKRJW.js → record-artifact-DWSMBXYY.js} +4 -4
- package/chunks/ripGrep-C7X33LU6.js +60 -0
- package/chunks/{ru-LDM3GWVQ.js → ru-4L4LFHIT.js} +68 -6
- package/chunks/{run-qwen-serve-JK2DL7PI.js → run-qwen-serve-DGW5AFDJ.js} +1465 -283
- package/chunks/runtime-NYUSLBEZ.js +99 -0
- package/chunks/{scheduler-O4IGVZKK.js → scheduler-5VKDXULT.js} +51 -51
- package/chunks/{send-message-76GT3JMC.js → send-message-JZ752NWD.js} +7 -7
- package/chunks/serve-UTAHSFXH.js +76 -0
- package/chunks/{server-SGNPKX2O.js → server-VUHSYSUV.js} +9088 -1817
- package/chunks/{session-5BNM25EZ.js → session-QSGSSNFB.js} +340 -135
- package/chunks/settings-X24RYEED.js +120 -0
- package/chunks/shell-4MSI2R4O.js +70 -0
- package/chunks/{skill-I22QK5XS.js → skill-JR3GTNVZ.js} +24 -24
- package/chunks/spawnChannel-RFAAO44J.js +70 -0
- package/chunks/{src-7XL4G4DC.js → src-VLI3TKEY.js} +4 -4
- package/chunks/{src-BBQSM46M.js → src-YDBNMIIM.js} +183 -53
- package/chunks/standalone-update-4CY4HKGC.js +79 -0
- package/chunks/{startInteractiveUI-JII36UGN.js → startInteractiveUI-FOD7MMVB.js} +2368 -1923
- package/chunks/stdioHelpers-UMY72QRP.js +14 -0
- package/chunks/{syntheticOutput-F7LSDCAR.js → syntheticOutput-LELY6HAI.js} +5 -5
- package/chunks/task-create-QY3BIMNM.js +23 -0
- package/chunks/{task-list-TGGJX7EA.js → task-list-D2U47WBJ.js} +11 -10
- package/chunks/{task-stop-W7NGTMYQ.js → task-stop-N6E5IYLH.js} +4 -4
- package/chunks/{task-update-XYWMHJGJ.js → task-update-HJCQILLB.js} +13 -12
- package/chunks/{team-create-A7NUU5AQ.js → team-create-ZLQSU2E3.js} +50 -50
- package/chunks/{team-delete-UHQQ2QQX.js → team-delete-RCWYDRF4.js} +11 -10
- package/chunks/{team-plan-approval-TOQRJ2KI.js → team-plan-approval-YUAYBYLS.js} +50 -50
- package/chunks/theme-manager-SKNEBMOG.js +64 -0
- package/chunks/{todoWrite-C4ZAMSR3.js → todoWrite-FKCGATPJ.js} +6 -6
- package/chunks/{tool-search-SZ4EFS2T.js → tool-search-V5J3TGWY.js} +24 -24
- package/chunks/total-session-admission-2WIH72I3.js +72 -0
- package/chunks/tree-sitter-YJVE2ZUK.js +2980 -0
- package/chunks/trustedFolders-JF265CRI.js +80 -0
- package/chunks/types-ML3TRJQ5.js +16 -0
- package/chunks/updateCheck-AMXNPBP6.js +69 -0
- package/chunks/updateEventEmitter-5MKC7BLQ.js +10 -0
- package/chunks/validateNonInterActiveAuth-6YHQO7PD.js +194 -0
- package/chunks/{version-NO2XSNNP.js → version-UEJJK7PE.js} +3 -3
- package/chunks/{web-fetch-UYGMOHW4.js → web-fetch-QGODBB6S.js} +8 -8
- package/chunks/{workflow-WO2H6NRI.js → workflow-5YFA5V4M.js} +51 -51
- package/chunks/workspace-providers-status-LMBLBNR7.js +73 -0
- package/chunks/workspace-registration-store-VV2S4MSV.js +27 -0
- package/chunks/workspace-registry-BVMPYRLN.js +76 -0
- package/chunks/workspace-service-PUYIZ3J4.js +86 -0
- package/chunks/workspace-skills-status-CJ7J2KPP.js +72 -0
- package/chunks/{write-file-PX2Z7IBE.js → write-file-OV77M6X7.js} +51 -51
- package/chunks/{yargs-B64EYTCF.js → yargs-6H2AUULL.js} +2 -2
- package/chunks/{zh-J4F6QWQV.js → zh-FSAH32JB.js} +79 -7
- package/chunks/{zh-TW-XVDWOLSW.js → zh-TW-D2YIE2LO.js} +79 -7
- package/cli.js +18 -17
- package/locales/ca.js +91 -7
- package/locales/de.js +90 -7
- package/locales/en.js +109 -7
- package/locales/fr.js +91 -7
- package/locales/ja.js +93 -7
- package/locales/pt.js +90 -7
- package/locales/ru.js +90 -7
- package/locales/zh-TW.js +106 -7
- package/locales/zh.js +106 -7
- package/package.json +3 -6
- package/web-shell/assets/{arc-BWyoJpY2.js → arc-CObt_TK9.js} +1 -1
- package/web-shell/assets/{architectureDiagram-3BPJPVTR-BT0mGrz2.js → architectureDiagram-3BPJPVTR-B7aiJ6CK.js} +1 -1
- package/web-shell/assets/{blockDiagram-GPEHLZMM-BLgUWvyf.js → blockDiagram-GPEHLZMM-BSK2CrID.js} +1 -1
- package/web-shell/assets/{c4Diagram-AAUBKEIU-DYx9M7oU.js → c4Diagram-AAUBKEIU-Bhx2p7T_.js} +1 -1
- package/web-shell/assets/channel-BBaLq8MV.js +1 -0
- package/web-shell/assets/{chunk-2J33WTMH-CfMHWbuZ.js → chunk-2J33WTMH-c3Hzv0Ni.js} +1 -1
- package/web-shell/assets/{chunk-4BX2VUAB-B1URoqEV.js → chunk-4BX2VUAB-DNXaK7ZF.js} +1 -1
- package/web-shell/assets/{chunk-55IACEB6-DAIaM4QF.js → chunk-55IACEB6-BXjvDj_i.js} +1 -1
- package/web-shell/assets/{chunk-727SXJPM-B2X34knw.js → chunk-727SXJPM-B6CaKFp-.js} +1 -1
- package/web-shell/assets/{chunk-AQP2D5EJ-Cif-zLTQ.js → chunk-AQP2D5EJ-tij6Mz9B.js} +1 -1
- package/web-shell/assets/{chunk-FMBD7UC4-H18WCXdY.js → chunk-FMBD7UC4-DdlsGk2h.js} +1 -1
- package/web-shell/assets/{chunk-ND2GUHAM-YFtetHi0.js → chunk-ND2GUHAM-CdgGZSHE.js} +1 -1
- package/web-shell/assets/{chunk-QZHKN3VN-By2hiH3r.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-VrcnnLZu.js → cose-bilkent-S5V4N54A-BUVmNp1Y.js} +1 -1
- package/web-shell/assets/{dagre-BM42HDAG-CGo-IaVV.js → dagre-BM42HDAG-CO4q310O.js} +1 -1
- package/web-shell/assets/{diagram-2AECGRRQ-Dl4QjzIB.js → diagram-2AECGRRQ-C6gFvWkg.js} +1 -1
- package/web-shell/assets/{diagram-5GNKFQAL-qMLmsO0u.js → diagram-5GNKFQAL-NG2I_c0h.js} +1 -1
- package/web-shell/assets/{diagram-KO2AKTUF-CHlmuxPI.js → diagram-KO2AKTUF-DFKMS6I9.js} +1 -1
- package/web-shell/assets/{diagram-LMA3HP47-BUwU3GwT.js → diagram-LMA3HP47-BiElfsfP.js} +1 -1
- package/web-shell/assets/{diagram-OG6HWLK6-HEhwPDUM.js → diagram-OG6HWLK6-zLWDYUqu.js} +1 -1
- package/web-shell/assets/{erDiagram-TEJ5UH35-1n0llBmM.js → erDiagram-TEJ5UH35-DoVaazhK.js} +1 -1
- package/web-shell/assets/{flowDiagram-I6XJVG4X-BN74uMnt.js → flowDiagram-I6XJVG4X-0RLz-mXg.js} +1 -1
- package/web-shell/assets/{ganttDiagram-6RSMTGT7-BoOq78i3.js → ganttDiagram-6RSMTGT7-C-eX1A39.js} +3 -3
- package/web-shell/assets/{gitGraphDiagram-PVQCEYII-CN8b00c8.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-CCurnIna.js → infoDiagram-5YYISTIA-C800cFvZ.js} +1 -1
- package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-AwuRqdUP.js → ishikawaDiagram-YF4QCWOH-CFK1Jk6e.js} +1 -1
- package/web-shell/assets/{journeyDiagram-JHISSGLW-B7IICk-E.js → journeyDiagram-JHISSGLW-Cjx0WAC4.js} +1 -1
- package/web-shell/assets/{kanban-definition-UN3LZRKU-BYF0OKhx.js → kanban-definition-UN3LZRKU-DWMDHbiv.js} +1 -1
- package/web-shell/assets/{linear-GWWguGfD.js → linear-vpW4FrZs.js} +1 -1
- package/web-shell/assets/{mermaid.core-JqtkxvCl.js → mermaid.core-DsHRUnDd.js} +5 -5
- package/web-shell/assets/{mindmap-definition-RKZ34NQL-B0MmHsZ6.js → mindmap-definition-RKZ34NQL-D3Eb1cAK.js} +1 -1
- package/web-shell/assets/{pieDiagram-4H26LBE5-DhImUZLQ.js → pieDiagram-4H26LBE5-Cr2-6sWt.js} +1 -1
- package/web-shell/assets/{quadrantDiagram-W4KKPZXB-DGeSC3DT.js → quadrantDiagram-W4KKPZXB-Yd7yUgVp.js} +1 -1
- package/web-shell/assets/{requirementDiagram-4Y6WPE33-DkspY6Re.js → requirementDiagram-4Y6WPE33-BE6SprL8.js} +1 -1
- package/web-shell/assets/{sankeyDiagram-5OEKKPKP-CaOofS2x.js → sankeyDiagram-5OEKKPKP-DzkuMK8d.js} +1 -1
- package/web-shell/assets/{sequenceDiagram-3UESZ5HK-DFQ_kFnN.js → sequenceDiagram-3UESZ5HK-wD9A3Dhi.js} +1 -1
- package/web-shell/assets/{stateDiagram-AJRCARHV-D3snw0Tz.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-l4zH8nLM.js → timeline-definition-PNZ67QCA-Btc08sUA.js} +1 -1
- package/web-shell/assets/{vennDiagram-CIIHVFJN-BnRlA98M.js → vennDiagram-CIIHVFJN-Bv6upsOA.js} +1 -1
- package/web-shell/assets/{wardley-L42UT6IY-BS0xUdmd.js → wardley-L42UT6IY-D-XamnCK.js} +1 -1
- package/web-shell/assets/{wardleyDiagram-YWT4CUSO-DKGBUWyQ.js → wardleyDiagram-YWT4CUSO-BbP_5Wfp.js} +1 -1
- package/web-shell/assets/{xychartDiagram-2RQKCTM6-DVb2HuOB.js → xychartDiagram-2RQKCTM6-CO5Hh28b.js} +1 -1
- package/web-shell/index.html +16 -4
- package/chunks/MaxSizedBox-5DT2SD7B.js +0 -71
- package/chunks/agent-H2DGKS77.js +0 -68
- package/chunks/agent-headless-KFMFIT6J.js +0 -62
- package/chunks/bridge-NA3ZQQKJ.js +0 -78
- package/chunks/chunk-5P5XGNYH.js +0 -93
- package/chunks/chunk-6SHO7WFF.js +0 -79
- package/chunks/chunk-IFEWJXFS.js +0 -37
- package/chunks/chunk-XNXVCNAT.js +0 -88
- package/chunks/contextCommand-LXFZRP4L.js +0 -68
- package/chunks/daemon-status-provider-GJRXY5EN.js +0 -76
- package/chunks/earlyInputCapture-KNOYZ4MJ.js +0 -69
- package/chunks/environment-ATFTYMLZ.js +0 -88
- package/chunks/errors-A54HAADA.js +0 -75
- package/chunks/handleAutoUpdate-CEZJAARW.js +0 -65
- package/chunks/initializer-BRFJKRRX.js +0 -71
- package/chunks/list-KVHF7O4X.js +0 -73
- package/chunks/loadedSettingsAdapter-LL5PSFKX.js +0 -68
- package/chunks/mcp-3GCXRTOQ.js +0 -68
- package/chunks/nonInteractiveCli-PTQI3DV6.js +0 -119
- package/chunks/openaiContentGenerator-YE42PKCY.js +0 -56
- package/chunks/pidfile-NZYSCFRK.js +0 -73
- package/chunks/read-file-33XGP5HF.js +0 -30
- package/chunks/ripGrep-QWZLGTAN.js +0 -60
- package/chunks/serve-JTMIGANH.js +0 -74
- package/chunks/settings-3MI4XXP6.js +0 -118
- package/chunks/shell-YJKBE67T.js +0 -68
- package/chunks/spawnChannel-UNV6W4DU.js +0 -70
- package/chunks/task-create-WCHTB435.js +0 -22
- package/chunks/theme-manager-WZ4RRMMB.js +0 -64
- package/chunks/total-session-admission-ULXJWXFV.js +0 -72
- package/chunks/trustedFolders-LAZZPZ3D.js +0 -79
- package/chunks/types-QX5C3CHJ.js +0 -12
- package/chunks/updateCheck-KONLM73X.js +0 -65
- package/chunks/validateNonInterActiveAuth-MPKSRCXD.js +0 -184
- package/chunks/workspace-providers-status-3W7E7DFW.js +0 -71
- package/chunks/workspace-registry-SXJZNN3O.js +0 -74
- package/chunks/workspace-service-CZRQZ4Q4.js +0 -80
- package/chunks/workspace-skills-status-K7WFREPD.js +0 -70
- package/node_modules/@qwen-code/audio-capture/dist/index.d.ts +0 -35
- package/node_modules/@qwen-code/audio-capture/dist/index.js +0 -48
- package/node_modules/@qwen-code/audio-capture/dist/index.js.map +0 -1
- package/node_modules/@qwen-code/audio-capture/dist/platform.d.ts +0 -7
- package/node_modules/@qwen-code/audio-capture/dist/platform.js +0 -18
- package/node_modules/@qwen-code/audio-capture/dist/platform.js.map +0 -1
- package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/LICENSE +0 -21
- package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/README.md +0 -58
- package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/SECURITY.md +0 -5
- package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/bin.js +0 -84
- package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/build-test.js +0 -19
- package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/index.js +0 -6
- package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/node-gyp-build.js +0 -207
- package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/optional.js +0 -7
- package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/package.json +0 -43
- package/node_modules/@qwen-code/audio-capture/package.json +0 -30
- package/node_modules/@qwen-code/audio-capture/prebuilds/darwin-arm64/@qwen-code+audio-capture.node +0 -0
- package/node_modules/@qwen-code/audio-capture/prebuilds/darwin-x64/@qwen-code+audio-capture.node +0 -0
- package/node_modules/@qwen-code/audio-capture/prebuilds/linux-arm64/@qwen-code+audio-capture.node +0 -0
- package/node_modules/@qwen-code/audio-capture/prebuilds/linux-x64/@qwen-code+audio-capture.node +0 -0
- package/node_modules/@qwen-code/audio-capture/prebuilds/win32-x64/@qwen-code+audio-capture.node +0 -0
- package/web-shell/assets/channel-wmPUGHtg.js +0 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-BA2ljEjW.js +0 -1
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-BA2ljEjW.js +0 -1
- package/web-shell/assets/index-CNwoO1Cn.js +0 -783
- package/web-shell/assets/index-CWQ0z6kZ.css +0 -5
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-BbSm_9d0.js +0 -1
|
@@ -3,15 +3,13 @@
|
|
|
3
3
|
import {
|
|
4
4
|
DaemonMetricsRing,
|
|
5
5
|
computeCpuPercent
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import {
|
|
8
|
-
findCliEntryPath
|
|
9
|
-
} from "./chunk-AHNXYU4O.js";
|
|
6
|
+
} from "./chunk-HGT6JR3U.js";
|
|
10
7
|
import {
|
|
11
8
|
CAPABILITIES_SCHEMA_VERSION,
|
|
12
9
|
ClientMcpSenderRegistry,
|
|
13
10
|
PathMutexRegistry,
|
|
14
11
|
SERVE_CAPABILITY_REGISTRY,
|
|
12
|
+
WorkspaceVoiceCoordinator,
|
|
15
13
|
allowOriginCors,
|
|
16
14
|
allowOriginMode,
|
|
17
15
|
bearerAuth,
|
|
@@ -22,71 +20,92 @@ import {
|
|
|
22
20
|
getRateLimiter,
|
|
23
21
|
getServeProtocolVersions,
|
|
24
22
|
hostAllowlist,
|
|
23
|
+
isBrowserAutomationMcpAvailable,
|
|
25
24
|
listenerMaxConnections,
|
|
26
25
|
parseAllowOriginPatterns,
|
|
27
26
|
parseDaemonStatusDetail,
|
|
28
27
|
positiveFiniteOrNull,
|
|
29
28
|
require_express,
|
|
30
29
|
resolveWebShellDir
|
|
31
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-MO7O5722.js";
|
|
32
31
|
import {
|
|
33
32
|
isLoopbackBind
|
|
34
|
-
} from "./chunk-
|
|
35
|
-
import "./chunk-3HX5LZ6R.js";
|
|
36
|
-
import "./chunk-7RYW5LQV.js";
|
|
33
|
+
} from "./chunk-RXFQM6FQ.js";
|
|
37
34
|
import {
|
|
38
35
|
RUNTIME_STARTUP_CANCELLED_MESSAGE
|
|
39
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-QUPXZXLV.js";
|
|
40
37
|
import {
|
|
41
38
|
LOAD_REPLAY_META_KEY
|
|
42
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-PZL23GTM.js";
|
|
43
40
|
import {
|
|
44
41
|
DEFAULT_COMPACTED_REPLAY_MAX_BYTES,
|
|
45
42
|
normalizeCompactedReplayMaxBytes
|
|
46
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-COH43MRJ.js";
|
|
44
|
+
import "./chunk-WBL3FJEU.js";
|
|
47
45
|
import {
|
|
48
|
-
|
|
49
|
-
} from "./chunk-
|
|
46
|
+
resolveChannelCwd
|
|
47
|
+
} from "./chunk-4QZADKJS.js";
|
|
50
48
|
import {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
49
|
+
MAX_REGISTERED_WORKSPACES,
|
|
50
|
+
resolveWorkspaceInputs,
|
|
51
|
+
workspaceRegistrationId
|
|
52
|
+
} from "./chunk-WMC6HH7Y.js";
|
|
53
|
+
import {
|
|
54
|
+
canonicalizeWorkspace
|
|
55
|
+
} from "./chunk-W7FJ3N32.js";
|
|
56
|
+
import "./chunk-3MX7D6QN.js";
|
|
54
57
|
import {
|
|
55
58
|
QWEN_SERVER_TOKEN_ENV
|
|
56
|
-
} from "./chunk-
|
|
59
|
+
} from "./chunk-GYTKQYDB.js";
|
|
57
60
|
import {
|
|
58
61
|
channelSelectionNames
|
|
59
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-TJTKSVIV.js";
|
|
63
|
+
import "./chunk-5HBA2Z7V.js";
|
|
64
|
+
import {
|
|
65
|
+
ChannelWebhookEnqueueError
|
|
66
|
+
} from "./chunk-OJAMDVF5.js";
|
|
67
|
+
import "./chunk-T2NCM2ET.js";
|
|
68
|
+
import {
|
|
69
|
+
sanitizeLogText
|
|
70
|
+
} from "./chunk-AU4R7ACM.js";
|
|
71
|
+
import "./chunk-UDXSXLER.js";
|
|
72
|
+
import {
|
|
73
|
+
loadServeFastPathSettings,
|
|
74
|
+
preResolveServeFastPathHomeEnvOverrides
|
|
75
|
+
} from "./chunk-PEJWA3QQ.js";
|
|
76
|
+
import "./chunk-GOXKNSDZ.js";
|
|
60
77
|
import {
|
|
61
78
|
getGlobalQwenDirLite,
|
|
62
79
|
resolveConfigPathLite
|
|
63
|
-
} from "./chunk-
|
|
64
|
-
import "./chunk-
|
|
80
|
+
} from "./chunk-IDS7MSUP.js";
|
|
81
|
+
import "./chunk-QRUIS3DN.js";
|
|
82
|
+
import "./chunk-ALGGS7UH.js";
|
|
65
83
|
import {
|
|
66
|
-
|
|
67
|
-
} from "./chunk-
|
|
68
|
-
import "./chunk-43W4YSO6.js";
|
|
84
|
+
isWithinRoot
|
|
85
|
+
} from "./chunk-MR3PXB6E.js";
|
|
69
86
|
import {
|
|
70
87
|
writeStderrLine,
|
|
71
88
|
writeStdoutLine
|
|
72
|
-
} from "./chunk-
|
|
89
|
+
} from "./chunk-YUZI3WAC.js";
|
|
73
90
|
import {
|
|
74
|
-
|
|
75
|
-
} from "./chunk-
|
|
76
|
-
import "./chunk-
|
|
77
|
-
import "./chunk-
|
|
78
|
-
import "./chunk-
|
|
79
|
-
import "./chunk-
|
|
91
|
+
getCliVersion
|
|
92
|
+
} from "./chunk-2J4ZWME4.js";
|
|
93
|
+
import "./chunk-VJNBRRZG.js";
|
|
94
|
+
import "./chunk-H6XPXXMH.js";
|
|
95
|
+
import "./chunk-5M6IDOMF.js";
|
|
96
|
+
import "./chunk-E2UVIFI2.js";
|
|
97
|
+
import "./chunk-CR3C7WXL.js";
|
|
98
|
+
import "./chunk-XWRJCPHC.js";
|
|
80
99
|
import {
|
|
81
100
|
finalizeStartupProfile,
|
|
82
101
|
profileCheckpoint
|
|
83
|
-
} from "./chunk-
|
|
84
|
-
import "./chunk-
|
|
85
|
-
import "./chunk-
|
|
86
|
-
import "./chunk-
|
|
102
|
+
} from "./chunk-QSWDGAIC.js";
|
|
103
|
+
import "./chunk-Q7YDKOGY.js";
|
|
104
|
+
import "./chunk-DMTGGOSA.js";
|
|
105
|
+
import "./chunk-YQ3U5MUC.js";
|
|
87
106
|
import {
|
|
88
107
|
init_esbuild_shims
|
|
89
|
-
} from "./chunk-
|
|
108
|
+
} from "./chunk-5O2XNYP6.js";
|
|
90
109
|
import {
|
|
91
110
|
__name,
|
|
92
111
|
__toESM
|
|
@@ -95,99 +114,13 @@ import {
|
|
|
95
114
|
// packages/cli/src/serve/run-qwen-serve.ts
|
|
96
115
|
init_esbuild_shims();
|
|
97
116
|
var import_express = __toESM(require_express(), 1);
|
|
98
|
-
import { X509Certificate } from "node:crypto";
|
|
117
|
+
import { X509Certificate, createHash as createHash2, timingSafeEqual } from "node:crypto";
|
|
99
118
|
import * as fs from "node:fs";
|
|
100
119
|
import * as https from "node:https";
|
|
101
120
|
import * as path from "node:path";
|
|
102
121
|
import * as os from "node:os";
|
|
103
122
|
import { monitorEventLoopDelay, performance } from "node:perf_hooks";
|
|
104
123
|
|
|
105
|
-
// packages/cli/src/serve/workspace-inputs.ts
|
|
106
|
-
init_esbuild_shims();
|
|
107
|
-
var DuplicateWorkspaceInputError = class extends Error {
|
|
108
|
-
static {
|
|
109
|
-
__name(this, "DuplicateWorkspaceInputError");
|
|
110
|
-
}
|
|
111
|
-
constructor(workspace) {
|
|
112
|
-
super(
|
|
113
|
-
`Duplicate --workspace value resolves to ${JSON.stringify(workspace)}. Pass distinct --workspace values.`
|
|
114
|
-
);
|
|
115
|
-
this.name = "DuplicateWorkspaceInputError";
|
|
116
|
-
}
|
|
117
|
-
};
|
|
118
|
-
var NestedWorkspaceInputError = class extends Error {
|
|
119
|
-
static {
|
|
120
|
-
__name(this, "NestedWorkspaceInputError");
|
|
121
|
-
}
|
|
122
|
-
constructor(parent, child) {
|
|
123
|
-
super(
|
|
124
|
-
`Nested --workspace values are not supported yet: ${JSON.stringify(child)} is inside ${JSON.stringify(parent)}. Pass non-nested --workspace values.`
|
|
125
|
-
);
|
|
126
|
-
this.name = "NestedWorkspaceInputError";
|
|
127
|
-
}
|
|
128
|
-
};
|
|
129
|
-
var MissingWorkspaceInputError = class extends Error {
|
|
130
|
-
static {
|
|
131
|
-
__name(this, "MissingWorkspaceInputError");
|
|
132
|
-
}
|
|
133
|
-
constructor() {
|
|
134
|
-
super("--workspace requires a value.");
|
|
135
|
-
this.name = "MissingWorkspaceInputError";
|
|
136
|
-
}
|
|
137
|
-
};
|
|
138
|
-
function normalizeWorkspaceInputs(workspace) {
|
|
139
|
-
if (Array.isArray(workspace)) {
|
|
140
|
-
if (workspace.length === 0) {
|
|
141
|
-
throw new MissingWorkspaceInputError();
|
|
142
|
-
}
|
|
143
|
-
return workspace.map((value) => String(value));
|
|
144
|
-
}
|
|
145
|
-
if (workspace === void 0) return [process.cwd()];
|
|
146
|
-
return [String(workspace)];
|
|
147
|
-
}
|
|
148
|
-
__name(normalizeWorkspaceInputs, "normalizeWorkspaceInputs");
|
|
149
|
-
function isNestedWorkspace(parent, child) {
|
|
150
|
-
return parent !== child && isWithinRoot(child, parent);
|
|
151
|
-
}
|
|
152
|
-
__name(isNestedWorkspace, "isNestedWorkspace");
|
|
153
|
-
function rejectDuplicateOrNestedWorkspaceInputs(workspaces) {
|
|
154
|
-
if (workspaces.length <= 1) return;
|
|
155
|
-
let canonicalWorkspaces;
|
|
156
|
-
try {
|
|
157
|
-
canonicalWorkspaces = workspaces.map(
|
|
158
|
-
(workspace) => canonicalizeWorkspace(workspace)
|
|
159
|
-
);
|
|
160
|
-
} catch {
|
|
161
|
-
return;
|
|
162
|
-
}
|
|
163
|
-
const seen = /* @__PURE__ */ new Set();
|
|
164
|
-
for (const workspace of canonicalWorkspaces) {
|
|
165
|
-
if (seen.has(workspace)) {
|
|
166
|
-
throw new DuplicateWorkspaceInputError(workspace);
|
|
167
|
-
}
|
|
168
|
-
seen.add(workspace);
|
|
169
|
-
}
|
|
170
|
-
for (let i = 0; i < canonicalWorkspaces.length; i++) {
|
|
171
|
-
for (let j = i + 1; j < canonicalWorkspaces.length; j++) {
|
|
172
|
-
const first = canonicalWorkspaces[i];
|
|
173
|
-
const second = canonicalWorkspaces[j];
|
|
174
|
-
if (isNestedWorkspace(first, second)) {
|
|
175
|
-
throw new NestedWorkspaceInputError(first, second);
|
|
176
|
-
}
|
|
177
|
-
if (isNestedWorkspace(second, first)) {
|
|
178
|
-
throw new NestedWorkspaceInputError(second, first);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
__name(rejectDuplicateOrNestedWorkspaceInputs, "rejectDuplicateOrNestedWorkspaceInputs");
|
|
184
|
-
function resolveWorkspaceInputs(workspace) {
|
|
185
|
-
const workspaces = normalizeWorkspaceInputs(workspace);
|
|
186
|
-
rejectDuplicateOrNestedWorkspaceInputs(workspaces);
|
|
187
|
-
return workspaces;
|
|
188
|
-
}
|
|
189
|
-
__name(resolveWorkspaceInputs, "resolveWorkspaceInputs");
|
|
190
|
-
|
|
191
124
|
// packages/cli/src/serve/permission-audit.ts
|
|
192
125
|
init_esbuild_shims();
|
|
193
126
|
var DEFAULT_PERMISSION_AUDIT_RING_SIZE = 512;
|
|
@@ -885,6 +818,120 @@ function asRecord(value) {
|
|
|
885
818
|
}
|
|
886
819
|
__name(asRecord, "asRecord");
|
|
887
820
|
|
|
821
|
+
// packages/cli/src/serve/channel-workspace-grouping.ts
|
|
822
|
+
init_esbuild_shims();
|
|
823
|
+
function resolveChannelOwnerCwd(rawCwd, workspaceCwd) {
|
|
824
|
+
return canonicalizeWorkspace(resolveChannelCwd(rawCwd, workspaceCwd));
|
|
825
|
+
}
|
|
826
|
+
__name(resolveChannelOwnerCwd, "resolveChannelOwnerCwd");
|
|
827
|
+
function rawChannelCwd(entry) {
|
|
828
|
+
if (!entry || typeof entry !== "object") return void 0;
|
|
829
|
+
const cwd = entry.cwd;
|
|
830
|
+
return typeof cwd === "string" && cwd.length > 0 ? cwd : void 0;
|
|
831
|
+
}
|
|
832
|
+
__name(rawChannelCwd, "rawChannelCwd");
|
|
833
|
+
function resolveChannelWorkspaceGroups(input) {
|
|
834
|
+
const { workspaces, selection, loadChannelsConfig } = input;
|
|
835
|
+
const primary = workspaces.find((workspace) => workspace.primary);
|
|
836
|
+
if (!primary) {
|
|
837
|
+
return {
|
|
838
|
+
ok: false,
|
|
839
|
+
error: {
|
|
840
|
+
code: "no_primary_workspace",
|
|
841
|
+
message: "No primary workspace is registered."
|
|
842
|
+
}
|
|
843
|
+
};
|
|
844
|
+
}
|
|
845
|
+
if (selection.mode === "all") {
|
|
846
|
+
if (!primary.trusted) {
|
|
847
|
+
return {
|
|
848
|
+
ok: false,
|
|
849
|
+
error: {
|
|
850
|
+
code: "untrusted_workspace",
|
|
851
|
+
message: `Primary workspace "${primary.workspaceCwd}" is not trusted; cannot host channels.`
|
|
852
|
+
}
|
|
853
|
+
};
|
|
854
|
+
}
|
|
855
|
+
return {
|
|
856
|
+
ok: true,
|
|
857
|
+
groups: [
|
|
858
|
+
{ workspaceCwd: primary.workspaceCwd, selection: { mode: "all" } }
|
|
859
|
+
]
|
|
860
|
+
};
|
|
861
|
+
}
|
|
862
|
+
const channelsConfigByWorkspace = /* @__PURE__ */ new Map();
|
|
863
|
+
for (const workspace of workspaces) {
|
|
864
|
+
channelsConfigByWorkspace.set(
|
|
865
|
+
workspace.workspaceCwd,
|
|
866
|
+
loadChannelsConfig(workspace.workspaceCwd)
|
|
867
|
+
);
|
|
868
|
+
}
|
|
869
|
+
const namesByWorkspace = /* @__PURE__ */ new Map();
|
|
870
|
+
for (const name of selection.names) {
|
|
871
|
+
const owners = [];
|
|
872
|
+
for (const workspace of workspaces) {
|
|
873
|
+
const entry = (channelsConfigByWorkspace.get(workspace.workspaceCwd) ?? {})[name];
|
|
874
|
+
if (!entry || typeof entry !== "object") continue;
|
|
875
|
+
let ownerCwd;
|
|
876
|
+
try {
|
|
877
|
+
ownerCwd = resolveChannelOwnerCwd(
|
|
878
|
+
rawChannelCwd(entry),
|
|
879
|
+
workspace.workspaceCwd
|
|
880
|
+
);
|
|
881
|
+
} catch {
|
|
882
|
+
continue;
|
|
883
|
+
}
|
|
884
|
+
if (ownerCwd === workspace.workspaceCwd) {
|
|
885
|
+
owners.push(workspace);
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
if (owners.length === 0) {
|
|
889
|
+
return {
|
|
890
|
+
ok: false,
|
|
891
|
+
error: {
|
|
892
|
+
code: "channel_workspace_mismatch",
|
|
893
|
+
channel: name,
|
|
894
|
+
message: `Channel "${name}" is not configured in any registered workspace, or its "cwd" points outside them.`
|
|
895
|
+
}
|
|
896
|
+
};
|
|
897
|
+
}
|
|
898
|
+
if (owners.length > 1) {
|
|
899
|
+
return {
|
|
900
|
+
ok: false,
|
|
901
|
+
error: {
|
|
902
|
+
code: "ambiguous_channel_workspace",
|
|
903
|
+
channel: name,
|
|
904
|
+
message: `Channel "${name}" is configured in multiple registered workspaces (${owners.map((owner2) => owner2.workspaceCwd).join(
|
|
905
|
+
", "
|
|
906
|
+
)}). Define it in one workspace's settings or set an explicit "cwd".`
|
|
907
|
+
}
|
|
908
|
+
};
|
|
909
|
+
}
|
|
910
|
+
const owner = owners[0];
|
|
911
|
+
if (!owner.trusted) {
|
|
912
|
+
return {
|
|
913
|
+
ok: false,
|
|
914
|
+
error: {
|
|
915
|
+
code: "untrusted_workspace",
|
|
916
|
+
channel: name,
|
|
917
|
+
message: `Channel "${name}" targets untrusted workspace "${owner.workspaceCwd}".`
|
|
918
|
+
}
|
|
919
|
+
};
|
|
920
|
+
}
|
|
921
|
+
const names = namesByWorkspace.get(owner.workspaceCwd) ?? [];
|
|
922
|
+
names.push(name);
|
|
923
|
+
namesByWorkspace.set(owner.workspaceCwd, names);
|
|
924
|
+
}
|
|
925
|
+
return {
|
|
926
|
+
ok: true,
|
|
927
|
+
groups: [...namesByWorkspace.entries()].map(([workspaceCwd, names]) => ({
|
|
928
|
+
workspaceCwd,
|
|
929
|
+
selection: { mode: "names", names }
|
|
930
|
+
}))
|
|
931
|
+
};
|
|
932
|
+
}
|
|
933
|
+
__name(resolveChannelWorkspaceGroups, "resolveChannelWorkspaceGroups");
|
|
934
|
+
|
|
888
935
|
// packages/cli/src/serve/run-qwen-serve.ts
|
|
889
936
|
var QWEN_SERVE_CLIENT_MCP_OVER_WS_ENV = "QWEN_SERVE_CLIENT_MCP_OVER_WS";
|
|
890
937
|
var QWEN_SERVE_CDP_TUNNEL_OVER_WS_ENV = "QWEN_SERVE_CDP_TUNNEL_OVER_WS";
|
|
@@ -1074,6 +1121,10 @@ function extractContextFilename(value) {
|
|
|
1074
1121
|
return void 0;
|
|
1075
1122
|
}
|
|
1076
1123
|
__name(extractContextFilename, "extractContextFilename");
|
|
1124
|
+
function sessionArtifactsPersistenceAvailableFromSettings(settings) {
|
|
1125
|
+
return settings?.general?.chatRecording !== false;
|
|
1126
|
+
}
|
|
1127
|
+
__name(sessionArtifactsPersistenceAvailableFromSettings, "sessionArtifactsPersistenceAvailableFromSettings");
|
|
1077
1128
|
var settingsWriteLocks = /* @__PURE__ */ new Map();
|
|
1078
1129
|
function withSettingsLock(workspace, fn) {
|
|
1079
1130
|
const prev = settingsWriteLocks.get(workspace) ?? Promise.resolve();
|
|
@@ -1085,12 +1136,29 @@ __name(withSettingsLock, "withSettingsLock");
|
|
|
1085
1136
|
var channelWorkerRuntimePromise;
|
|
1086
1137
|
async function loadChannelWorkerRuntime() {
|
|
1087
1138
|
channelWorkerRuntimePromise ??= Promise.all([
|
|
1088
|
-
import("./channel-worker-supervisor-
|
|
1089
|
-
import("./pidfile-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1139
|
+
import("./channel-worker-supervisor-QCKIOYZD.js"),
|
|
1140
|
+
import("./pidfile-AUMGYIOK.js"),
|
|
1141
|
+
import("./runtime-NYUSLBEZ.js"),
|
|
1142
|
+
import("./cli-entry-path-4VJ3Y6T2.js"),
|
|
1143
|
+
import("./channel-worker-group-K7QKH6IG.js"),
|
|
1144
|
+
import("./channel-worker-manager-YSFB4HUU.js")
|
|
1145
|
+
]).then(
|
|
1146
|
+
([
|
|
1147
|
+
supervisor,
|
|
1148
|
+
pidfile,
|
|
1149
|
+
channelRuntime,
|
|
1150
|
+
cliEntryPath,
|
|
1151
|
+
workerGroup,
|
|
1152
|
+
workerManager
|
|
1153
|
+
]) => ({
|
|
1154
|
+
createChannelWorkerSupervisor: supervisor.createChannelWorkerSupervisor,
|
|
1155
|
+
channelServicePidfile: pidfile,
|
|
1156
|
+
loadChannelsConfig: channelRuntime.loadChannelsConfig,
|
|
1157
|
+
createChannelWorkerGroup: workerGroup.createChannelWorkerGroup,
|
|
1158
|
+
createChannelWorkerManager: workerManager.createChannelWorkerManager,
|
|
1159
|
+
findCliEntryPath: cliEntryPath.findCliEntryPath
|
|
1160
|
+
})
|
|
1161
|
+
).catch((err) => {
|
|
1094
1162
|
channelWorkerRuntimePromise = void 0;
|
|
1095
1163
|
throw err;
|
|
1096
1164
|
});
|
|
@@ -1108,9 +1176,18 @@ function createDisabledChannelWorkerSupervisor() {
|
|
|
1108
1176
|
},
|
|
1109
1177
|
async stop() {
|
|
1110
1178
|
},
|
|
1179
|
+
async restart() {
|
|
1180
|
+
return { ...snapshot, channels: [] };
|
|
1181
|
+
},
|
|
1111
1182
|
killAllSync() {
|
|
1112
1183
|
},
|
|
1113
|
-
snapshot: /* @__PURE__ */ __name(() => ({ ...snapshot, channels: [] }), "snapshot")
|
|
1184
|
+
snapshot: /* @__PURE__ */ __name(() => ({ ...snapshot, channels: [] }), "snapshot"),
|
|
1185
|
+
async enqueueWebhookTask() {
|
|
1186
|
+
throw new ChannelWebhookEnqueueError(
|
|
1187
|
+
"channel_worker_unavailable",
|
|
1188
|
+
"Channel worker is not running."
|
|
1189
|
+
);
|
|
1190
|
+
}
|
|
1114
1191
|
};
|
|
1115
1192
|
}
|
|
1116
1193
|
__name(createDisabledChannelWorkerSupervisor, "createDisabledChannelWorkerSupervisor");
|
|
@@ -1123,11 +1200,23 @@ function writeServeChannelReservation(channelServicePidfile, channels) {
|
|
|
1123
1200
|
__name(writeServeChannelReservation, "writeServeChannelReservation");
|
|
1124
1201
|
function channelServicePidfileConflictError(info) {
|
|
1125
1202
|
const owner = info.owner === "serve" ? "qwen serve" : "qwen channel start";
|
|
1126
|
-
return
|
|
1127
|
-
|
|
1203
|
+
return Object.assign(
|
|
1204
|
+
new Error(
|
|
1205
|
+
`Channel service is already running under ${owner} (PID ${info.pid}). Stop it before enabling daemon-managed channels.`
|
|
1206
|
+
),
|
|
1207
|
+
{ code: "channel_service_conflict", owner: info.owner, pid: info.pid }
|
|
1128
1208
|
);
|
|
1129
1209
|
}
|
|
1130
1210
|
__name(channelServicePidfileConflictError, "channelServicePidfileConflictError");
|
|
1211
|
+
function channelServiceStartingConflictError() {
|
|
1212
|
+
return Object.assign(
|
|
1213
|
+
new Error(
|
|
1214
|
+
"Channel service is already starting. Retry after the current startup finishes."
|
|
1215
|
+
),
|
|
1216
|
+
{ code: "channel_service_conflict" }
|
|
1217
|
+
);
|
|
1218
|
+
}
|
|
1219
|
+
__name(channelServiceStartingConflictError, "channelServiceStartingConflictError");
|
|
1131
1220
|
function normalizeInstallModelIds(req, provider, getDefaultModelIds) {
|
|
1132
1221
|
const fromRequest = req.modelIds?.map((id) => id.trim()).filter((id) => id.length > 0);
|
|
1133
1222
|
const modelIds = fromRequest && fromRequest.length > 0 ? fromRequest : getDefaultModelIds(provider);
|
|
@@ -1157,7 +1246,7 @@ function shouldPreheatBridge(deps) {
|
|
|
1157
1246
|
__name(shouldPreheatBridge, "shouldPreheatBridge");
|
|
1158
1247
|
var coreRuntimePromise;
|
|
1159
1248
|
function loadCoreRuntime() {
|
|
1160
|
-
coreRuntimePromise ??= import("./src-
|
|
1249
|
+
coreRuntimePromise ??= import("./src-YDBNMIIM.js");
|
|
1161
1250
|
return coreRuntimePromise;
|
|
1162
1251
|
}
|
|
1163
1252
|
__name(loadCoreRuntime, "loadCoreRuntime");
|
|
@@ -1187,10 +1276,10 @@ __name(resolveDaemonLogBaseDirForRun, "resolveDaemonLogBaseDirForRun");
|
|
|
1187
1276
|
var settingsRuntimePromise;
|
|
1188
1277
|
function loadSettingsRuntimeModules() {
|
|
1189
1278
|
settingsRuntimePromise ??= Promise.all([
|
|
1190
|
-
import("./settings-
|
|
1191
|
-
import("./environment-
|
|
1192
|
-
import("./loadedSettingsAdapter-
|
|
1193
|
-
import("./trustedFolders-
|
|
1279
|
+
import("./settings-X24RYEED.js"),
|
|
1280
|
+
import("./environment-OYA3ZVEL.js"),
|
|
1281
|
+
import("./loadedSettingsAdapter-V4ZTRKUO.js"),
|
|
1282
|
+
import("./trustedFolders-JF265CRI.js")
|
|
1194
1283
|
]).then(([settings, environment, loadedSettingsAdapter, trustedFolders]) => ({
|
|
1195
1284
|
settings,
|
|
1196
1285
|
environment,
|
|
@@ -1200,6 +1289,21 @@ function loadSettingsRuntimeModules() {
|
|
|
1200
1289
|
return settingsRuntimePromise;
|
|
1201
1290
|
}
|
|
1202
1291
|
__name(loadSettingsRuntimeModules, "loadSettingsRuntimeModules");
|
|
1292
|
+
var channelWebhookConfigRuntimePromise;
|
|
1293
|
+
function loadChannelWebhookConfigRuntime() {
|
|
1294
|
+
channelWebhookConfigRuntimePromise ??= Promise.all([
|
|
1295
|
+
import("./runtime-NYUSLBEZ.js"),
|
|
1296
|
+
import("./config-utils-XSHOMMK4.js")
|
|
1297
|
+
]).then(([channelRuntime, configUtils]) => ({
|
|
1298
|
+
loadChannelsConfig: channelRuntime.loadChannelsConfig,
|
|
1299
|
+
parseChannelWebhookConfig: configUtils.parseChannelWebhookConfig
|
|
1300
|
+
})).catch((err) => {
|
|
1301
|
+
channelWebhookConfigRuntimePromise = void 0;
|
|
1302
|
+
throw err;
|
|
1303
|
+
});
|
|
1304
|
+
return channelWebhookConfigRuntimePromise;
|
|
1305
|
+
}
|
|
1306
|
+
__name(loadChannelWebhookConfigRuntime, "loadChannelWebhookConfigRuntime");
|
|
1203
1307
|
async function loadServeRuntimeModules() {
|
|
1204
1308
|
const [
|
|
1205
1309
|
serverModule,
|
|
@@ -1213,16 +1317,16 @@ async function loadServeRuntimeModules() {
|
|
|
1213
1317
|
totalSessionAdmissionModule,
|
|
1214
1318
|
workspaceRegistryModule
|
|
1215
1319
|
] = await Promise.all([
|
|
1216
|
-
import("./server-
|
|
1217
|
-
import("./bridge-
|
|
1218
|
-
import("./spawnChannel-
|
|
1219
|
-
import("./workspace-service-
|
|
1220
|
-
import("./types-
|
|
1221
|
-
import("./daemon-status-provider-
|
|
1222
|
-
import("./workspace-providers-status-
|
|
1223
|
-
import("./workspace-skills-status-
|
|
1224
|
-
import("./total-session-admission-
|
|
1225
|
-
import("./workspace-registry-
|
|
1320
|
+
import("./server-VUHSYSUV.js"),
|
|
1321
|
+
import("./bridge-HKEWPNB5.js"),
|
|
1322
|
+
import("./spawnChannel-RFAAO44J.js"),
|
|
1323
|
+
import("./workspace-service-PUYIZ3J4.js"),
|
|
1324
|
+
import("./types-ML3TRJQ5.js"),
|
|
1325
|
+
import("./daemon-status-provider-KFL3LRTP.js"),
|
|
1326
|
+
import("./workspace-providers-status-LMBLBNR7.js"),
|
|
1327
|
+
import("./workspace-skills-status-CJ7J2KPP.js"),
|
|
1328
|
+
import("./total-session-admission-2WIH72I3.js"),
|
|
1329
|
+
import("./workspace-registry-BVMPYRLN.js")
|
|
1226
1330
|
]);
|
|
1227
1331
|
return {
|
|
1228
1332
|
createServeApp: serverModule.createServeApp,
|
|
@@ -1233,11 +1337,13 @@ async function loadServeRuntimeModules() {
|
|
|
1233
1337
|
createSpawnChannelFactory: spawnChannelModule.createSpawnChannelFactory,
|
|
1234
1338
|
createDaemonWorkspaceService: workspaceModule.createDaemonWorkspaceService,
|
|
1235
1339
|
WorkspaceSettingsPartialPersistError: workspaceTypesModule.WorkspaceSettingsPartialPersistError,
|
|
1340
|
+
WorkspaceSkillNotToggleableError: workspaceTypesModule.WorkspaceSkillNotToggleableError,
|
|
1236
1341
|
createDaemonStatusProvider: daemonStatusProviderModule.createDaemonStatusProvider,
|
|
1237
1342
|
createWorkspaceProvidersStatusProvider: workspaceProvidersStatusModule.createWorkspaceProvidersStatusProvider,
|
|
1238
1343
|
createWorkspaceSkillsStatusProvider: workspaceSkillsStatusModule.createWorkspaceSkillsStatusProvider,
|
|
1239
1344
|
createTotalSessionAdmissionController: totalSessionAdmissionModule.createTotalSessionAdmissionController,
|
|
1240
|
-
createWorkspaceRegistry: workspaceRegistryModule.createWorkspaceRegistry
|
|
1345
|
+
createWorkspaceRegistry: workspaceRegistryModule.createWorkspaceRegistry,
|
|
1346
|
+
createWorkspaceSessionOwnerIndex: workspaceRegistryModule.createWorkspaceSessionOwnerIndex
|
|
1241
1347
|
};
|
|
1242
1348
|
}
|
|
1243
1349
|
__name(loadServeRuntimeModules, "loadServeRuntimeModules");
|
|
@@ -1261,7 +1367,7 @@ function sessionIdleTimeoutMs(value) {
|
|
|
1261
1367
|
return value !== void 0 ? channelIdleTimeoutMs(value) : DEFAULT_SESSION_IDLE_TIMEOUT_MS;
|
|
1262
1368
|
}
|
|
1263
1369
|
__name(sessionIdleTimeoutMs, "sessionIdleTimeoutMs");
|
|
1264
|
-
function currentServeFeaturesForRunQwenServe(opts, sessionShellCommandEnabled) {
|
|
1370
|
+
function currentServeFeaturesForRunQwenServe(opts, sessionShellCommandEnabled, sessionArtifactsPersistenceAvailable, env) {
|
|
1265
1371
|
return getAdvertisedServeFeatures(void 0, {
|
|
1266
1372
|
requireAuth: opts.requireAuth === true,
|
|
1267
1373
|
mcpPoolActive: opts.mcpPoolActive !== false,
|
|
@@ -1270,12 +1376,18 @@ function currentServeFeaturesForRunQwenServe(opts, sessionShellCommandEnabled) {
|
|
|
1270
1376
|
...opts.writerIdleTimeoutMs !== void 0 ? { writerIdleTimeoutMs: opts.writerIdleTimeoutMs } : {},
|
|
1271
1377
|
persistSettingAvailable: true,
|
|
1272
1378
|
sessionShellCommandEnabled,
|
|
1379
|
+
sessionArtifactsPersistenceAvailable,
|
|
1273
1380
|
rateLimit: opts.rateLimit === true,
|
|
1274
1381
|
reloadAvailable: true,
|
|
1382
|
+
channelReloadAvailable: opts.channelSelection !== void 0,
|
|
1383
|
+
channelControlAvailable: true,
|
|
1384
|
+
persistentWorkspaceRegistrationAvailable: true,
|
|
1385
|
+
workspaceRuntimeRemovalAvailable: true,
|
|
1275
1386
|
// Advertise the same WS feature flags as the runtime path (serve-features.ts)
|
|
1276
1387
|
// so the bootstrap `/capabilities` window doesn't briefly under-report them.
|
|
1277
1388
|
clientMcpOverWsEnabled: opts.clientMcpOverWs === true,
|
|
1278
|
-
cdpTunnelOverWsEnabled: opts.cdpTunnelOverWs === true
|
|
1389
|
+
cdpTunnelOverWsEnabled: opts.cdpTunnelOverWs === true,
|
|
1390
|
+
browserAutomationMcpAvailable: isBrowserAutomationMcpAvailable(opts, env)
|
|
1279
1391
|
});
|
|
1280
1392
|
}
|
|
1281
1393
|
__name(currentServeFeaturesForRunQwenServe, "currentServeFeaturesForRunQwenServe");
|
|
@@ -1287,7 +1399,9 @@ function createBootstrapCapabilities(input) {
|
|
|
1287
1399
|
mode: input.opts.mode,
|
|
1288
1400
|
features: currentServeFeaturesForRunQwenServe(
|
|
1289
1401
|
input.opts,
|
|
1290
|
-
input.sessionShellCommandEnabled
|
|
1402
|
+
input.sessionShellCommandEnabled,
|
|
1403
|
+
input.sessionArtifactsPersistenceAvailable,
|
|
1404
|
+
input.env
|
|
1291
1405
|
),
|
|
1292
1406
|
modelServices: [],
|
|
1293
1407
|
workspaceCwd: input.boundWorkspace,
|
|
@@ -1432,10 +1546,12 @@ function createBootstrapServeApp(input) {
|
|
|
1432
1546
|
daemonLog,
|
|
1433
1547
|
qwenCodeVersion,
|
|
1434
1548
|
sessionShellCommandEnabled,
|
|
1549
|
+
sessionArtifactsPersistenceAvailable,
|
|
1435
1550
|
permissionPolicy,
|
|
1436
1551
|
multiWorkspaceCapabilitiesRequireRuntime,
|
|
1437
1552
|
getRuntimeError,
|
|
1438
1553
|
getChannelWorkerSnapshot,
|
|
1554
|
+
getChannelWorkerSnapshots,
|
|
1439
1555
|
onHealthServed
|
|
1440
1556
|
} = input;
|
|
1441
1557
|
const app = (0, import_express.default)();
|
|
@@ -1487,7 +1603,9 @@ function createBootstrapServeApp(input) {
|
|
|
1487
1603
|
boundWorkspace,
|
|
1488
1604
|
qwenCodeVersion,
|
|
1489
1605
|
sessionShellCommandEnabled,
|
|
1490
|
-
|
|
1606
|
+
sessionArtifactsPersistenceAvailable,
|
|
1607
|
+
permissionPolicy,
|
|
1608
|
+
env: process.env
|
|
1491
1609
|
})
|
|
1492
1610
|
);
|
|
1493
1611
|
});
|
|
@@ -1502,6 +1620,7 @@ function createBootstrapServeApp(input) {
|
|
|
1502
1620
|
}
|
|
1503
1621
|
const runtimeError = getRuntimeError();
|
|
1504
1622
|
const channelWorker = getChannelWorkerSnapshot();
|
|
1623
|
+
const channelWorkers = getChannelWorkerSnapshots();
|
|
1505
1624
|
const runtimeFailed = runtimeError !== void 0;
|
|
1506
1625
|
const issue = runtimeError ? {
|
|
1507
1626
|
code: "daemon_runtime_failed",
|
|
@@ -1558,7 +1677,9 @@ function createBootstrapServeApp(input) {
|
|
|
1558
1677
|
protocolVersions: getServeProtocolVersions(),
|
|
1559
1678
|
features: currentServeFeaturesForRunQwenServe(
|
|
1560
1679
|
opts,
|
|
1561
|
-
sessionShellCommandEnabled
|
|
1680
|
+
sessionShellCommandEnabled,
|
|
1681
|
+
sessionArtifactsPersistenceAvailable,
|
|
1682
|
+
process.env
|
|
1562
1683
|
)
|
|
1563
1684
|
},
|
|
1564
1685
|
runtime: {
|
|
@@ -1571,6 +1692,7 @@ function createBootstrapServeApp(input) {
|
|
|
1571
1692
|
},
|
|
1572
1693
|
channel: { live: false },
|
|
1573
1694
|
channelWorker,
|
|
1695
|
+
...channelWorkers.length > 0 ? { channelWorkers } : {},
|
|
1574
1696
|
transport: {
|
|
1575
1697
|
restSseActive: 0,
|
|
1576
1698
|
acp: {
|
|
@@ -1630,13 +1752,12 @@ function createDelegatingServeApp(bootstrapApp, getRuntimeApp, options = {}) {
|
|
|
1630
1752
|
const dispatch = /* @__PURE__ */ __name(async () => {
|
|
1631
1753
|
let target = getRuntimeApp();
|
|
1632
1754
|
if (!target && options.waitForDeferredRuntimeRoutes === true && !isBootstrapServeRoute(req) && !isCorsPreflightRequest(req) && options.startRuntime && options.runtimeReady) {
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
res,
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
return;
|
|
1755
|
+
const webhookRequest = isChannelWebhookRequest(req);
|
|
1756
|
+
const authGate = webhookRequest ? options.authenticateDeferredChannelWebhookRequest ?? options.authenticateDeferredRuntimeRequest : options.authenticateDeferredRuntimeRequest;
|
|
1757
|
+
if (authGate) {
|
|
1758
|
+
if (!runSynchronousRequestGate(authGate, req, res, next)) {
|
|
1759
|
+
return;
|
|
1760
|
+
}
|
|
1640
1761
|
}
|
|
1641
1762
|
options.startRuntime();
|
|
1642
1763
|
try {
|
|
@@ -1658,6 +1779,83 @@ function isBootstrapServeRoute(req) {
|
|
|
1658
1779
|
return BOOTSTRAP_SERVE_PATHS.has(path2);
|
|
1659
1780
|
}
|
|
1660
1781
|
__name(isBootstrapServeRoute, "isBootstrapServeRoute");
|
|
1782
|
+
function isChannelWebhookRequest(req) {
|
|
1783
|
+
return req.method === "POST" && /^\/channels\/[^/]+\/webhooks\/[^/]+\/?$/u.test(req.path);
|
|
1784
|
+
}
|
|
1785
|
+
__name(isChannelWebhookRequest, "isChannelWebhookRequest");
|
|
1786
|
+
function createDeferredChannelWebhookAuth(resolveSource, runtime, daemonLog) {
|
|
1787
|
+
return (req, res, next) => {
|
|
1788
|
+
const match = /^\/channels\/([^/]+)\/webhooks\/([^/]+)\/?$/u.exec(req.path);
|
|
1789
|
+
const channelName = decodeDeferredWebhookPathSegment(match?.[1]);
|
|
1790
|
+
const source = decodeDeferredWebhookPathSegment(match?.[2]);
|
|
1791
|
+
if (!channelName || !source) {
|
|
1792
|
+
daemonLog.warn("deferred webhook auth failed", {
|
|
1793
|
+
channelName: channelName ?? "unknown",
|
|
1794
|
+
source: source ?? "unknown",
|
|
1795
|
+
reason: "invalid webhook path"
|
|
1796
|
+
});
|
|
1797
|
+
res.status(401).json({ error: "Invalid webhook secret" });
|
|
1798
|
+
return;
|
|
1799
|
+
}
|
|
1800
|
+
const configSource = resolveSource(channelName);
|
|
1801
|
+
const secret = readDeferredWebhookSecret(
|
|
1802
|
+
runtime,
|
|
1803
|
+
configSource.workspaceCwd,
|
|
1804
|
+
channelName,
|
|
1805
|
+
source,
|
|
1806
|
+
configSource.env
|
|
1807
|
+
);
|
|
1808
|
+
if (!matchesWebhookSecret(req.get("x-qwen-webhook-secret"), secret)) {
|
|
1809
|
+
daemonLog.warn("deferred webhook auth failed", {
|
|
1810
|
+
channelName,
|
|
1811
|
+
source,
|
|
1812
|
+
reason: secret ? "secret mismatch" : "source not configured"
|
|
1813
|
+
});
|
|
1814
|
+
res.status(401).json({ error: "Invalid webhook secret" });
|
|
1815
|
+
return;
|
|
1816
|
+
}
|
|
1817
|
+
next();
|
|
1818
|
+
};
|
|
1819
|
+
}
|
|
1820
|
+
__name(createDeferredChannelWebhookAuth, "createDeferredChannelWebhookAuth");
|
|
1821
|
+
function decodeDeferredWebhookPathSegment(segment) {
|
|
1822
|
+
if (segment === void 0) return void 0;
|
|
1823
|
+
try {
|
|
1824
|
+
return decodeURIComponent(segment);
|
|
1825
|
+
} catch {
|
|
1826
|
+
return void 0;
|
|
1827
|
+
}
|
|
1828
|
+
}
|
|
1829
|
+
__name(decodeDeferredWebhookPathSegment, "decodeDeferredWebhookPathSegment");
|
|
1830
|
+
function readDeferredWebhookSecret(runtime, workspace, channelName, source, env) {
|
|
1831
|
+
try {
|
|
1832
|
+
const rawConfig = runtime.loadChannelsConfig(workspace)[channelName];
|
|
1833
|
+
if (typeof rawConfig !== "object" || rawConfig === null) {
|
|
1834
|
+
return void 0;
|
|
1835
|
+
}
|
|
1836
|
+
return runtime.parseChannelWebhookConfig(
|
|
1837
|
+
channelName,
|
|
1838
|
+
rawConfig,
|
|
1839
|
+
env
|
|
1840
|
+
)?.sources[source]?.secret;
|
|
1841
|
+
} catch (err) {
|
|
1842
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
1843
|
+
writeStderrLine(
|
|
1844
|
+
`[webhook-secret] failed to read deferred webhook secret for ${sanitizeLogText(channelName, 128)}/${sanitizeLogText(source, 128)}: ${sanitizeLogText(reason, 512)}`
|
|
1845
|
+
);
|
|
1846
|
+
return void 0;
|
|
1847
|
+
}
|
|
1848
|
+
}
|
|
1849
|
+
__name(readDeferredWebhookSecret, "readDeferredWebhookSecret");
|
|
1850
|
+
function matchesWebhookSecret(candidate, expected) {
|
|
1851
|
+
if (typeof candidate !== "string" || typeof expected !== "string" || expected.length === 0) {
|
|
1852
|
+
return false;
|
|
1853
|
+
}
|
|
1854
|
+
const expectedDigest = createHash2("sha256").update(expected).digest();
|
|
1855
|
+
const candidateDigest = createHash2("sha256").update(candidate).digest();
|
|
1856
|
+
return timingSafeEqual(expectedDigest, candidateDigest);
|
|
1857
|
+
}
|
|
1858
|
+
__name(matchesWebhookSecret, "matchesWebhookSecret");
|
|
1661
1859
|
function isCorsPreflightRequest(req) {
|
|
1662
1860
|
return req.method === "OPTIONS" && Boolean(req.headers.origin) && Boolean(
|
|
1663
1861
|
req.headers["access-control-request-method"] || req.headers["access-control-request-headers"]
|
|
@@ -1723,30 +1921,42 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
1723
1921
|
clientMcpOverWs: optsIn.clientMcpOverWs ?? (!envFlagDisabled(clientMcpOverWsEnv) && clientMcpOverWsEnv !== void 0),
|
|
1724
1922
|
cdpTunnelOverWs: optsIn.cdpTunnelOverWs ?? (!envFlagDisabled(cdpTunnelOverWsEnv) && (cdpTunnelOverWsEnv !== void 0 || chromeExtensionOriginAllowed))
|
|
1725
1923
|
};
|
|
1726
|
-
|
|
1727
|
-
|
|
1924
|
+
let channelRuntime = opts.channelSelection ? await loadChannelWorkerRuntime() : void 0;
|
|
1925
|
+
let channelServicePidfile = deps.channelServicePidfile ?? channelRuntime?.channelServicePidfile;
|
|
1926
|
+
const ensureChannelRuntime = /* @__PURE__ */ __name(async () => {
|
|
1927
|
+
channelRuntime ??= await loadChannelWorkerRuntime();
|
|
1928
|
+
channelServicePidfile ??= channelRuntime.channelServicePidfile;
|
|
1929
|
+
return channelRuntime;
|
|
1930
|
+
}, "ensureChannelRuntime");
|
|
1728
1931
|
let channelPidfileReserved = false;
|
|
1729
1932
|
const removeCurrentServePidfile = /* @__PURE__ */ __name(() => {
|
|
1730
|
-
if (!
|
|
1933
|
+
if (!channelServicePidfile) return;
|
|
1731
1934
|
if (!channelPidfileReserved) return;
|
|
1732
1935
|
if (channelServicePidfile.removeServeServiceInfo) {
|
|
1733
1936
|
if (channelServicePidfile.removeServeServiceInfo(process.pid)) {
|
|
1734
1937
|
channelPidfileReserved = false;
|
|
1938
|
+
} else {
|
|
1939
|
+
const info2 = channelServicePidfile.readServiceInfo();
|
|
1940
|
+
if (!info2 || info2.owner !== "serve" || info2.pid !== process.pid || info2.servePid !== process.pid) {
|
|
1941
|
+
channelPidfileReserved = false;
|
|
1942
|
+
}
|
|
1735
1943
|
}
|
|
1736
1944
|
return;
|
|
1737
1945
|
}
|
|
1738
1946
|
const info = channelServicePidfile.readServiceInfo();
|
|
1739
1947
|
if (info?.owner === "serve" && info.pid === process.pid && info.servePid === process.pid) {
|
|
1740
1948
|
channelServicePidfile.removeServiceInfo();
|
|
1949
|
+
const remaining = channelServicePidfile.readServiceInfo();
|
|
1950
|
+
channelPidfileReserved = remaining?.owner === "serve" && remaining.pid === process.pid && remaining.servePid === process.pid;
|
|
1951
|
+
} else {
|
|
1741
1952
|
channelPidfileReserved = false;
|
|
1742
1953
|
}
|
|
1743
1954
|
}, "removeCurrentServePidfile");
|
|
1744
|
-
const reserveChannelServicePidfile = /* @__PURE__ */ __name(() => {
|
|
1745
|
-
if (!opts.channelSelection) return;
|
|
1955
|
+
const reserveChannelServicePidfile = /* @__PURE__ */ __name((selection) => {
|
|
1746
1956
|
if (!channelServicePidfile) {
|
|
1747
1957
|
throw new Error("Channel service pidfile runtime is not available.");
|
|
1748
1958
|
}
|
|
1749
|
-
const channelPidfileNames = channelSelectionNames(
|
|
1959
|
+
const channelPidfileNames = channelSelectionNames(selection);
|
|
1750
1960
|
const existingChannelService = channelServicePidfile.readServiceInfo();
|
|
1751
1961
|
if (existingChannelService) {
|
|
1752
1962
|
throw channelServicePidfileConflictError(existingChannelService);
|
|
@@ -1771,9 +1981,7 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
1771
1981
|
return;
|
|
1772
1982
|
} catch (retryErr) {
|
|
1773
1983
|
if (retryErr && typeof retryErr === "object" && "code" in retryErr && retryErr.code === "EEXIST") {
|
|
1774
|
-
throw
|
|
1775
|
-
"Channel service is already starting. Retry after the current startup finishes."
|
|
1776
|
-
);
|
|
1984
|
+
throw channelServiceStartingConflictError();
|
|
1777
1985
|
}
|
|
1778
1986
|
throw retryErr;
|
|
1779
1987
|
}
|
|
@@ -1892,7 +2100,9 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
1892
2100
|
}, "validateAndCanonicalizeWorkspace");
|
|
1893
2101
|
const workspaceInputs = rawWorkspaces.map((workspace) => ({
|
|
1894
2102
|
raw: workspace,
|
|
1895
|
-
cwd: validateAndCanonicalizeWorkspace(workspace)
|
|
2103
|
+
cwd: validateAndCanonicalizeWorkspace(workspace),
|
|
2104
|
+
removable: false,
|
|
2105
|
+
registrationIds: []
|
|
1896
2106
|
}));
|
|
1897
2107
|
const boundWorkspace = workspaceInputs[0].cwd;
|
|
1898
2108
|
const seenCanonicalWorkspaces = /* @__PURE__ */ new Set();
|
|
@@ -1924,6 +2134,71 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
1924
2134
|
}
|
|
1925
2135
|
}
|
|
1926
2136
|
}
|
|
2137
|
+
if (workspaceInputs.length > MAX_REGISTERED_WORKSPACES) {
|
|
2138
|
+
throw new Error(
|
|
2139
|
+
`At most ${MAX_REGISTERED_WORKSPACES} --workspace values may be registered.`
|
|
2140
|
+
);
|
|
2141
|
+
}
|
|
2142
|
+
let workspaceRegistrationStore = deps.workspaceRegistrationStore;
|
|
2143
|
+
if (workspaceRegistrationStore === void 0 && process.env["QWEN_SERVE_NO_PERSISTENT_REGISTRATION"] !== "1") {
|
|
2144
|
+
const { WorkspaceRegistrationStore } = await import("./workspace-registration-store-VV2S4MSV.js");
|
|
2145
|
+
workspaceRegistrationStore = new WorkspaceRegistrationStore(boundWorkspace);
|
|
2146
|
+
}
|
|
2147
|
+
if (workspaceRegistrationStore) {
|
|
2148
|
+
try {
|
|
2149
|
+
const stored = await workspaceRegistrationStore.read();
|
|
2150
|
+
for (const storedWorkspace of stored.workspaces) {
|
|
2151
|
+
const registrationId = workspaceRegistrationId(storedWorkspace);
|
|
2152
|
+
let cwd;
|
|
2153
|
+
try {
|
|
2154
|
+
cwd = validateAndCanonicalizeWorkspace(storedWorkspace);
|
|
2155
|
+
} catch (err) {
|
|
2156
|
+
writeStderrLine(
|
|
2157
|
+
`qwen serve: skipping persisted workspace registration ${JSON.stringify(
|
|
2158
|
+
storedWorkspace
|
|
2159
|
+
)}: ${err instanceof Error ? err.message : String(err)}`
|
|
2160
|
+
);
|
|
2161
|
+
continue;
|
|
2162
|
+
}
|
|
2163
|
+
const existingInput = workspaceInputs.find(
|
|
2164
|
+
(workspace) => workspace.cwd === cwd
|
|
2165
|
+
);
|
|
2166
|
+
if (existingInput) {
|
|
2167
|
+
existingInput.registrationIds.push(registrationId);
|
|
2168
|
+
continue;
|
|
2169
|
+
}
|
|
2170
|
+
const nested = workspaceInputs.some(
|
|
2171
|
+
(workspace) => isWithinRoot(cwd, workspace.cwd) || isWithinRoot(workspace.cwd, cwd)
|
|
2172
|
+
);
|
|
2173
|
+
if (nested) {
|
|
2174
|
+
writeStderrLine(
|
|
2175
|
+
`qwen serve: skipping persisted workspace registration ${JSON.stringify(
|
|
2176
|
+
storedWorkspace
|
|
2177
|
+
)}: path nests with an explicit or earlier restored workspace`
|
|
2178
|
+
);
|
|
2179
|
+
continue;
|
|
2180
|
+
}
|
|
2181
|
+
if (workspaceInputs.length >= MAX_REGISTERED_WORKSPACES) {
|
|
2182
|
+
writeStderrLine(
|
|
2183
|
+
`qwen serve: skipping persisted workspace registration ${JSON.stringify(
|
|
2184
|
+
storedWorkspace
|
|
2185
|
+
)}: workspace limit reached`
|
|
2186
|
+
);
|
|
2187
|
+
continue;
|
|
2188
|
+
}
|
|
2189
|
+
workspaceInputs.push({
|
|
2190
|
+
raw: storedWorkspace,
|
|
2191
|
+
cwd,
|
|
2192
|
+
removable: true,
|
|
2193
|
+
registrationIds: [registrationId]
|
|
2194
|
+
});
|
|
2195
|
+
}
|
|
2196
|
+
} catch (err) {
|
|
2197
|
+
writeStderrLine(
|
|
2198
|
+
`qwen serve: failed to read persisted workspace registrations: ${err instanceof Error ? err.message : String(err)}; continuing with explicit workspaces only`
|
|
2199
|
+
);
|
|
2200
|
+
}
|
|
2201
|
+
}
|
|
1927
2202
|
if (workspaceInputs.length > 1 && deps.bridge) {
|
|
1928
2203
|
throw new Error(
|
|
1929
2204
|
"Injected bridge dependencies are only supported with a single workspace; multiple --workspace values require runQwenServe to construct one bridge per workspace."
|
|
@@ -1933,8 +2208,10 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
1933
2208
|
let permissionPolicy;
|
|
1934
2209
|
let permissionConsensusQuorum;
|
|
1935
2210
|
let bootSettings;
|
|
2211
|
+
let sessionArtifactsPersistenceAvailable = true;
|
|
1936
2212
|
try {
|
|
1937
2213
|
bootSettings = deps.bootSettings ?? loadServeFastPathSettings(boundWorkspace);
|
|
2214
|
+
sessionArtifactsPersistenceAvailable = sessionArtifactsPersistenceAvailableFromSettings(bootSettings);
|
|
1938
2215
|
contextFilenameForInit = extractContextFilename(
|
|
1939
2216
|
bootSettings.context?.fileName
|
|
1940
2217
|
);
|
|
@@ -2107,20 +2384,139 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
2107
2384
|
void runtimeReady.catch(() => {
|
|
2108
2385
|
});
|
|
2109
2386
|
const disposeDaemonEventLoopMonitor = /* @__PURE__ */ __name(() => {
|
|
2110
|
-
daemonEventLoopMonitor
|
|
2387
|
+
const eventLoopMonitor = daemonEventLoopMonitor;
|
|
2111
2388
|
daemonEventLoopMonitor = void 0;
|
|
2112
|
-
daemonMetricsSampler
|
|
2389
|
+
const metricsSampler = daemonMetricsSampler;
|
|
2113
2390
|
daemonMetricsSampler = void 0;
|
|
2391
|
+
try {
|
|
2392
|
+
eventLoopMonitor?.dispose();
|
|
2393
|
+
} catch (err) {
|
|
2394
|
+
daemonLog.warn(
|
|
2395
|
+
`event loop monitor dispose error: ${err instanceof Error ? err.message : String(err)}`
|
|
2396
|
+
);
|
|
2397
|
+
}
|
|
2398
|
+
try {
|
|
2399
|
+
metricsSampler?.dispose();
|
|
2400
|
+
} catch (err) {
|
|
2401
|
+
daemonLog.warn(
|
|
2402
|
+
`metrics sampler dispose error: ${err instanceof Error ? err.message : String(err)}`
|
|
2403
|
+
);
|
|
2404
|
+
}
|
|
2114
2405
|
}, "disposeDaemonEventLoopMonitor");
|
|
2115
|
-
let
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2406
|
+
let channelWorkerManager;
|
|
2407
|
+
let channelWorkerManagerStarting;
|
|
2408
|
+
let channelControlDraining = false;
|
|
2409
|
+
let channelWorkspaceGroups;
|
|
2410
|
+
const channelWebhookEnvByWorkspace = /* @__PURE__ */ new Map();
|
|
2411
|
+
let channelWebhookConfigVersion = 0;
|
|
2412
|
+
let refreshChannelWebhookConfigs;
|
|
2413
|
+
let ensureChannelWorkerManager;
|
|
2414
|
+
const getChannelWebhookConfigSources = /* @__PURE__ */ __name(() => {
|
|
2415
|
+
const app2 = runtimeApp ?? runtimeAppForCleanup;
|
|
2416
|
+
const registry = app2?.locals?.["workspaceRegistry"];
|
|
2417
|
+
return (channelWorkspaceGroups ?? []).map((group) => {
|
|
2418
|
+
const env = registry?.getByWorkspaceCwd(group.workspaceCwd)?.env.effectiveEnv ?? channelWebhookEnvByWorkspace.get(group.workspaceCwd);
|
|
2419
|
+
return {
|
|
2420
|
+
workspaceCwd: group.workspaceCwd,
|
|
2421
|
+
...group.selection.mode === "names" ? { channelNames: group.selection.names } : {},
|
|
2422
|
+
...env ? { env } : {}
|
|
2423
|
+
};
|
|
2424
|
+
});
|
|
2425
|
+
}, "getChannelWebhookConfigSources");
|
|
2426
|
+
const resolveChannelWebhookConfigSource = /* @__PURE__ */ __name((channelName) => {
|
|
2427
|
+
const source = getChannelWebhookConfigSources().find(
|
|
2428
|
+
(source2) => !source2.channelNames || source2.channelNames.includes(channelName)
|
|
2429
|
+
);
|
|
2430
|
+
if (source) return source;
|
|
2431
|
+
const env = channelWebhookEnvByWorkspace.get(boundWorkspace);
|
|
2432
|
+
return {
|
|
2433
|
+
workspaceCwd: boundWorkspace,
|
|
2434
|
+
...env ? { env } : {}
|
|
2435
|
+
};
|
|
2436
|
+
}, "resolveChannelWebhookConfigSource");
|
|
2437
|
+
let closeServerAfterChannelWorkerStartupFailure = false;
|
|
2438
|
+
let runtimeFailureListenerClose;
|
|
2439
|
+
const getChannelWorkerSnapshot = /* @__PURE__ */ __name(() => channelWorkerManager?.primarySnapshot() ?? {
|
|
2440
|
+
enabled: false,
|
|
2441
|
+
state: "disabled",
|
|
2442
|
+
channels: []
|
|
2443
|
+
}, "getChannelWorkerSnapshot");
|
|
2444
|
+
const getChannelWorkerSnapshots = /* @__PURE__ */ __name(() => channelWorkerManager?.snapshots() ?? [], "getChannelWorkerSnapshots");
|
|
2445
|
+
const getChannelWorkerControl = /* @__PURE__ */ __name(() => channelWorkerManager?.state() ?? {
|
|
2446
|
+
enabled: false,
|
|
2447
|
+
selection: null,
|
|
2448
|
+
transition: "idle",
|
|
2449
|
+
workers: []
|
|
2450
|
+
}, "getChannelWorkerControl");
|
|
2451
|
+
const daemonDrainingError = /* @__PURE__ */ __name(() => Object.assign(new Error("Daemon is shutting down."), {
|
|
2452
|
+
code: "daemon_draining"
|
|
2453
|
+
}), "daemonDrainingError");
|
|
2454
|
+
const setChannelWorkerSelection = /* @__PURE__ */ __name(async (selection) => {
|
|
2455
|
+
if (channelControlDraining) throw daemonDrainingError();
|
|
2456
|
+
const manager = await ensureChannelWorkerManager?.();
|
|
2457
|
+
if (!manager) throw new Error("Channel worker manager is unavailable.");
|
|
2458
|
+
if (channelControlDraining) {
|
|
2459
|
+
await manager.shutdown().catch(() => void 0);
|
|
2460
|
+
throw daemonDrainingError();
|
|
2461
|
+
}
|
|
2462
|
+
return manager.setSelection(selection);
|
|
2463
|
+
}, "setChannelWorkerSelection");
|
|
2464
|
+
const stopChannelWorker = /* @__PURE__ */ __name(async () => {
|
|
2465
|
+
if (channelControlDraining) throw daemonDrainingError();
|
|
2466
|
+
const manager = channelWorkerManager ?? await channelWorkerManagerStarting;
|
|
2467
|
+
if (channelControlDraining) {
|
|
2468
|
+
await manager?.shutdown().catch(() => void 0);
|
|
2469
|
+
throw daemonDrainingError();
|
|
2470
|
+
}
|
|
2471
|
+
if (!manager) {
|
|
2472
|
+
return { changed: false, state: getChannelWorkerControl() };
|
|
2473
|
+
}
|
|
2474
|
+
return manager.stopSelection();
|
|
2475
|
+
}, "stopChannelWorker");
|
|
2476
|
+
const reloadChannelWorker = /* @__PURE__ */ __name(async () => {
|
|
2477
|
+
if (channelControlDraining) throw daemonDrainingError();
|
|
2478
|
+
const manager = channelWorkerManager ?? await channelWorkerManagerStarting;
|
|
2479
|
+
if (channelControlDraining) {
|
|
2480
|
+
await manager?.shutdown().catch(() => void 0);
|
|
2481
|
+
throw daemonDrainingError();
|
|
2482
|
+
}
|
|
2483
|
+
if (!manager) {
|
|
2484
|
+
return { enabled: false, state: "disabled", channels: [] };
|
|
2485
|
+
}
|
|
2486
|
+
try {
|
|
2487
|
+
return await manager.reload();
|
|
2488
|
+
} finally {
|
|
2489
|
+
writeChannelWorkerPidfile();
|
|
2490
|
+
}
|
|
2491
|
+
}, "reloadChannelWorker");
|
|
2492
|
+
const isLiveWorker = /* @__PURE__ */ __name((snapshot) => snapshot.state === "running" || snapshot.state === "starting", "isLiveWorker");
|
|
2493
|
+
let channelWorkerPidfileUsesWorkers = workspaceInputs.length > 1;
|
|
2494
|
+
const writeChannelWorkerPidfile = /* @__PURE__ */ __name(() => {
|
|
2495
|
+
if (runtimeStartupError !== void 0) return;
|
|
2496
|
+
if (!channelPidfileReserved || !channelServicePidfile) return;
|
|
2497
|
+
const snapshots = getChannelWorkerSnapshots();
|
|
2498
|
+
const workers = snapshots.map((snapshot) => ({
|
|
2499
|
+
workspaceId: snapshot.workspaceId,
|
|
2500
|
+
workspaceCwd: snapshot.workspaceCwd,
|
|
2501
|
+
channels: snapshot.channels,
|
|
2502
|
+
// Drop a stale pid (worker exited/failed/stopped) so readers never signal
|
|
2503
|
+
// a dead process — mirrors the pre-4b clear-on-exit behavior.
|
|
2504
|
+
...isLiveWorker(snapshot) && snapshot.pid !== void 0 ? { workerPid: snapshot.pid } : {}
|
|
2505
|
+
}));
|
|
2506
|
+
const channels = [
|
|
2507
|
+
...new Set(snapshots.flatMap((snapshot) => snapshot.channels))
|
|
2508
|
+
];
|
|
2509
|
+
const primary = snapshots.find((snapshot) => snapshot.primary);
|
|
2510
|
+
if (workers.length > 1 || snapshots.some((snapshot) => !snapshot.primary)) {
|
|
2511
|
+
channelWorkerPidfileUsesWorkers = true;
|
|
2512
|
+
}
|
|
2513
|
+
const includeWorkers = channelWorkerPidfileUsesWorkers && workers.length > 0;
|
|
2119
2514
|
try {
|
|
2120
2515
|
channelServicePidfile.writeServeServiceInfo({
|
|
2121
|
-
channels
|
|
2516
|
+
channels,
|
|
2122
2517
|
servePid: process.pid,
|
|
2123
|
-
|
|
2518
|
+
...primary && isLiveWorker(primary) && primary.pid !== void 0 ? { workerPid: primary.pid } : {},
|
|
2519
|
+
...includeWorkers ? { workers } : {}
|
|
2124
2520
|
});
|
|
2125
2521
|
} catch (err) {
|
|
2126
2522
|
daemonLog.warn(
|
|
@@ -2133,11 +2529,83 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
2133
2529
|
() => runtimeStartupError
|
|
2134
2530
|
);
|
|
2135
2531
|
const shutdownBridges = /* @__PURE__ */ new WeakSet();
|
|
2532
|
+
const disposedRuntimeApps = /* @__PURE__ */ new WeakSet();
|
|
2533
|
+
const stoppedRuntimeAppProducers = /* @__PURE__ */ new WeakSet();
|
|
2534
|
+
const stoppedExtensionReconcilers = /* @__PURE__ */ new WeakSet();
|
|
2535
|
+
const stopExtensionReconciler = /* @__PURE__ */ __name((app2) => {
|
|
2536
|
+
if (!app2 || stoppedExtensionReconcilers.has(app2)) return;
|
|
2537
|
+
stoppedExtensionReconcilers.add(app2);
|
|
2538
|
+
const stopExtensionGenerationReconciler = app2.locals?.["stopExtensionGenerationReconciler"];
|
|
2539
|
+
try {
|
|
2540
|
+
stopExtensionGenerationReconciler?.();
|
|
2541
|
+
} catch (err) {
|
|
2542
|
+
daemonLog.warn(
|
|
2543
|
+
`extension generation reconciler dispose error: ${err instanceof Error ? err.message : String(err)}`
|
|
2544
|
+
);
|
|
2545
|
+
}
|
|
2546
|
+
}, "stopExtensionReconciler");
|
|
2547
|
+
const stopRuntimeAppProducers = /* @__PURE__ */ __name((app2) => {
|
|
2548
|
+
if (!app2 || stoppedRuntimeAppProducers.has(app2)) return;
|
|
2549
|
+
stoppedRuntimeAppProducers.add(app2);
|
|
2550
|
+
const locals = app2.locals;
|
|
2551
|
+
const stopSafely = /* @__PURE__ */ __name((name, stop) => {
|
|
2552
|
+
try {
|
|
2553
|
+
stop?.();
|
|
2554
|
+
} catch (err) {
|
|
2555
|
+
daemonLog.warn(
|
|
2556
|
+
`${name} dispose error: ${err instanceof Error ? err.message : String(err)}`
|
|
2557
|
+
);
|
|
2558
|
+
}
|
|
2559
|
+
}, "stopSafely");
|
|
2560
|
+
stopSafely("scheduled-task keepalive", locals.stopScheduledTaskKeepalive);
|
|
2561
|
+
stopSafely("workspace git state", locals.stopWorkspaceGitState);
|
|
2562
|
+
for (const stop of locals.subSessionStoppers ?? []) {
|
|
2563
|
+
stopSafely("sub-session launcher", stop);
|
|
2564
|
+
}
|
|
2565
|
+
stopExtensionReconciler(app2);
|
|
2566
|
+
}, "stopRuntimeAppProducers");
|
|
2567
|
+
const disposeRuntimeAppResources = /* @__PURE__ */ __name((app2) => {
|
|
2568
|
+
if (!app2 || disposedRuntimeApps.has(app2)) return;
|
|
2569
|
+
disposedRuntimeApps.add(app2);
|
|
2570
|
+
stopRuntimeAppProducers(app2);
|
|
2571
|
+
const deviceFlowRegistry = getDeviceFlowRegistry(app2);
|
|
2572
|
+
if (deviceFlowRegistry) {
|
|
2573
|
+
try {
|
|
2574
|
+
deviceFlowRegistry.dispose();
|
|
2575
|
+
} catch (err) {
|
|
2576
|
+
daemonLog.warn(
|
|
2577
|
+
`device-flow registry dispose error: ${err instanceof Error ? err.message : String(err)}`
|
|
2578
|
+
);
|
|
2579
|
+
}
|
|
2580
|
+
}
|
|
2581
|
+
const acpHandle = app2.locals?.["acpHandle"];
|
|
2582
|
+
if (acpHandle?.dispose) {
|
|
2583
|
+
try {
|
|
2584
|
+
acpHandle.dispose();
|
|
2585
|
+
} catch (err) {
|
|
2586
|
+
daemonLog.warn(
|
|
2587
|
+
`ACP handle dispose error: ${err instanceof Error ? err.message : String(err)}`
|
|
2588
|
+
);
|
|
2589
|
+
}
|
|
2590
|
+
}
|
|
2591
|
+
const rateLimiter = getRateLimiter(app2);
|
|
2592
|
+
if (rateLimiter) {
|
|
2593
|
+
try {
|
|
2594
|
+
rateLimiter.setDraining(true);
|
|
2595
|
+
rateLimiter.dispose();
|
|
2596
|
+
} catch (err) {
|
|
2597
|
+
daemonLog.warn(
|
|
2598
|
+
`rate limiter dispose error: ${err instanceof Error ? err.message : String(err)}`
|
|
2599
|
+
);
|
|
2600
|
+
}
|
|
2601
|
+
}
|
|
2602
|
+
disposeDaemonEventLoopMonitor();
|
|
2603
|
+
}, "disposeRuntimeAppResources");
|
|
2136
2604
|
const getRuntimeBridgesForCleanup = /* @__PURE__ */ __name(() => {
|
|
2137
2605
|
const appForCleanup = runtimeApp ?? runtimeAppForCleanup;
|
|
2138
2606
|
const registry = appForCleanup?.locals?.["workspaceRegistry"];
|
|
2139
2607
|
const bridges = [
|
|
2140
|
-
...registry ? registry.
|
|
2608
|
+
...registry ? registry.listManaged().map((runtime) => runtime.bridge) : [],
|
|
2141
2609
|
...bridgeRef ? [bridgeRef] : [],
|
|
2142
2610
|
...internalRuntimeBridgesForCleanup
|
|
2143
2611
|
];
|
|
@@ -2319,12 +2787,15 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
2319
2787
|
// `agent_message_chunk._meta` (`usage` + `durationMs`) at the bridge's
|
|
2320
2788
|
// single session/update fan-in. Increments (not cumulative), so the ring
|
|
2321
2789
|
// sums tokens per window (token-burn chart) and pools the round-trip times
|
|
2322
|
-
// for the LLM-latency percentiles.
|
|
2323
|
-
|
|
2790
|
+
// for the LLM-latency percentiles. `apiErrors` / `apiRetries` ride the
|
|
2791
|
+
// same frame (per-round increments, 0 when none) and window into the
|
|
2792
|
+
// model-API-health chart.
|
|
2793
|
+
tokenUsage(inputTokens, outputTokens, durationMs, apiErrors, apiRetries) {
|
|
2324
2794
|
metricsRing.recordTokens(inputTokens, outputTokens);
|
|
2325
2795
|
if (typeof durationMs === "number") {
|
|
2326
2796
|
metricsRing.recordLlmDuration(durationMs);
|
|
2327
2797
|
}
|
|
2798
|
+
metricsRing.recordApiActivity(apiErrors ?? 0, apiRetries ?? 0);
|
|
2328
2799
|
}
|
|
2329
2800
|
};
|
|
2330
2801
|
return telemetry;
|
|
@@ -2414,6 +2885,7 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
2414
2885
|
getBridges: /* @__PURE__ */ __name(() => runtimeBridges.length > 0 ? runtimeBridges : bridgeRef ? [bridgeRef] : [], "getBridges")
|
|
2415
2886
|
}
|
|
2416
2887
|
);
|
|
2888
|
+
const sessionOwnerIndex = runtime.createWorkspaceSessionOwnerIndex();
|
|
2417
2889
|
const persistDisabledToolsFn = /* @__PURE__ */ __name((workspace, toolName, enabled) => withSettingsLock(workspace, async () => {
|
|
2418
2890
|
const fresh = settingsRuntime.settings.loadSettings(workspace);
|
|
2419
2891
|
const wsScope = fresh.forScope(WORKSPACE_SETTING_SCOPE).settings;
|
|
@@ -2428,6 +2900,63 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
2428
2900
|
[...next].sort()
|
|
2429
2901
|
);
|
|
2430
2902
|
}), "persistDisabledToolsFn");
|
|
2903
|
+
const persistDisabledSkillsFn = /* @__PURE__ */ __name((workspace, skillName, enabled) => withSettingsLock(workspace, async () => {
|
|
2904
|
+
const fresh = settingsRuntime.settings.loadSettings(workspace);
|
|
2905
|
+
const normalizedName = skillName.trim().toLowerCase();
|
|
2906
|
+
const disabledNames = /* @__PURE__ */ __name((value) => Array.isArray(value) ? value.filter(
|
|
2907
|
+
(entry) => typeof entry === "string"
|
|
2908
|
+
) : [], "disabledNames");
|
|
2909
|
+
const lockedScopes = [
|
|
2910
|
+
["system", fresh.system.settings.skills?.disabled],
|
|
2911
|
+
["user", fresh.user.settings.skills?.disabled],
|
|
2912
|
+
["systemDefaults", fresh.systemDefaults.settings.skills?.disabled]
|
|
2913
|
+
];
|
|
2914
|
+
for (const [scope, names] of lockedScopes) {
|
|
2915
|
+
if (disabledNames(names).some(
|
|
2916
|
+
(name) => name.trim().toLowerCase() === normalizedName
|
|
2917
|
+
)) {
|
|
2918
|
+
throw new runtime.WorkspaceSkillNotToggleableError(
|
|
2919
|
+
skillName,
|
|
2920
|
+
"locked",
|
|
2921
|
+
scope
|
|
2922
|
+
);
|
|
2923
|
+
}
|
|
2924
|
+
}
|
|
2925
|
+
const workspaceDisabled = disabledNames(
|
|
2926
|
+
fresh.workspace.settings.skills?.disabled
|
|
2927
|
+
);
|
|
2928
|
+
const next = [];
|
|
2929
|
+
let found = false;
|
|
2930
|
+
let changed = false;
|
|
2931
|
+
for (const name of workspaceDisabled) {
|
|
2932
|
+
if (name.trim().toLowerCase() !== normalizedName) {
|
|
2933
|
+
next.push(name);
|
|
2934
|
+
continue;
|
|
2935
|
+
}
|
|
2936
|
+
if (enabled) {
|
|
2937
|
+
changed = true;
|
|
2938
|
+
continue;
|
|
2939
|
+
}
|
|
2940
|
+
if (!found) {
|
|
2941
|
+
next.push(skillName);
|
|
2942
|
+
found = true;
|
|
2943
|
+
if (name !== skillName) changed = true;
|
|
2944
|
+
} else {
|
|
2945
|
+
changed = true;
|
|
2946
|
+
}
|
|
2947
|
+
}
|
|
2948
|
+
if (!enabled && !found) {
|
|
2949
|
+
next.push(skillName);
|
|
2950
|
+
changed = true;
|
|
2951
|
+
}
|
|
2952
|
+
if (!changed) return { changed: false, disabled: workspaceDisabled };
|
|
2953
|
+
fresh.setValue(
|
|
2954
|
+
WORKSPACE_SETTING_SCOPE,
|
|
2955
|
+
"skills.disabled",
|
|
2956
|
+
next.length > 0 ? next : void 0
|
|
2957
|
+
);
|
|
2958
|
+
return { changed: true, disabled: next };
|
|
2959
|
+
}), "persistDisabledSkillsFn");
|
|
2431
2960
|
const persistSettingFn = /* @__PURE__ */ __name((workspace, scope, key, value) => withSettingsLock(workspace, async () => {
|
|
2432
2961
|
const fresh = settingsRuntime.settings.loadSettings(workspace);
|
|
2433
2962
|
fresh.setValue(scope, key, value);
|
|
@@ -2460,12 +2989,19 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
2460
2989
|
);
|
|
2461
2990
|
}
|
|
2462
2991
|
}), "persistSettingsFn");
|
|
2992
|
+
const { createSubSessionLauncher } = await import("./create-sub-session-WJOWBFEP.js");
|
|
2993
|
+
const subSessionLauncher = createSubSessionLauncher({
|
|
2994
|
+
getBridge: /* @__PURE__ */ __name(() => bridgeRef, "getBridge"),
|
|
2995
|
+
boundWorkspace
|
|
2996
|
+
});
|
|
2463
2997
|
const bridge = deps.bridge ?? runtime.createAcpSessionBridge({
|
|
2464
2998
|
// Reverse tool channel: let `BridgeClient.extMethod` reach the WS
|
|
2465
2999
|
// connection that hosts a named client MCP server (#5626).
|
|
2466
3000
|
clientMcpSender: clientMcpSenderRegistry.lookup,
|
|
3001
|
+
onCreateSubSession: subSessionLauncher.launch,
|
|
2467
3002
|
maxSessions: opts.maxSessions,
|
|
2468
3003
|
freshSessionAdmission: totalSessionAdmission.admit,
|
|
3004
|
+
sessionLifecycle: sessionOwnerIndex.handleBridgeSessionLifecycle,
|
|
2469
3005
|
...opts.maxPendingPromptsPerSession !== void 0 ? { maxPendingPromptsPerSession: opts.maxPendingPromptsPerSession } : {},
|
|
2470
3006
|
...opts.eventRingSize !== void 0 ? { eventRingSize: opts.eventRingSize } : {},
|
|
2471
3007
|
...opts.compactedReplayMaxBytes !== void 0 ? { compactedReplayMaxBytes: opts.compactedReplayMaxBytes } : {},
|
|
@@ -2494,16 +3030,21 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
2494
3030
|
internalRuntimeBridgesForCleanup.push(bridge);
|
|
2495
3031
|
}
|
|
2496
3032
|
runtimeBridges.push(bridge);
|
|
3033
|
+
let invalidatePrimaryServeFeaturesCache = /* @__PURE__ */ __name(() => {
|
|
3034
|
+
}, "invalidatePrimaryServeFeaturesCache");
|
|
2497
3035
|
const workspaceService = runtime.createDaemonWorkspaceService({
|
|
2498
3036
|
boundWorkspace,
|
|
2499
3037
|
contextFilename: contextFilenameForInit ?? "QWEN.md",
|
|
2500
3038
|
statusProvider,
|
|
2501
3039
|
workspaceProvidersStatusProvider,
|
|
2502
3040
|
workspaceSkillsStatusProvider,
|
|
3041
|
+
voiceEnv: runtimeEffectiveEnv,
|
|
2503
3042
|
isChannelLive: /* @__PURE__ */ __name(() => bridge.isChannelLive(), "isChannelLive"),
|
|
2504
3043
|
persistDisabledTools: persistDisabledToolsFn,
|
|
3044
|
+
persistDisabledSkills: persistDisabledSkillsFn,
|
|
2505
3045
|
persistSetting: persistSettingFn,
|
|
2506
3046
|
persistSettings: persistSettingsFn,
|
|
3047
|
+
preheatAcpChild: /* @__PURE__ */ __name(() => bridge.preheat(), "preheatAcpChild"),
|
|
2507
3048
|
reloadDaemonEnv: /* @__PURE__ */ __name((workspace) => withSettingsLock(workspace, async () => {
|
|
2508
3049
|
const fresh = settingsRuntime.settings.loadSettings(workspace, {
|
|
2509
3050
|
skipLoadEnvironment: true
|
|
@@ -2566,7 +3107,12 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
2566
3107
|
queryWorkspaceStatus: /* @__PURE__ */ __name((method, idle) => bridge.queryWorkspaceStatus(method, idle), "queryWorkspaceStatus"),
|
|
2567
3108
|
invokeWorkspaceCommand: /* @__PURE__ */ __name((method, params, invokeOpts) => bridge.invokeWorkspaceCommand(method, params, invokeOpts), "invokeWorkspaceCommand"),
|
|
2568
3109
|
refreshExtensionsForAllSessions: /* @__PURE__ */ __name(() => bridge.refreshExtensionsForAllSessions(), "refreshExtensionsForAllSessions"),
|
|
2569
|
-
publishWorkspaceEvent: /* @__PURE__ */ __name((event) =>
|
|
3110
|
+
publishWorkspaceEvent: /* @__PURE__ */ __name((event) => {
|
|
3111
|
+
if (event.type === "settings_changed" || event.type === "settings_reloaded") {
|
|
3112
|
+
invalidatePrimaryServeFeaturesCache();
|
|
3113
|
+
}
|
|
3114
|
+
bridge.publishWorkspaceEvent(event);
|
|
3115
|
+
}, "publishWorkspaceEvent")
|
|
2570
3116
|
});
|
|
2571
3117
|
const workspaceRuntimes = [
|
|
2572
3118
|
{
|
|
@@ -2574,6 +3120,8 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
2574
3120
|
workspaceCwd: boundWorkspace,
|
|
2575
3121
|
primary: true,
|
|
2576
3122
|
trusted: trustedWorkspace,
|
|
3123
|
+
removable: false,
|
|
3124
|
+
registrationIds: workspaceInputs[0]?.registrationIds ?? [],
|
|
2577
3125
|
env: primaryRuntimeEnv,
|
|
2578
3126
|
bridge,
|
|
2579
3127
|
workspaceService,
|
|
@@ -2614,6 +3162,13 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
2614
3162
|
}
|
|
2615
3163
|
};
|
|
2616
3164
|
}, "createRuntimeEnvMetadata");
|
|
3165
|
+
const subSessionStoppers = [];
|
|
3166
|
+
const subSessionStoppersByWorkspace = /* @__PURE__ */ new Map();
|
|
3167
|
+
const runtimeCleanupPromises = /* @__PURE__ */ new WeakMap();
|
|
3168
|
+
const removeArrayValue = /* @__PURE__ */ __name((values, value) => {
|
|
3169
|
+
const index = values.indexOf(value);
|
|
3170
|
+
if (index >= 0) values.splice(index, 1);
|
|
3171
|
+
}, "removeArrayValue");
|
|
2617
3172
|
for (const workspaceInput of workspaceInputs.slice(1)) {
|
|
2618
3173
|
let secondarySettings;
|
|
2619
3174
|
try {
|
|
@@ -2667,10 +3222,17 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
2667
3222
|
...opts.experimentalLsp === true ? { extraArgs: ["--experimental-lsp"] } : {}
|
|
2668
3223
|
});
|
|
2669
3224
|
const secondaryClientMcpSenderRegistry = new ClientMcpSenderRegistry();
|
|
3225
|
+
let secondaryBridgeRef;
|
|
3226
|
+
const secondarySubSessionLauncher = createSubSessionLauncher({
|
|
3227
|
+
getBridge: /* @__PURE__ */ __name(() => secondaryBridgeRef, "getBridge"),
|
|
3228
|
+
boundWorkspace: workspaceInput.cwd
|
|
3229
|
+
});
|
|
2670
3230
|
const secondaryBridge = runtime.createAcpSessionBridge({
|
|
2671
3231
|
clientMcpSender: secondaryClientMcpSenderRegistry.lookup,
|
|
3232
|
+
onCreateSubSession: secondarySubSessionLauncher.launch,
|
|
2672
3233
|
maxSessions: opts.maxSessions,
|
|
2673
3234
|
freshSessionAdmission: totalSessionAdmission.admit,
|
|
3235
|
+
sessionLifecycle: sessionOwnerIndex.handleBridgeSessionLifecycle,
|
|
2674
3236
|
...opts.maxPendingPromptsPerSession !== void 0 ? { maxPendingPromptsPerSession: opts.maxPendingPromptsPerSession } : {},
|
|
2675
3237
|
...opts.eventRingSize !== void 0 ? { eventRingSize: opts.eventRingSize } : {},
|
|
2676
3238
|
...opts.compactedReplayMaxBytes !== void 0 ? { compactedReplayMaxBytes: opts.compactedReplayMaxBytes } : {},
|
|
@@ -2696,8 +3258,14 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
2696
3258
|
fresh.setValue(WORKSPACE_SETTING_SCOPE, "tools.approvalMode", mode);
|
|
2697
3259
|
}), "persistApprovalMode")
|
|
2698
3260
|
});
|
|
3261
|
+
secondaryBridgeRef = secondaryBridge;
|
|
2699
3262
|
runtimeBridges.push(secondaryBridge);
|
|
2700
3263
|
internalRuntimeBridgesForCleanup.push(secondaryBridge);
|
|
3264
|
+
subSessionStoppers.push(secondarySubSessionLauncher.stop);
|
|
3265
|
+
subSessionStoppersByWorkspace.set(
|
|
3266
|
+
workspaceInput.cwd,
|
|
3267
|
+
secondarySubSessionLauncher.stop
|
|
3268
|
+
);
|
|
2701
3269
|
const secondaryWorkspaceService = runtime.createDaemonWorkspaceService({
|
|
2702
3270
|
boundWorkspace: workspaceInput.cwd,
|
|
2703
3271
|
contextFilename: contextFilenameForInit ?? "QWEN.md",
|
|
@@ -2706,8 +3274,12 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
2706
3274
|
env: secondaryEnv.effectiveEnv
|
|
2707
3275
|
}),
|
|
2708
3276
|
workspaceSkillsStatusProvider: runtime.createWorkspaceSkillsStatusProvider(),
|
|
3277
|
+
voiceEnv: secondaryEnv.effectiveEnv,
|
|
3278
|
+
voiceSettingsScope: WORKSPACE_SETTING_SCOPE,
|
|
2709
3279
|
isChannelLive: /* @__PURE__ */ __name(() => secondaryBridge.isChannelLive(), "isChannelLive"),
|
|
3280
|
+
preheatAcpChild: /* @__PURE__ */ __name(() => secondaryBridge.preheat(), "preheatAcpChild"),
|
|
2710
3281
|
persistDisabledTools: persistDisabledToolsFn,
|
|
3282
|
+
persistDisabledSkills: persistDisabledSkillsFn,
|
|
2711
3283
|
persistSetting: persistSettingFn,
|
|
2712
3284
|
persistSettings: persistSettingsFn,
|
|
2713
3285
|
reloadDaemonEnv: /* @__PURE__ */ __name((workspace) => withSettingsLock(workspace, async () => {
|
|
@@ -2765,6 +3337,8 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
2765
3337
|
workspaceCwd: workspaceInput.cwd,
|
|
2766
3338
|
primary: false,
|
|
2767
3339
|
trusted: secondaryTrusted,
|
|
3340
|
+
removable: workspaceInput.removable,
|
|
3341
|
+
registrationIds: workspaceInput.registrationIds,
|
|
2768
3342
|
env: secondaryEnv.metadata,
|
|
2769
3343
|
bridge: secondaryBridge,
|
|
2770
3344
|
workspaceService: secondaryWorkspaceService,
|
|
@@ -2772,7 +3346,10 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
2772
3346
|
clientMcpSenderRegistry: secondaryClientMcpSenderRegistry
|
|
2773
3347
|
});
|
|
2774
3348
|
}
|
|
2775
|
-
const workspaceRegistry = runtime.createWorkspaceRegistry(workspaceRuntimes
|
|
3349
|
+
const workspaceRegistry = runtime.createWorkspaceRegistry(workspaceRuntimes, {
|
|
3350
|
+
sessionOwnerIndex
|
|
3351
|
+
});
|
|
3352
|
+
const workspaceVoiceCoordinator = new WorkspaceVoiceCoordinator();
|
|
2776
3353
|
core.registerDaemonGaugeCallbacks({
|
|
2777
3354
|
sessionCount: /* @__PURE__ */ __name(() => workspaceRegistry.list().reduce((sum, item) => sum + item.bridge.sessionCount, 0), "sessionCount"),
|
|
2778
3355
|
sseCount: /* @__PURE__ */ __name(() => runtime.getActiveSseCount(), "sseCount"),
|
|
@@ -2801,7 +3378,7 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
2801
3378
|
prevCpu = cpu;
|
|
2802
3379
|
prevCpuAt = nowMs;
|
|
2803
3380
|
}
|
|
2804
|
-
const acp = app2.locals?.["acpHandle"]?.
|
|
3381
|
+
const acp = app2.locals?.["acpHandle"]?.getSnapshot();
|
|
2805
3382
|
const hits = getRateLimiter(app2)?.getHitCounts();
|
|
2806
3383
|
const rejectedTotal = hits ? hits.prompt + hits.mutation + hits.read : 0;
|
|
2807
3384
|
const rateLimitRejected = prevRateRejected === void 0 ? 0 : Math.max(0, rejectedTotal - prevRateRejected);
|
|
@@ -2864,8 +3441,317 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
2864
3441
|
metricsLoopDelay.disable();
|
|
2865
3442
|
}
|
|
2866
3443
|
};
|
|
3444
|
+
const createDynamicWorkspaceRuntime = /* @__PURE__ */ __name(async (cwd) => {
|
|
3445
|
+
let wsSettings;
|
|
3446
|
+
try {
|
|
3447
|
+
wsSettings = settingsRuntime.settings.loadSettings(cwd);
|
|
3448
|
+
} catch (err) {
|
|
3449
|
+
writeStderrLine(
|
|
3450
|
+
`qwen serve: could not read full settings for dynamic workspace ${cwd} (${err instanceof Error ? err.message : String(err)}); falling back to defaults.`
|
|
3451
|
+
);
|
|
3452
|
+
}
|
|
3453
|
+
const trusted = wsSettings ? settingsRuntime.trustedFolders.getWorkspaceTrustStatus(
|
|
3454
|
+
wsSettings.merged,
|
|
3455
|
+
cwd
|
|
3456
|
+
).effective.state === "trusted" : false;
|
|
3457
|
+
const wsEnv = createRuntimeEnvMetadata(cwd, wsSettings);
|
|
3458
|
+
const wsHash = core.hashDaemonWorkspace(cwd);
|
|
3459
|
+
const wsFsFactory = runtime.resolveBridgeFsFactory({
|
|
3460
|
+
boundWorkspaces: [cwd],
|
|
3461
|
+
trusted,
|
|
3462
|
+
emit: deps.fsAuditEmit,
|
|
3463
|
+
pathLocks: sharedPathLocks,
|
|
3464
|
+
...customIgnoreFiles !== void 0 ? { customIgnoreFiles } : {}
|
|
3465
|
+
});
|
|
3466
|
+
const wsChannelFactory = runtime.createSpawnChannelFactory({
|
|
3467
|
+
sourceEnv: wsEnv.effectiveEnv,
|
|
3468
|
+
onDiagnosticLine: diagnosticSink,
|
|
3469
|
+
pipeHooks: {
|
|
3470
|
+
onMessageSent: /* @__PURE__ */ __name((bytes) => recordPipeMessage("outbound", bytes), "onMessageSent"),
|
|
3471
|
+
onMessageReceived: /* @__PURE__ */ __name((bytes) => recordPipeMessage("inbound", bytes), "onMessageReceived"),
|
|
3472
|
+
onMessageObserved: /* @__PURE__ */ __name(({ direction, bytes, message }) => observeLargePipeFrame({
|
|
3473
|
+
direction: daemonPipeDirection(direction),
|
|
3474
|
+
bytes,
|
|
3475
|
+
message
|
|
3476
|
+
}), "onMessageObserved")
|
|
3477
|
+
},
|
|
3478
|
+
...opts.experimentalLsp === true ? { extraArgs: ["--experimental-lsp"] } : {}
|
|
3479
|
+
});
|
|
3480
|
+
const wsClientMcpRegistry = new ClientMcpSenderRegistry();
|
|
3481
|
+
let wsBridgeRef;
|
|
3482
|
+
const wsSubSessionLauncher = createSubSessionLauncher({
|
|
3483
|
+
getBridge: /* @__PURE__ */ __name(() => wsBridgeRef, "getBridge"),
|
|
3484
|
+
boundWorkspace: cwd
|
|
3485
|
+
});
|
|
3486
|
+
let wsBridge;
|
|
3487
|
+
try {
|
|
3488
|
+
wsBridge = runtime.createAcpSessionBridge({
|
|
3489
|
+
clientMcpSender: wsClientMcpRegistry.lookup,
|
|
3490
|
+
onCreateSubSession: wsSubSessionLauncher.launch,
|
|
3491
|
+
maxSessions: opts.maxSessions,
|
|
3492
|
+
freshSessionAdmission: totalSessionAdmission.admit,
|
|
3493
|
+
sessionLifecycle: sessionOwnerIndex.handleBridgeSessionLifecycle,
|
|
3494
|
+
...opts.maxPendingPromptsPerSession !== void 0 ? { maxPendingPromptsPerSession: opts.maxPendingPromptsPerSession } : {},
|
|
3495
|
+
...opts.eventRingSize !== void 0 ? { eventRingSize: opts.eventRingSize } : {},
|
|
3496
|
+
...opts.compactedReplayMaxBytes !== void 0 ? { compactedReplayMaxBytes: opts.compactedReplayMaxBytes } : {},
|
|
3497
|
+
...opts.channelIdleTimeoutMs !== void 0 ? { channelIdleTimeoutMs: opts.channelIdleTimeoutMs } : {},
|
|
3498
|
+
...opts.sessionReapIntervalMs !== void 0 ? { sessionReapIntervalMs: opts.sessionReapIntervalMs } : {},
|
|
3499
|
+
...opts.sessionIdleTimeoutMs !== void 0 ? { sessionIdleTimeoutMs: opts.sessionIdleTimeoutMs } : {},
|
|
3500
|
+
...opts.permissionResponseTimeoutMs !== void 0 ? { permissionResponseTimeoutMs: opts.permissionResponseTimeoutMs } : {},
|
|
3501
|
+
boundWorkspace: cwd,
|
|
3502
|
+
sessionShellCommandEnabled,
|
|
3503
|
+
childEnvOverrides,
|
|
3504
|
+
channelFactory: wsChannelFactory,
|
|
3505
|
+
onDiagnosticLine: diagnosticSink,
|
|
3506
|
+
telemetry: createRuntimeBridgeTelemetry(wsHash),
|
|
3507
|
+
...permissionPolicy !== void 0 ? { permissionPolicy } : {},
|
|
3508
|
+
...permissionConsensusQuorum !== void 0 ? { permissionConsensusQuorum } : {},
|
|
3509
|
+
permissionAudit: permissionAuditPublisher,
|
|
3510
|
+
statusProvider: runtime.createDaemonStatusProvider({
|
|
3511
|
+
env: wsEnv.effectiveEnv
|
|
3512
|
+
}),
|
|
3513
|
+
fileSystem: createBridgeFileSystemAdapter(wsFsFactory),
|
|
3514
|
+
persistApprovalMode: /* @__PURE__ */ __name((workspace, mode) => withSettingsLock(workspace, async () => {
|
|
3515
|
+
const fresh = settingsRuntime.settings.loadSettings(workspace);
|
|
3516
|
+
fresh.setValue(
|
|
3517
|
+
WORKSPACE_SETTING_SCOPE,
|
|
3518
|
+
"tools.approvalMode",
|
|
3519
|
+
mode
|
|
3520
|
+
);
|
|
3521
|
+
}), "persistApprovalMode")
|
|
3522
|
+
});
|
|
3523
|
+
} catch (err) {
|
|
3524
|
+
wsSubSessionLauncher.stop();
|
|
3525
|
+
throw err;
|
|
3526
|
+
}
|
|
3527
|
+
wsBridgeRef = wsBridge;
|
|
3528
|
+
let wsService;
|
|
3529
|
+
try {
|
|
3530
|
+
wsService = runtime.createDaemonWorkspaceService({
|
|
3531
|
+
boundWorkspace: cwd,
|
|
3532
|
+
contextFilename: contextFilenameForInit ?? "QWEN.md",
|
|
3533
|
+
statusProvider: runtime.createDaemonStatusProvider({
|
|
3534
|
+
env: wsEnv.effectiveEnv
|
|
3535
|
+
}),
|
|
3536
|
+
workspaceProvidersStatusProvider: runtime.createWorkspaceProvidersStatusProvider({
|
|
3537
|
+
env: wsEnv.effectiveEnv
|
|
3538
|
+
}),
|
|
3539
|
+
workspaceSkillsStatusProvider: runtime.createWorkspaceSkillsStatusProvider(),
|
|
3540
|
+
voiceEnv: wsEnv.effectiveEnv,
|
|
3541
|
+
voiceSettingsScope: WORKSPACE_SETTING_SCOPE,
|
|
3542
|
+
isChannelLive: /* @__PURE__ */ __name(() => wsBridge.isChannelLive(), "isChannelLive"),
|
|
3543
|
+
preheatAcpChild: /* @__PURE__ */ __name(() => wsBridge.preheat(), "preheatAcpChild"),
|
|
3544
|
+
persistDisabledTools: persistDisabledToolsFn,
|
|
3545
|
+
persistDisabledSkills: persistDisabledSkillsFn,
|
|
3546
|
+
persistSetting: persistSettingFn,
|
|
3547
|
+
persistSettings: persistSettingsFn,
|
|
3548
|
+
reloadDaemonEnv: /* @__PURE__ */ __name((workspace) => withSettingsLock(workspace, async () => {
|
|
3549
|
+
const fresh = settingsRuntime.settings.loadSettings(workspace, {
|
|
3550
|
+
skipLoadEnvironment: true
|
|
3551
|
+
});
|
|
3552
|
+
const result = settingsRuntime.settings.reloadEnvironment(
|
|
3553
|
+
fresh.merged,
|
|
3554
|
+
workspace
|
|
3555
|
+
);
|
|
3556
|
+
try {
|
|
3557
|
+
const refreshedRuntimeEnv = settingsRuntime.environment.buildRuntimeEnvironment(
|
|
3558
|
+
fresh.merged,
|
|
3559
|
+
workspace,
|
|
3560
|
+
daemonRuntimeBaseEnv
|
|
3561
|
+
);
|
|
3562
|
+
logRuntimeEnvFileReadFailures(workspace, refreshedRuntimeEnv);
|
|
3563
|
+
wsEnv.replace(refreshedRuntimeEnv.effectiveEnv);
|
|
3564
|
+
wsEnv.metadata.envFileReadFailed = refreshedRuntimeEnv.envFileReadFailed;
|
|
3565
|
+
wsEnv.metadata.envFileReadFailures.splice(
|
|
3566
|
+
0,
|
|
3567
|
+
wsEnv.metadata.envFileReadFailures.length,
|
|
3568
|
+
...refreshedRuntimeEnv.envFileReadFailures
|
|
3569
|
+
);
|
|
3570
|
+
wsEnv.metadata.overlayKeys.splice(
|
|
3571
|
+
0,
|
|
3572
|
+
wsEnv.metadata.overlayKeys.length,
|
|
3573
|
+
...refreshedRuntimeEnv.overlayKeys
|
|
3574
|
+
);
|
|
3575
|
+
wsEnv.metadata.envFilePaths.splice(
|
|
3576
|
+
0,
|
|
3577
|
+
wsEnv.metadata.envFilePaths.length,
|
|
3578
|
+
...refreshedRuntimeEnv.envFilePaths
|
|
3579
|
+
);
|
|
3580
|
+
delete wsEnv.metadata.fallbackReason;
|
|
3581
|
+
} catch (err) {
|
|
3582
|
+
wsEnv.metadata.fallbackReason = err instanceof Error ? err.message : String(err);
|
|
3583
|
+
daemonLog.warn(
|
|
3584
|
+
"failed to rebuild dynamic runtime env snapshot after daemon env reload; preserving previous runtime env",
|
|
3585
|
+
{
|
|
3586
|
+
workspace,
|
|
3587
|
+
error: wsEnv.metadata.fallbackReason
|
|
3588
|
+
}
|
|
3589
|
+
);
|
|
3590
|
+
}
|
|
3591
|
+
return result;
|
|
3592
|
+
}), "reloadDaemonEnv"),
|
|
3593
|
+
queryWorkspaceStatus: /* @__PURE__ */ __name((method, idle) => wsBridge.queryWorkspaceStatus(method, idle), "queryWorkspaceStatus"),
|
|
3594
|
+
invokeWorkspaceCommand: /* @__PURE__ */ __name((method, params, invokeOpts) => wsBridge.invokeWorkspaceCommand(method, params, invokeOpts), "invokeWorkspaceCommand"),
|
|
3595
|
+
refreshExtensionsForAllSessions: /* @__PURE__ */ __name(() => wsBridge.refreshExtensionsForAllSessions(), "refreshExtensionsForAllSessions"),
|
|
3596
|
+
publishWorkspaceEvent: /* @__PURE__ */ __name((event) => wsBridge.publishWorkspaceEvent(event), "publishWorkspaceEvent")
|
|
3597
|
+
});
|
|
3598
|
+
} catch (err) {
|
|
3599
|
+
wsSubSessionLauncher.stop();
|
|
3600
|
+
await wsBridge.shutdown().catch(() => {
|
|
3601
|
+
try {
|
|
3602
|
+
wsBridge.killAllSync();
|
|
3603
|
+
} catch {
|
|
3604
|
+
}
|
|
3605
|
+
});
|
|
3606
|
+
throw err;
|
|
3607
|
+
}
|
|
3608
|
+
runtimeBridges.push(wsBridge);
|
|
3609
|
+
internalRuntimeBridgesForCleanup.push(wsBridge);
|
|
3610
|
+
subSessionStoppers.push(wsSubSessionLauncher.stop);
|
|
3611
|
+
subSessionStoppersByWorkspace.set(cwd, wsSubSessionLauncher.stop);
|
|
3612
|
+
return {
|
|
3613
|
+
workspaceId: wsHash,
|
|
3614
|
+
workspaceCwd: cwd,
|
|
3615
|
+
primary: false,
|
|
3616
|
+
trusted,
|
|
3617
|
+
removable: true,
|
|
3618
|
+
registrationIds: [],
|
|
3619
|
+
env: wsEnv.metadata,
|
|
3620
|
+
bridge: wsBridge,
|
|
3621
|
+
workspaceService: wsService,
|
|
3622
|
+
routeFileSystemFactory: wsFsFactory,
|
|
3623
|
+
clientMcpSenderRegistry: wsClientMcpRegistry
|
|
3624
|
+
};
|
|
3625
|
+
}, "createDynamicWorkspaceRuntime");
|
|
3626
|
+
const workspaceRuntimeRemoval = {
|
|
3627
|
+
async runtimeAdded(runtimeAdded) {
|
|
3628
|
+
const app3 = runtimeApp ?? runtimeAppForCleanup;
|
|
3629
|
+
const startScheduledTaskKeepaliveForWorkspace = app3?.locals?.["startScheduledTaskKeepaliveForWorkspace"];
|
|
3630
|
+
startScheduledTaskKeepaliveForWorkspace?.(runtimeAdded);
|
|
3631
|
+
if (!channelWorkerManager) return;
|
|
3632
|
+
try {
|
|
3633
|
+
await channelWorkerManager.restoreWorkspace(
|
|
3634
|
+
runtimeAdded.workspaceCwd
|
|
3635
|
+
);
|
|
3636
|
+
await channelWorkerManager.refreshWorkspaces();
|
|
3637
|
+
} catch (err) {
|
|
3638
|
+
daemonLog.error(
|
|
3639
|
+
"workspace channel worker startup error",
|
|
3640
|
+
err instanceof Error ? err : null
|
|
3641
|
+
);
|
|
3642
|
+
} finally {
|
|
3643
|
+
writeChannelWorkerPidfile();
|
|
3644
|
+
}
|
|
3645
|
+
},
|
|
3646
|
+
beginDrain(runtimeToDrain) {
|
|
3647
|
+
totalSessionAdmission.beginWorkspaceDrain(runtimeToDrain.workspaceCwd);
|
|
3648
|
+
channelWorkerManager?.beginWorkspaceDrain(runtimeToDrain.workspaceCwd);
|
|
3649
|
+
workspaceVoiceCoordinator.beginWorkspaceDrain(runtimeToDrain);
|
|
3650
|
+
},
|
|
3651
|
+
cancelDrain(runtimeToDrain) {
|
|
3652
|
+
channelWorkerManager?.cancelWorkspaceDrain(runtimeToDrain.workspaceCwd);
|
|
3653
|
+
totalSessionAdmission.cancelWorkspaceDrain(runtimeToDrain.workspaceCwd);
|
|
3654
|
+
workspaceVoiceCoordinator.cancelWorkspaceDrain(runtimeToDrain);
|
|
3655
|
+
},
|
|
3656
|
+
completeDrain(runtimeToDrain) {
|
|
3657
|
+
totalSessionAdmission.completeWorkspaceDrain(
|
|
3658
|
+
runtimeToDrain.workspaceCwd
|
|
3659
|
+
);
|
|
3660
|
+
workspaceVoiceCoordinator.completeWorkspaceDrain(runtimeToDrain);
|
|
3661
|
+
},
|
|
3662
|
+
getActivity(runtimeToDrain) {
|
|
3663
|
+
return {
|
|
3664
|
+
pendingSessionStarts: totalSessionAdmission.snapshotForWorkspace(
|
|
3665
|
+
runtimeToDrain.workspaceCwd
|
|
3666
|
+
).inFlight,
|
|
3667
|
+
channelWorkers: channelWorkerManager?.workspaceActivity(
|
|
3668
|
+
runtimeToDrain.workspaceCwd
|
|
3669
|
+
) ?? 0,
|
|
3670
|
+
voiceSessions: workspaceVoiceCoordinator.getWorkspaceActivity(runtimeToDrain)
|
|
3671
|
+
};
|
|
3672
|
+
},
|
|
3673
|
+
disposeRuntime(runtimeToDrain, reason = "workspace_removed") {
|
|
3674
|
+
const existing = runtimeCleanupPromises.get(runtimeToDrain);
|
|
3675
|
+
if (existing) return existing;
|
|
3676
|
+
const cleanup = (async () => {
|
|
3677
|
+
await workspaceVoiceCoordinator.disposeRuntime(
|
|
3678
|
+
runtimeToDrain,
|
|
3679
|
+
reason
|
|
3680
|
+
);
|
|
3681
|
+
const stopSubSessions = subSessionStoppersByWorkspace.get(
|
|
3682
|
+
runtimeToDrain.workspaceCwd
|
|
3683
|
+
);
|
|
3684
|
+
try {
|
|
3685
|
+
stopSubSessions?.();
|
|
3686
|
+
} catch {
|
|
3687
|
+
}
|
|
3688
|
+
if (reason === "workspace_removed" && channelWorkerManager) {
|
|
3689
|
+
await channelWorkerManager.removeWorkspace(runtimeToDrain.workspaceCwd).catch((err) => {
|
|
3690
|
+
daemonLog.error(
|
|
3691
|
+
"workspace channel worker cleanup error",
|
|
3692
|
+
err instanceof Error ? err : null
|
|
3693
|
+
);
|
|
3694
|
+
});
|
|
3695
|
+
try {
|
|
3696
|
+
await channelWorkerManager.refreshWorkspaces();
|
|
3697
|
+
} catch (err) {
|
|
3698
|
+
channelWorkspaceGroups = (channelWorkspaceGroups ?? []).filter(
|
|
3699
|
+
(group) => group.workspaceCwd !== runtimeToDrain.workspaceCwd
|
|
3700
|
+
);
|
|
3701
|
+
channelWebhookConfigVersion += 1;
|
|
3702
|
+
refreshChannelWebhookConfigs?.();
|
|
3703
|
+
daemonLog.error(
|
|
3704
|
+
"workspace channel worker topology refresh error",
|
|
3705
|
+
err instanceof Error ? err : null
|
|
3706
|
+
);
|
|
3707
|
+
}
|
|
3708
|
+
writeChannelWorkerPidfile();
|
|
3709
|
+
}
|
|
3710
|
+
if (reason === "workspace_removed") {
|
|
3711
|
+
const app3 = runtimeApp ?? runtimeAppForCleanup;
|
|
3712
|
+
const stopWorkspaceGitStateForWorkspace = app3?.locals?.["stopWorkspaceGitStateForWorkspace"];
|
|
3713
|
+
const stopScheduledTaskKeepaliveForWorkspace = app3?.locals?.["stopScheduledTaskKeepaliveForWorkspace"];
|
|
3714
|
+
stopWorkspaceGitStateForWorkspace?.(runtimeToDrain.workspaceCwd);
|
|
3715
|
+
stopScheduledTaskKeepaliveForWorkspace?.(
|
|
3716
|
+
runtimeToDrain.workspaceCwd
|
|
3717
|
+
);
|
|
3718
|
+
}
|
|
3719
|
+
let bridgeStopped = false;
|
|
3720
|
+
try {
|
|
3721
|
+
if (!shutdownBridges.has(runtimeToDrain.bridge)) {
|
|
3722
|
+
await runtimeToDrain.bridge.shutdown({ reason });
|
|
3723
|
+
}
|
|
3724
|
+
bridgeStopped = true;
|
|
3725
|
+
} finally {
|
|
3726
|
+
if (bridgeStopped || reason === "workspace_removed") {
|
|
3727
|
+
subSessionStoppersByWorkspace.delete(runtimeToDrain.workspaceCwd);
|
|
3728
|
+
if (stopSubSessions) {
|
|
3729
|
+
removeArrayValue(subSessionStoppers, stopSubSessions);
|
|
3730
|
+
}
|
|
3731
|
+
removeArrayValue(runtimeBridges, runtimeToDrain.bridge);
|
|
3732
|
+
removeArrayValue(
|
|
3733
|
+
internalRuntimeBridgesForCleanup,
|
|
3734
|
+
runtimeToDrain.bridge
|
|
3735
|
+
);
|
|
3736
|
+
shutdownBridges.add(runtimeToDrain.bridge);
|
|
3737
|
+
}
|
|
3738
|
+
}
|
|
3739
|
+
})();
|
|
3740
|
+
runtimeCleanupPromises.set(runtimeToDrain, cleanup);
|
|
3741
|
+
void cleanup.catch(() => {
|
|
3742
|
+
if (reason === "daemon_shutdown" && runtimeCleanupPromises.get(runtimeToDrain) === cleanup) {
|
|
3743
|
+
runtimeCleanupPromises.delete(runtimeToDrain);
|
|
3744
|
+
}
|
|
3745
|
+
});
|
|
3746
|
+
return cleanup;
|
|
3747
|
+
}
|
|
3748
|
+
};
|
|
2867
3749
|
const app2 = runtime.createServeApp(opts, () => actualPort, {
|
|
2868
3750
|
workspaceRegistry,
|
|
3751
|
+
createWorkspaceRuntime: createDynamicWorkspaceRuntime,
|
|
3752
|
+
workspaceRegistrationStore,
|
|
3753
|
+
workspaceRuntimeRemoval,
|
|
3754
|
+
voiceCoordinator: workspaceVoiceCoordinator,
|
|
2869
3755
|
bridge,
|
|
2870
3756
|
webShellDir,
|
|
2871
3757
|
boundWorkspace,
|
|
@@ -2880,6 +3766,27 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
2880
3766
|
primaryRuntimeEnv,
|
|
2881
3767
|
daemonLog,
|
|
2882
3768
|
getChannelWorkerSnapshot,
|
|
3769
|
+
getChannelWorkerSnapshots,
|
|
3770
|
+
getChannelWorkerControl,
|
|
3771
|
+
isChannelControlDraining: /* @__PURE__ */ __name(() => channelControlDraining, "isChannelControlDraining"),
|
|
3772
|
+
isChannelControlInitializing: /* @__PURE__ */ __name(() => channelWorkerManagerStarting !== void 0, "isChannelControlInitializing"),
|
|
3773
|
+
setChannelWorkerSelection,
|
|
3774
|
+
stopChannelWorker,
|
|
3775
|
+
getChannelWebhookConfigSources,
|
|
3776
|
+
getChannelWebhookConfigVersion: /* @__PURE__ */ __name(() => channelWebhookConfigVersion, "getChannelWebhookConfigVersion"),
|
|
3777
|
+
registerChannelWebhookConfigRefresh: /* @__PURE__ */ __name((refresh) => {
|
|
3778
|
+
refreshChannelWebhookConfigs = refresh;
|
|
3779
|
+
}, "registerChannelWebhookConfigRefresh"),
|
|
3780
|
+
enqueueChannelWebhookTask: /* @__PURE__ */ __name(async (task) => {
|
|
3781
|
+
if (!channelWorkerManager) {
|
|
3782
|
+
throw new ChannelWebhookEnqueueError(
|
|
3783
|
+
"channel_worker_unavailable",
|
|
3784
|
+
"Channel worker is not running."
|
|
3785
|
+
);
|
|
3786
|
+
}
|
|
3787
|
+
return channelWorkerManager.enqueueWebhookTask(task);
|
|
3788
|
+
}, "enqueueChannelWebhookTask"),
|
|
3789
|
+
reloadChannelWorker,
|
|
2883
3790
|
getPerfSnapshot: /* @__PURE__ */ __name(() => ({
|
|
2884
3791
|
eventLoop: currentDaemonEventLoopMonitor.snapshot(),
|
|
2885
3792
|
promptQueueWait: {
|
|
@@ -2901,8 +3808,12 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
2901
3808
|
// so the WS provider and the child-answering bridge share one sender map.
|
|
2902
3809
|
clientMcpSenderRegistry,
|
|
2903
3810
|
persistDisabledTools: persistDisabledToolsFn,
|
|
3811
|
+
persistDisabledSkills: persistDisabledSkillsFn,
|
|
2904
3812
|
persistSetting: persistSettingFn,
|
|
2905
3813
|
persistSettings: persistSettingsFn,
|
|
3814
|
+
sessionArtifactsPersistenceAvailable: sessionArtifactsPersistenceAvailableFromSettings(
|
|
3815
|
+
runtimeBootSettings?.merged
|
|
3816
|
+
),
|
|
2906
3817
|
installAuthProvider: /* @__PURE__ */ __name((req) => withSettingsLock(
|
|
2907
3818
|
boundWorkspace,
|
|
2908
3819
|
async () => {
|
|
@@ -2941,14 +3852,18 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
2941
3852
|
}
|
|
2942
3853
|
), "installAuthProvider")
|
|
2943
3854
|
});
|
|
3855
|
+
invalidatePrimaryServeFeaturesCache = app2.locals.invalidateServeFeaturesCache ?? invalidatePrimaryServeFeaturesCache;
|
|
3856
|
+
app2.locals.subSessionStoppers = subSessionStoppers;
|
|
3857
|
+
subSessionStoppers.push(subSessionLauncher.stop);
|
|
3858
|
+
subSessionStoppersByWorkspace.set(boundWorkspace, subSessionLauncher.stop);
|
|
2944
3859
|
return { app: app2, bridge };
|
|
2945
3860
|
}, "buildRuntime");
|
|
2946
3861
|
if (deps.bridge) {
|
|
2947
3862
|
const runtime = await buildRuntime();
|
|
2948
3863
|
runtimeAppForCleanup = runtime.app;
|
|
2949
|
-
runtimeApp = runtime.app;
|
|
2950
3864
|
bridgeRef = runtime.bridge;
|
|
2951
3865
|
if (!opts.channelSelection) {
|
|
3866
|
+
runtimeApp = runtime.app;
|
|
2952
3867
|
runtimeStartupSettled = true;
|
|
2953
3868
|
markRuntimeReady();
|
|
2954
3869
|
}
|
|
@@ -2962,17 +3877,25 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
2962
3877
|
daemonLog,
|
|
2963
3878
|
qwenCodeVersion: cliVersion,
|
|
2964
3879
|
sessionShellCommandEnabled,
|
|
3880
|
+
sessionArtifactsPersistenceAvailable,
|
|
2965
3881
|
permissionPolicy,
|
|
2966
3882
|
multiWorkspaceCapabilitiesRequireRuntime: workspaceInputs.length > 1,
|
|
2967
3883
|
getRuntimeError: /* @__PURE__ */ __name(() => runtimeStartupError, "getRuntimeError"),
|
|
2968
3884
|
getChannelWorkerSnapshot,
|
|
3885
|
+
getChannelWorkerSnapshots,
|
|
2969
3886
|
onHealthServed: deferRuntimeUntilFirstHealth ? () => startRuntimeAfterHealth?.() : void 0
|
|
2970
3887
|
});
|
|
3888
|
+
const deferredChannelWebhookAuth = deferRuntimeUntilFirstHealth ? createDeferredChannelWebhookAuth(
|
|
3889
|
+
resolveChannelWebhookConfigSource,
|
|
3890
|
+
await loadChannelWebhookConfigRuntime(),
|
|
3891
|
+
daemonLog
|
|
3892
|
+
) : void 0;
|
|
2971
3893
|
const app = runtimeApp ?? createDelegatingServeApp(bootstrapApp, () => runtimeApp, {
|
|
2972
3894
|
waitForDeferredRuntimeRoutes: deferRuntimeUntilFirstHealth,
|
|
2973
3895
|
startRuntime: /* @__PURE__ */ __name(() => startRuntimeForRequest?.(), "startRuntime"),
|
|
2974
3896
|
runtimeReady,
|
|
2975
|
-
authenticateDeferredRuntimeRequest: bearerAuth(opts.token)
|
|
3897
|
+
authenticateDeferredRuntimeRequest: bearerAuth(opts.token),
|
|
3898
|
+
authenticateDeferredChannelWebhookRequest: deferredChannelWebhookAuth
|
|
2976
3899
|
});
|
|
2977
3900
|
let listenHostname = opts.hostname;
|
|
2978
3901
|
if (opts.hostname.startsWith("[")) {
|
|
@@ -2989,7 +3912,70 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
2989
3912
|
`Invalid maxConnections: ${opts.maxConnections}. Must be >= 0 (0 / Infinity = unlimited).`
|
|
2990
3913
|
);
|
|
2991
3914
|
}
|
|
2992
|
-
|
|
3915
|
+
const channelValidationSettingsRuntime = opts.channelSelection ? await loadSettingsRuntimeModules() : void 0;
|
|
3916
|
+
const resolveChannelWorkspaceGroupsAtListen = /* @__PURE__ */ __name(() => {
|
|
3917
|
+
if (!opts.channelSelection || !channelValidationSettingsRuntime || !channelRuntime) {
|
|
3918
|
+
return void 0;
|
|
3919
|
+
}
|
|
3920
|
+
const settingsByWorkspace = /* @__PURE__ */ new Map();
|
|
3921
|
+
if (workspaceInputs.length === 1) {
|
|
3922
|
+
const workspace = workspaceInputs[0];
|
|
3923
|
+
const settings = channelValidationSettingsRuntime.settings.loadSettings(
|
|
3924
|
+
workspace.cwd
|
|
3925
|
+
);
|
|
3926
|
+
channelWebhookEnvByWorkspace.set(
|
|
3927
|
+
workspace.cwd,
|
|
3928
|
+
channelValidationSettingsRuntime.environment.buildRuntimeEnvironment(
|
|
3929
|
+
settings.merged,
|
|
3930
|
+
workspace.cwd,
|
|
3931
|
+
daemonRuntimeBaseEnv
|
|
3932
|
+
).effectiveEnv
|
|
3933
|
+
);
|
|
3934
|
+
return void 0;
|
|
3935
|
+
}
|
|
3936
|
+
const workspaces = workspaceInputs.map((workspace, index) => {
|
|
3937
|
+
const settings = channelValidationSettingsRuntime.settings.loadSettings(
|
|
3938
|
+
workspace.cwd
|
|
3939
|
+
);
|
|
3940
|
+
settingsByWorkspace.set(workspace.cwd, settings);
|
|
3941
|
+
channelWebhookEnvByWorkspace.set(
|
|
3942
|
+
workspace.cwd,
|
|
3943
|
+
channelValidationSettingsRuntime.environment.buildRuntimeEnvironment(
|
|
3944
|
+
settings.merged,
|
|
3945
|
+
workspace.cwd,
|
|
3946
|
+
daemonRuntimeBaseEnv
|
|
3947
|
+
).effectiveEnv
|
|
3948
|
+
);
|
|
3949
|
+
const trusted = index === 0 && deps.trustedWorkspace !== void 0 ? deps.trustedWorkspace : channelValidationSettingsRuntime.trustedFolders.getWorkspaceTrustStatus(
|
|
3950
|
+
settings.merged,
|
|
3951
|
+
workspace.cwd
|
|
3952
|
+
).effective.state === "trusted";
|
|
3953
|
+
return {
|
|
3954
|
+
workspaceCwd: workspace.cwd,
|
|
3955
|
+
primary: index === 0,
|
|
3956
|
+
trusted
|
|
3957
|
+
};
|
|
3958
|
+
});
|
|
3959
|
+
const grouping = resolveChannelWorkspaceGroups({
|
|
3960
|
+
workspaces,
|
|
3961
|
+
selection: opts.channelSelection,
|
|
3962
|
+
loadChannelsConfig: /* @__PURE__ */ __name((cwd) => {
|
|
3963
|
+
const settings = settingsByWorkspace.get(cwd);
|
|
3964
|
+
if (!settings) return {};
|
|
3965
|
+
return channelRuntime.loadChannelsConfig(cwd, settings);
|
|
3966
|
+
}, "loadChannelsConfig")
|
|
3967
|
+
});
|
|
3968
|
+
if (!grouping.ok) {
|
|
3969
|
+
throw Object.assign(new Error(grouping.error.message), {
|
|
3970
|
+
code: grouping.error.code,
|
|
3971
|
+
...grouping.error.channel ? { channel: grouping.error.channel } : {}
|
|
3972
|
+
});
|
|
3973
|
+
}
|
|
3974
|
+
return grouping.groups;
|
|
3975
|
+
}, "resolveChannelWorkspaceGroupsAtListen");
|
|
3976
|
+
if (opts.channelSelection) {
|
|
3977
|
+
reserveChannelServicePidfile(opts.channelSelection);
|
|
3978
|
+
}
|
|
2993
3979
|
return await new Promise((resolve, reject) => {
|
|
2994
3980
|
const onListening = /* @__PURE__ */ __name(() => {
|
|
2995
3981
|
startup.listenerReadyAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -3008,45 +3994,14 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
3008
3994
|
const scheme = tlsOptions ? "https" : "http";
|
|
3009
3995
|
const url = `${scheme}://${formatHostForUrl(opts.hostname)}:${actualPort}`;
|
|
3010
3996
|
try {
|
|
3011
|
-
|
|
3012
|
-
const createSupervisor = deps.channelWorkerSupervisorFactory ?? channelRuntime?.createChannelWorkerSupervisor;
|
|
3013
|
-
if (!createSupervisor) {
|
|
3014
|
-
throw new Error(
|
|
3015
|
-
"Channel worker supervisor runtime is not available."
|
|
3016
|
-
);
|
|
3017
|
-
}
|
|
3018
|
-
channelWorker = createSupervisor({
|
|
3019
|
-
cliEntryPath: findCliEntryPath(),
|
|
3020
|
-
daemonUrl: formatChannelWorkerDaemonUrl(opts.hostname, actualPort),
|
|
3021
|
-
...token ? { daemonToken: token } : {},
|
|
3022
|
-
workspace: boundWorkspace,
|
|
3023
|
-
selection: opts.channelSelection,
|
|
3024
|
-
onReady: /* @__PURE__ */ __name((snapshot) => {
|
|
3025
|
-
writeChannelWorkerPidfile(snapshot);
|
|
3026
|
-
}, "onReady"),
|
|
3027
|
-
onLog: /* @__PURE__ */ __name(({ stream, line }) => {
|
|
3028
|
-
const message = `channel worker ${stream}: ${line}`;
|
|
3029
|
-
if (stream === "stderr") {
|
|
3030
|
-
daemonLog.warn(message);
|
|
3031
|
-
} else {
|
|
3032
|
-
daemonLog.info(message);
|
|
3033
|
-
}
|
|
3034
|
-
}, "onLog"),
|
|
3035
|
-
onExit: /* @__PURE__ */ __name((snapshot) => {
|
|
3036
|
-
daemonLog.warn(
|
|
3037
|
-
`channel worker exited (state=${snapshot.state}, pid=${snapshot.pid ?? "unknown"}, code=${snapshot.exitCode ?? "null"}, signal=${snapshot.signal ?? "null"}, error=${snapshot.error ?? "none"}, restartCount=${snapshot.restartCount ?? 0}, nextRestartAt=${snapshot.nextRestartAt ?? "none"}, staleHeartbeatAt=${snapshot.staleHeartbeatAt ?? "none"})`
|
|
3038
|
-
);
|
|
3039
|
-
writeChannelWorkerPidfile(snapshot, { clearWorkerPid: true });
|
|
3040
|
-
}, "onExit")
|
|
3041
|
-
});
|
|
3042
|
-
}
|
|
3997
|
+
channelWorkspaceGroups = resolveChannelWorkspaceGroupsAtListen();
|
|
3043
3998
|
} catch (err) {
|
|
3044
3999
|
removeCurrentServePidfile();
|
|
3045
4000
|
const error = err instanceof Error ? err : new Error(String(err));
|
|
3046
4001
|
server.close((closeErr) => {
|
|
3047
4002
|
if (closeErr) {
|
|
3048
4003
|
daemonLog.error(
|
|
3049
|
-
"server close after channel worker
|
|
4004
|
+
"server close after channel worker validation error failed",
|
|
3050
4005
|
closeErr
|
|
3051
4006
|
);
|
|
3052
4007
|
}
|
|
@@ -3054,6 +4009,19 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
3054
4009
|
});
|
|
3055
4010
|
return;
|
|
3056
4011
|
}
|
|
4012
|
+
if (channelWorkspaceGroups) {
|
|
4013
|
+
for (const group of channelWorkspaceGroups) {
|
|
4014
|
+
daemonLog.info("channel worker group assigned", {
|
|
4015
|
+
workspace: group.workspaceCwd,
|
|
4016
|
+
channels: group.selection.mode === "all" ? ["all"] : group.selection.names
|
|
4017
|
+
});
|
|
4018
|
+
}
|
|
4019
|
+
if (opts.channelSelection?.mode === "all") {
|
|
4020
|
+
writeStderrLine(
|
|
4021
|
+
"qwen serve: --channel all is primary-workspace only; non-primary workspace channels are not hosted."
|
|
4022
|
+
);
|
|
4023
|
+
}
|
|
4024
|
+
}
|
|
3057
4025
|
writeStdoutLine(
|
|
3058
4026
|
`qwen serve listening on ${url} (mode=${opts.mode}, workspace=${boundWorkspace})`
|
|
3059
4027
|
);
|
|
@@ -3129,20 +4097,28 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
3129
4097
|
}
|
|
3130
4098
|
}, "shutdownBridgeAfterFailedStartup");
|
|
3131
4099
|
const stopChannelWorkerAfterFailedStartup = /* @__PURE__ */ __name(async () => {
|
|
3132
|
-
|
|
4100
|
+
if (!channelWorkerManager) return true;
|
|
4101
|
+
try {
|
|
4102
|
+
await channelWorkerManager.shutdown();
|
|
4103
|
+
return true;
|
|
4104
|
+
} catch (stopErr) {
|
|
3133
4105
|
daemonLog.error(
|
|
3134
4106
|
"channel worker stop after runtime startup error failed",
|
|
3135
4107
|
stopErr instanceof Error ? stopErr : null
|
|
3136
4108
|
);
|
|
3137
|
-
|
|
4109
|
+
return false;
|
|
4110
|
+
}
|
|
3138
4111
|
}, "stopChannelWorkerAfterFailedStartup");
|
|
3139
4112
|
const failRuntimeStartup = /* @__PURE__ */ __name(async (err, bridgeForCleanup) => {
|
|
3140
4113
|
const error = err instanceof Error ? err : new Error(String(err));
|
|
3141
4114
|
if (runtimeStartupSettled) {
|
|
4115
|
+
disposeRuntimeAppResources(runtimeApp ?? runtimeAppForCleanup);
|
|
3142
4116
|
await shutdownBridgeAfterFailedStartup(bridgeForCleanup);
|
|
3143
4117
|
return;
|
|
3144
4118
|
}
|
|
3145
4119
|
runtimeStartupSettled = true;
|
|
4120
|
+
disposeRuntimeAppResources(runtimeApp ?? runtimeAppForCleanup);
|
|
4121
|
+
runtimeApp = void 0;
|
|
3146
4122
|
clearRuntimeStartupTimer();
|
|
3147
4123
|
const message = error.message;
|
|
3148
4124
|
runtimeStartupError = message;
|
|
@@ -3152,14 +4128,28 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
3152
4128
|
}
|
|
3153
4129
|
writeStderrLine(`qwen serve: runtime startup failed: ${message}`);
|
|
3154
4130
|
daemonLog.error("runtime startup failed", error);
|
|
3155
|
-
|
|
4131
|
+
markRuntimeFailed(error);
|
|
4132
|
+
if (closeServerAfterChannelWorkerStartupFailure && server.listening) {
|
|
4133
|
+
runtimeFailureListenerClose = new Promise((resolve2) => {
|
|
4134
|
+
server.close((closeErr) => {
|
|
4135
|
+
if (closeErr) {
|
|
4136
|
+
daemonLog.error(
|
|
4137
|
+
"server close after runtime startup error failed",
|
|
4138
|
+
closeErr
|
|
4139
|
+
);
|
|
4140
|
+
}
|
|
4141
|
+
resolve2();
|
|
4142
|
+
});
|
|
4143
|
+
});
|
|
4144
|
+
server.closeAllConnections();
|
|
4145
|
+
}
|
|
4146
|
+
const channelWorkerStopped = await stopChannelWorkerAfterFailedStartup();
|
|
3156
4147
|
disposeDaemonEventLoopMonitor();
|
|
3157
|
-
removeCurrentServePidfile();
|
|
4148
|
+
if (channelWorkerStopped) removeCurrentServePidfile();
|
|
3158
4149
|
const bridgesForCleanup = bridgeForCleanup ? [bridgeForCleanup, ...getRuntimeBridgesForCleanup()] : getRuntimeBridgesForCleanup();
|
|
3159
4150
|
for (const bridge of [...new Set(bridgesForCleanup)]) {
|
|
3160
4151
|
await shutdownBridgeAfterFailedStartup(bridge);
|
|
3161
4152
|
}
|
|
3162
|
-
markRuntimeFailed(error);
|
|
3163
4153
|
}, "failRuntimeStartup");
|
|
3164
4154
|
const armRuntimeStartupTimer = /* @__PURE__ */ __name(() => {
|
|
3165
4155
|
if (runtimeStartupTimeoutMs <= 0 || runtimeStartupTimer) return;
|
|
@@ -3172,10 +4162,152 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
3172
4162
|
}, runtimeStartupTimeoutMs);
|
|
3173
4163
|
runtimeStartupTimer.unref();
|
|
3174
4164
|
}, "armRuntimeStartupTimer");
|
|
3175
|
-
const
|
|
4165
|
+
const resolveRuntimeChannelGroups = /* @__PURE__ */ __name(async (channelSelection, candidateApp, operation) => {
|
|
4166
|
+
const registry = candidateApp.locals?.["workspaceRegistry"];
|
|
4167
|
+
if (!registry) {
|
|
4168
|
+
throw new Error(
|
|
4169
|
+
"Workspace registry is not available for channel workers."
|
|
4170
|
+
);
|
|
4171
|
+
}
|
|
4172
|
+
const runtimes = registry.list();
|
|
4173
|
+
if (runtimes.length <= 1 && operation === "initial") {
|
|
4174
|
+
return [
|
|
4175
|
+
{
|
|
4176
|
+
workspaceCwd: registry.primary.workspaceCwd,
|
|
4177
|
+
selection: channelSelection
|
|
4178
|
+
}
|
|
4179
|
+
];
|
|
4180
|
+
}
|
|
4181
|
+
const workerRuntime = await ensureChannelRuntime();
|
|
4182
|
+
const settingsRuntime = await loadSettingsRuntimeModules();
|
|
4183
|
+
const settingsByWorkspace = /* @__PURE__ */ new Map();
|
|
4184
|
+
const grouping = resolveChannelWorkspaceGroups({
|
|
4185
|
+
workspaces: runtimes.map((runtime) => {
|
|
4186
|
+
const settings = settingsRuntime.settings.loadSettings(
|
|
4187
|
+
runtime.workspaceCwd
|
|
4188
|
+
);
|
|
4189
|
+
settingsByWorkspace.set(runtime.workspaceCwd, settings);
|
|
4190
|
+
return {
|
|
4191
|
+
workspaceCwd: runtime.workspaceCwd,
|
|
4192
|
+
primary: runtime.primary,
|
|
4193
|
+
trusted: runtime.trusted
|
|
4194
|
+
};
|
|
4195
|
+
}),
|
|
4196
|
+
selection: channelSelection,
|
|
4197
|
+
loadChannelsConfig: /* @__PURE__ */ __name((cwd) => {
|
|
4198
|
+
const settings = settingsByWorkspace.get(cwd);
|
|
4199
|
+
return settings ? workerRuntime.loadChannelsConfig(cwd, settings) : {};
|
|
4200
|
+
}, "loadChannelsConfig")
|
|
4201
|
+
});
|
|
4202
|
+
if (!grouping.ok) {
|
|
4203
|
+
throw Object.assign(new Error(grouping.error.message), {
|
|
4204
|
+
code: grouping.error.code,
|
|
4205
|
+
...grouping.error.channel ? { channel: grouping.error.channel } : {}
|
|
4206
|
+
});
|
|
4207
|
+
}
|
|
4208
|
+
return grouping.groups;
|
|
4209
|
+
}, "resolveRuntimeChannelGroups");
|
|
4210
|
+
ensureChannelWorkerManager = /* @__PURE__ */ __name(() => {
|
|
4211
|
+
if (channelWorkerManager) return Promise.resolve(channelWorkerManager);
|
|
4212
|
+
if (channelWorkerManagerStarting) return channelWorkerManagerStarting;
|
|
4213
|
+
const starting = (async () => {
|
|
4214
|
+
const candidateApp = runtimeApp ?? runtimeAppForCleanup;
|
|
4215
|
+
const registry = candidateApp?.locals?.["workspaceRegistry"];
|
|
4216
|
+
if (!candidateApp || !registry) {
|
|
4217
|
+
throw new Error(
|
|
4218
|
+
"Workspace registry is not available for channels."
|
|
4219
|
+
);
|
|
4220
|
+
}
|
|
4221
|
+
const workerRuntime = await ensureChannelRuntime();
|
|
4222
|
+
const createSupervisor = deps.channelWorkerSupervisorFactory ?? workerRuntime.createChannelWorkerSupervisor;
|
|
4223
|
+
const createGroup = /* @__PURE__ */ __name((groups) => workerRuntime.createChannelWorkerGroup({
|
|
4224
|
+
groups,
|
|
4225
|
+
registry,
|
|
4226
|
+
createSupervisor,
|
|
4227
|
+
shared: {
|
|
4228
|
+
cliEntryPath: workerRuntime.findCliEntryPath(),
|
|
4229
|
+
daemonUrl: formatChannelWorkerDaemonUrl(
|
|
4230
|
+
opts.hostname,
|
|
4231
|
+
actualPort
|
|
4232
|
+
),
|
|
4233
|
+
...token ? { daemonToken: token } : {}
|
|
4234
|
+
},
|
|
4235
|
+
onReady: /* @__PURE__ */ __name((snapshot) => {
|
|
4236
|
+
if (runtimeStartupError !== void 0) return;
|
|
4237
|
+
if (workspaceInputs.length > 1) {
|
|
4238
|
+
daemonLog.info("channel worker ready", {
|
|
4239
|
+
workspace: snapshot.workspaceCwd,
|
|
4240
|
+
pid: snapshot.pid,
|
|
4241
|
+
channels: snapshot.channels
|
|
4242
|
+
});
|
|
4243
|
+
}
|
|
4244
|
+
channelWorkerManager?.workerChanged();
|
|
4245
|
+
if (!runtimeStartupSettled) writeChannelWorkerPidfile();
|
|
4246
|
+
}, "onReady"),
|
|
4247
|
+
onExit: /* @__PURE__ */ __name((snapshot) => {
|
|
4248
|
+
const workspacePrefix = workspaceInputs.length > 1 ? `workspace=${snapshot.workspaceCwd}, ` : "";
|
|
4249
|
+
daemonLog.warn(
|
|
4250
|
+
`channel worker exited (${workspacePrefix}state=${snapshot.state}, pid=${snapshot.pid ?? "unknown"}, code=${snapshot.exitCode ?? "null"}, signal=${snapshot.signal ?? "null"}, error=${snapshot.error ?? "none"}, restartCount=${snapshot.restartCount ?? 0}, nextRestartAt=${snapshot.nextRestartAt ?? "none"}, staleHeartbeatAt=${snapshot.staleHeartbeatAt ?? "none"})`
|
|
4251
|
+
);
|
|
4252
|
+
channelWorkerManager?.workerChanged();
|
|
4253
|
+
if (!runtimeStartupSettled) writeChannelWorkerPidfile();
|
|
4254
|
+
}, "onExit"),
|
|
4255
|
+
onStateChange: /* @__PURE__ */ __name(() => {
|
|
4256
|
+
channelWorkerManager?.workerChanged();
|
|
4257
|
+
if (!runtimeStartupSettled) writeChannelWorkerPidfile();
|
|
4258
|
+
}, "onStateChange"),
|
|
4259
|
+
onLog: /* @__PURE__ */ __name(({ stream, line, workspaceCwd }) => {
|
|
4260
|
+
const message = workspaceInputs.length > 1 ? `channel worker [${workspaceCwd}] ${stream}: ${line}` : `channel worker ${stream}: ${line}`;
|
|
4261
|
+
if (stream === "stderr") daemonLog.warn(message);
|
|
4262
|
+
else daemonLog.info(message);
|
|
4263
|
+
}, "onLog")
|
|
4264
|
+
}), "createGroup");
|
|
4265
|
+
channelWorkerManager = workerRuntime.createChannelWorkerManager({
|
|
4266
|
+
resolveGroups: /* @__PURE__ */ __name((selection, operation) => resolveRuntimeChannelGroups(selection, candidateApp, operation), "resolveGroups"),
|
|
4267
|
+
createGroup,
|
|
4268
|
+
reserveLease: reserveChannelServicePidfile,
|
|
4269
|
+
releaseLease: /* @__PURE__ */ __name(() => {
|
|
4270
|
+
removeCurrentServePidfile();
|
|
4271
|
+
if (channelPidfileReserved) {
|
|
4272
|
+
throw new Error("Failed to release the channel service lease.");
|
|
4273
|
+
}
|
|
4274
|
+
}, "releaseLease"),
|
|
4275
|
+
initialLeaseReserved: channelPidfileReserved,
|
|
4276
|
+
onCommittedSelection: /* @__PURE__ */ __name((_selection, groups) => {
|
|
4277
|
+
channelWorkspaceGroups = groups;
|
|
4278
|
+
channelWebhookConfigVersion += 1;
|
|
4279
|
+
refreshChannelWebhookConfigs?.();
|
|
4280
|
+
}, "onCommittedSelection"),
|
|
4281
|
+
onStateChange: /* @__PURE__ */ __name(() => {
|
|
4282
|
+
if (runtimeStartupSettled) writeChannelWorkerPidfile();
|
|
4283
|
+
}, "onStateChange")
|
|
4284
|
+
});
|
|
4285
|
+
return channelWorkerManager;
|
|
4286
|
+
})();
|
|
4287
|
+
channelWorkerManagerStarting = starting;
|
|
4288
|
+
void starting.then(
|
|
4289
|
+
() => {
|
|
4290
|
+
if (channelWorkerManagerStarting === starting) {
|
|
4291
|
+
channelWorkerManagerStarting = void 0;
|
|
4292
|
+
}
|
|
4293
|
+
},
|
|
4294
|
+
() => {
|
|
4295
|
+
if (channelWorkerManagerStarting === starting) {
|
|
4296
|
+
channelWorkerManagerStarting = void 0;
|
|
4297
|
+
}
|
|
4298
|
+
}
|
|
4299
|
+
);
|
|
4300
|
+
return starting;
|
|
4301
|
+
}, "ensureChannelWorkerManager");
|
|
4302
|
+
const completeRuntimeStartup = /* @__PURE__ */ __name(async (candidateApp) => {
|
|
3176
4303
|
if (runtimeStartupSettled) return;
|
|
4304
|
+
runtimeApp = candidateApp;
|
|
4305
|
+
const acpHandle = candidateApp.locals?.["acpHandle"];
|
|
4306
|
+
acpHandle?.attachServer?.(server);
|
|
3177
4307
|
if (opts.channelSelection) {
|
|
3178
|
-
|
|
4308
|
+
closeServerAfterChannelWorkerStartupFailure = true;
|
|
4309
|
+
const manager = await ensureChannelWorkerManager();
|
|
4310
|
+
await manager.startInitial(opts.channelSelection);
|
|
3179
4311
|
if (runtimeStartupSettled) return;
|
|
3180
4312
|
}
|
|
3181
4313
|
if (runtimeStartupSettled) return;
|
|
@@ -3210,6 +4342,7 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
3210
4342
|
clearRuntimeStartFallbackTimer();
|
|
3211
4343
|
runtimeStarting = buildRuntime().then(async (runtime) => {
|
|
3212
4344
|
if (runtimeStartupSettled) {
|
|
4345
|
+
disposeRuntimeAppResources(runtime.app);
|
|
3213
4346
|
await shutdownBridgeAfterFailedStartup(runtime.bridge);
|
|
3214
4347
|
return;
|
|
3215
4348
|
}
|
|
@@ -3222,13 +4355,10 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
3222
4355
|
);
|
|
3223
4356
|
return;
|
|
3224
4357
|
}
|
|
3225
|
-
runtimeApp = runtime.app;
|
|
3226
|
-
const acpHandle = runtime.app.locals?.["acpHandle"];
|
|
3227
|
-
acpHandle?.attachServer?.(server);
|
|
3228
4358
|
if (shouldPreheat) {
|
|
3229
4359
|
startBridgePreheat(runtime.bridge);
|
|
3230
4360
|
}
|
|
3231
|
-
await completeRuntimeStartup();
|
|
4361
|
+
await completeRuntimeStartup(runtime.app);
|
|
3232
4362
|
}).catch((err) => failRuntimeStartup(err));
|
|
3233
4363
|
}, "startRuntime");
|
|
3234
4364
|
startRuntimeForRequest = startRuntime;
|
|
@@ -3266,11 +4396,10 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
3266
4396
|
if (shuttingDown) {
|
|
3267
4397
|
daemonLog.warn(`received ${signal} during drain \u2014 forcing exit`);
|
|
3268
4398
|
try {
|
|
3269
|
-
|
|
4399
|
+
channelWorkerManager?.killAllSync();
|
|
3270
4400
|
for (const runtimeBridge of getRuntimeBridgesForCleanup()) {
|
|
3271
4401
|
runtimeBridge.killAllSync();
|
|
3272
4402
|
}
|
|
3273
|
-
removeCurrentServePidfile();
|
|
3274
4403
|
} catch (err) {
|
|
3275
4404
|
daemonLog.error(
|
|
3276
4405
|
"force-kill error",
|
|
@@ -3286,16 +4415,24 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
3286
4415
|
try {
|
|
3287
4416
|
await handle.close();
|
|
3288
4417
|
await daemonLog.flush();
|
|
3289
|
-
process.exit(0);
|
|
4418
|
+
process.exit(runtimeStartupError === void 0 ? 0 : 1);
|
|
3290
4419
|
} catch (err) {
|
|
3291
4420
|
daemonLog.error("shutdown error", err instanceof Error ? err : null);
|
|
3292
4421
|
await daemonLog.flush().catch(() => {
|
|
3293
4422
|
});
|
|
4423
|
+
if (channelWorkerManager?.state().enabled) {
|
|
4424
|
+
daemonLog.error(
|
|
4425
|
+
"refusing to exit while a channel worker or service lease remains; signal again to retry after the child exits (another signal during that retry forces exit)"
|
|
4426
|
+
);
|
|
4427
|
+
await daemonLog.flush().catch(() => {
|
|
4428
|
+
});
|
|
4429
|
+
return;
|
|
4430
|
+
}
|
|
3294
4431
|
process.exit(1);
|
|
3295
4432
|
}
|
|
3296
4433
|
}, "onSignal");
|
|
3297
4434
|
const onUncaughtExceptionMonitor = /* @__PURE__ */ __name(() => {
|
|
3298
|
-
if (process.listenerCount("uncaughtException") === 0) {
|
|
4435
|
+
if (process.listenerCount("uncaughtException") === 0 && !channelWorkerManager?.state().enabled) {
|
|
3299
4436
|
removeCurrentServePidfile();
|
|
3300
4437
|
}
|
|
3301
4438
|
}, "onUncaughtExceptionMonitor");
|
|
@@ -3310,17 +4447,24 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
3310
4447
|
if (closePromise) return closePromise;
|
|
3311
4448
|
closePromise = new Promise((res, rej) => {
|
|
3312
4449
|
shuttingDown = true;
|
|
3313
|
-
|
|
4450
|
+
channelControlDraining = true;
|
|
4451
|
+
const initiallyMountedApp = runtimeApp ?? runtimeAppForCleanup;
|
|
4452
|
+
const initiallyMountedManagement = initiallyMountedApp?.locals?.["workspaceManagementHandle"];
|
|
4453
|
+
const initialManagementWait = initiallyMountedManagement?.sealAndWait?.();
|
|
3314
4454
|
clearRuntimeStartAfterHealthTimer();
|
|
3315
4455
|
clearRuntimeStartFallbackTimer();
|
|
3316
4456
|
cancelDeferredRuntimeStartup();
|
|
3317
4457
|
let settled = false;
|
|
3318
4458
|
let bridgeShutdownError;
|
|
4459
|
+
let channelWorkerShutdownError;
|
|
3319
4460
|
const finish = /* @__PURE__ */ __name((err) => {
|
|
3320
4461
|
if (settled) return;
|
|
3321
4462
|
settled = true;
|
|
3322
|
-
|
|
3323
|
-
|
|
4463
|
+
const preserveSignalHandlers = channelWorkerShutdownError !== void 0 && channelWorkerManager?.state().enabled === true;
|
|
4464
|
+
if (!preserveSignalHandlers) {
|
|
4465
|
+
process.removeListener("SIGINT", onSignal);
|
|
4466
|
+
process.removeListener("SIGTERM", onSignal);
|
|
4467
|
+
}
|
|
3324
4468
|
process.removeListener(
|
|
3325
4469
|
"uncaughtExceptionMonitor",
|
|
3326
4470
|
onUncaughtExceptionMonitor
|
|
@@ -3331,9 +4475,17 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
3331
4475
|
);
|
|
3332
4476
|
}).finally(() => daemonLog.flush().catch(() => {
|
|
3333
4477
|
})).finally(() => {
|
|
3334
|
-
const finalErr = err ?? bridgeShutdownError;
|
|
3335
|
-
if (finalErr)
|
|
3336
|
-
|
|
4478
|
+
const finalErr = err ?? bridgeShutdownError ?? channelWorkerShutdownError;
|
|
4479
|
+
if (finalErr) {
|
|
4480
|
+
if (channelWorkerShutdownError && channelWorkerManager?.state().enabled) {
|
|
4481
|
+
closePromise = void 0;
|
|
4482
|
+
shuttingDown = false;
|
|
4483
|
+
channelControlDraining = false;
|
|
4484
|
+
}
|
|
4485
|
+
rej(finalErr);
|
|
4486
|
+
} else {
|
|
4487
|
+
res();
|
|
4488
|
+
}
|
|
3337
4489
|
});
|
|
3338
4490
|
}, "finish");
|
|
3339
4491
|
void (coreRuntimePromise ? coreRuntimePromise.then((core) => core.forceFlushMetrics()) : Promise.resolve()).catch((flushErr) => {
|
|
@@ -3347,43 +4499,54 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
3347
4499
|
daemonLog
|
|
3348
4500
|
);
|
|
3349
4501
|
const appForCleanup = runtimeApp ?? runtimeAppForCleanup;
|
|
3350
|
-
const
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
} catch (err) {
|
|
3355
|
-
daemonLog.warn(
|
|
3356
|
-
`device-flow registry dispose error: ${err instanceof Error ? err.message : String(err)}`
|
|
3357
|
-
);
|
|
3358
|
-
}
|
|
4502
|
+
const workspaceManagementHandle = appForCleanup?.locals?.["workspaceManagementHandle"];
|
|
4503
|
+
await initialManagementWait;
|
|
4504
|
+
if (workspaceManagementHandle !== initiallyMountedManagement) {
|
|
4505
|
+
await workspaceManagementHandle?.sealAndWait?.();
|
|
3359
4506
|
}
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
4507
|
+
disposeRuntimeAppResources(appForCleanup);
|
|
4508
|
+
disposeDaemonEventLoopMonitor();
|
|
4509
|
+
if (channelWorkerManager) {
|
|
4510
|
+
await channelWorkerManager.shutdown().catch((err) => {
|
|
4511
|
+
daemonLog.error(
|
|
4512
|
+
"channel worker stop error",
|
|
4513
|
+
err instanceof Error ? err : null
|
|
3367
4514
|
);
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
rl.setDraining(true);
|
|
3373
|
-
rl.dispose();
|
|
4515
|
+
channelWorkerShutdownError = err instanceof Error ? err : new Error(String(err));
|
|
4516
|
+
});
|
|
4517
|
+
} else {
|
|
4518
|
+
removeCurrentServePidfile();
|
|
3374
4519
|
}
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
4520
|
+
const runtimeRemoval = appForCleanup?.locals?.["workspaceRuntimeRemoval"];
|
|
4521
|
+
const workspaceRegistry = appForCleanup?.locals?.["workspaceRegistry"];
|
|
4522
|
+
const managedRuntimeBridges = /* @__PURE__ */ new Set();
|
|
4523
|
+
if (runtimeRemoval && workspaceRegistry) {
|
|
4524
|
+
const managedRuntimes = workspaceRegistry.listManaged();
|
|
4525
|
+
for (const workspaceRuntime of managedRuntimes) {
|
|
4526
|
+
managedRuntimeBridges.add(workspaceRuntime.bridge);
|
|
4527
|
+
}
|
|
4528
|
+
await Promise.all(
|
|
4529
|
+
managedRuntimes.map(
|
|
4530
|
+
(workspaceRuntime) => runtimeRemoval.disposeRuntime(workspaceRuntime, "daemon_shutdown").catch((err) => {
|
|
4531
|
+
daemonLog.error(
|
|
4532
|
+
"workspace runtime shutdown error",
|
|
4533
|
+
err instanceof Error ? err : null
|
|
4534
|
+
);
|
|
4535
|
+
bridgeShutdownError = err instanceof Error ? err : new Error(String(err));
|
|
4536
|
+
try {
|
|
4537
|
+
workspaceRuntime.bridge.killAllSync();
|
|
4538
|
+
} catch {
|
|
4539
|
+
}
|
|
4540
|
+
})
|
|
4541
|
+
)
|
|
3380
4542
|
);
|
|
3381
|
-
}
|
|
3382
|
-
removeCurrentServePidfile();
|
|
4543
|
+
}
|
|
3383
4544
|
for (const bridgeForShutdown of getRuntimeBridgesForCleanup()) {
|
|
4545
|
+
if (managedRuntimeBridges.has(bridgeForShutdown)) continue;
|
|
3384
4546
|
if (shutdownBridges.has(bridgeForShutdown)) continue;
|
|
3385
4547
|
shutdownBridges.add(bridgeForShutdown);
|
|
3386
4548
|
await bridgeForShutdown.shutdown().catch((err) => {
|
|
4549
|
+
shutdownBridges.delete(bridgeForShutdown);
|
|
3387
4550
|
daemonLog.error(
|
|
3388
4551
|
"bridge shutdown error",
|
|
3389
4552
|
err instanceof Error ? err : null
|
|
@@ -3392,6 +4555,12 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
3392
4555
|
});
|
|
3393
4556
|
}
|
|
3394
4557
|
}).finally(() => {
|
|
4558
|
+
if (!server.listening) {
|
|
4559
|
+
void (runtimeFailureListenerClose ?? Promise.resolve()).then(
|
|
4560
|
+
() => finish()
|
|
4561
|
+
);
|
|
4562
|
+
return;
|
|
4563
|
+
}
|
|
3395
4564
|
const SECONDARY_DEADLINE_MS = 2e3;
|
|
3396
4565
|
let secondaryTimer;
|
|
3397
4566
|
const forceTimer = setTimeout(() => {
|
|
@@ -3425,17 +4594,19 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
3425
4594
|
server.on("error", (err) => {
|
|
3426
4595
|
daemonLog.error("server error", err instanceof Error ? err : null);
|
|
3427
4596
|
});
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
acpHandle?.attachServer?.(server);
|
|
4597
|
+
const preparedRuntimeApp = runtimeApp ?? runtimeAppForCleanup;
|
|
4598
|
+
if (preparedRuntimeApp && bridgeRef && deps.bridge) {
|
|
3431
4599
|
if (shouldPreheat) {
|
|
3432
4600
|
startBridgePreheat(bridgeRef);
|
|
3433
4601
|
}
|
|
3434
4602
|
if (opts.channelSelection && !runtimeStartupSettled) {
|
|
3435
4603
|
armRuntimeStartupTimer();
|
|
3436
|
-
runtimeStarting = completeRuntimeStartup().catch(
|
|
4604
|
+
runtimeStarting = completeRuntimeStartup(preparedRuntimeApp).catch(
|
|
3437
4605
|
(err) => failRuntimeStartup(err, bridgeRef)
|
|
3438
4606
|
);
|
|
4607
|
+
} else {
|
|
4608
|
+
const acpHandle = preparedRuntimeApp.locals?.["acpHandle"];
|
|
4609
|
+
acpHandle?.attachServer?.(server);
|
|
3439
4610
|
}
|
|
3440
4611
|
} else if (deferRuntimeUntilFirstHealth) {
|
|
3441
4612
|
scheduleRuntimeStartFallback();
|
|
@@ -3448,14 +4619,24 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
3448
4619
|
void runtimeReady.then(
|
|
3449
4620
|
() => resolve(handle),
|
|
3450
4621
|
(err) => {
|
|
3451
|
-
void handle.close().
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
)
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
4622
|
+
void handle.close().then(
|
|
4623
|
+
() => {
|
|
4624
|
+
reject(err instanceof Error ? err : new Error(String(err)));
|
|
4625
|
+
},
|
|
4626
|
+
(closeErr) => {
|
|
4627
|
+
daemonLog.error(
|
|
4628
|
+
"shutdown after runtime startup error failed",
|
|
4629
|
+
closeErr instanceof Error ? closeErr : null
|
|
4630
|
+
);
|
|
4631
|
+
if (channelWorkerManager?.state().enabled) {
|
|
4632
|
+
daemonLog.error(
|
|
4633
|
+
"runtime startup failed, but qwen serve remains alive to retain the channel service lease until worker exit is confirmed"
|
|
4634
|
+
);
|
|
4635
|
+
return;
|
|
4636
|
+
}
|
|
4637
|
+
reject(err instanceof Error ? err : new Error(String(err)));
|
|
4638
|
+
}
|
|
4639
|
+
);
|
|
3459
4640
|
}
|
|
3460
4641
|
);
|
|
3461
4642
|
}
|
|
@@ -3512,6 +4693,7 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
3512
4693
|
__name(runQwenServe, "runQwenServe");
|
|
3513
4694
|
export {
|
|
3514
4695
|
InvalidPolicyConfigError,
|
|
4696
|
+
createDisabledChannelWorkerSupervisor,
|
|
3515
4697
|
createLazyBridgeProxy,
|
|
3516
4698
|
extractContextFilename,
|
|
3517
4699
|
formatChannelWorkerDaemonUrl,
|
|
@@ -3522,11 +4704,11 @@ export {
|
|
|
3522
4704
|
};
|
|
3523
4705
|
/**
|
|
3524
4706
|
* @license
|
|
3525
|
-
* Copyright
|
|
4707
|
+
* Copyright 2025 Qwen Team
|
|
3526
4708
|
* SPDX-License-Identifier: Apache-2.0
|
|
3527
4709
|
*/
|
|
3528
4710
|
/**
|
|
3529
4711
|
* @license
|
|
3530
|
-
* Copyright
|
|
4712
|
+
* Copyright 2026 Qwen Team
|
|
3531
4713
|
* SPDX-License-Identifier: Apache-2.0
|
|
3532
4714
|
*/
|