@qwen-code/qwen-code 0.19.12 → 0.20.0-nightly.20260720.0c271659d
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundled/qc-helper/docs/integration-github-action.md +1 -1
- package/bundled/qc-helper/docs/qwen-serve.md +42 -5
- package/bundled/review/DESIGN.md +2 -2
- package/bundled/review/SKILL.md +13 -9
- package/chunks/{MaxSizedBox-QOXLJGAF.js → MaxSizedBox-ED3QND6V.js} +30 -27
- package/chunks/{StandaloneSessionPicker-FLV6CGYJ.js → StandaloneSessionPicker-NQVAOTKS.js} +50 -45
- package/chunks/{acpAgent-OB2CTF3P.js → acpAgent-HOBFF5B6.js} +353 -130
- package/chunks/{agent-CKSI7BTR.js → agent-J7EPFLA6.js} +22 -22
- package/chunks/{agent-headless-U36LIYTU.js → agent-headless-RRG3JU7Q.js} +22 -22
- package/chunks/{anthropicContentGenerator-ZZRGFEES.js → anthropicContentGenerator-HVKLXOOU.js} +6 -5
- package/chunks/{artifact-tool-PHO5XEGZ.js → artifact-tool-WBCAMD3O.js} +2 -2
- package/chunks/{askUserQuestion-CEPBT47X.js → askUserQuestion-6DZC4UV5.js} +2 -2
- package/chunks/{bridge-AIKTINJG.js → bridge-OW5FZ6BF.js} +25 -25
- package/chunks/build-SSCNEHZZ.js +62 -0
- package/chunks/{channel-worker-group-NEUVTPB2.js → channel-worker-group-53CMOPFT.js} +4 -4
- package/chunks/{channel-worker-manager-7CQVOVWV.js → channel-worker-manager-UTXILKC2.js} +4 -4
- package/chunks/{channel-worker-supervisor-3BU2KNCZ.js → channel-worker-supervisor-ZGO2W2MD.js} +3 -3
- package/chunks/chunk-27AJEU6G.js +442 -0
- package/chunks/{chunk-BABX5XRO.js → chunk-2HOVDT7W.js} +1 -1
- package/chunks/{chunk-GW7BONBU.js → chunk-2JOLZA6L.js} +5 -5
- package/chunks/{chunk-ZSDFNE6Y.js → chunk-2TDSM7I6.js} +3 -3
- package/chunks/{chunk-6IITZE7O.js → chunk-2YJLFCYI.js} +7 -7
- package/chunks/{chunk-VEFR4XJQ.js → chunk-37MGCVTS.js} +1 -1
- package/chunks/{chunk-3B6PSWHE.js → chunk-3ML52IFS.js} +4 -4
- package/chunks/{chunk-TKASNYDS.js → chunk-3QR5MOHP.js} +2 -2
- package/chunks/{chunk-KRMARA3A.js → chunk-3SNKL6L6.js} +29 -13
- package/chunks/{chunk-DJ4VHAFJ.js → chunk-3ZL6YMO2.js} +3 -3
- package/chunks/chunk-43T5WDQ7.js +127 -0
- package/chunks/{chunk-W6CQPLWM.js → chunk-4ODB7WIB.js} +1 -1
- package/chunks/{chunk-CHPQFLW6.js → chunk-4UH63YE5.js} +5 -5
- package/chunks/{chunk-2CCDMJM7.js → chunk-53OPIXUE.js} +3 -3
- package/chunks/{chunk-HTHUX2T5.js → chunk-5QWWOFGG.js} +0 -1
- package/chunks/{chunk-3DJY4IFO.js → chunk-5SCI6E3E.js} +1 -1
- package/chunks/{chunk-4CHDYDG3.js → chunk-6EFTQYW7.js} +1 -1
- package/chunks/{chunk-OBSLEYCD.js → chunk-6HQW55TM.js} +29 -2
- package/chunks/{chunk-N47VAEAJ.js → chunk-6MN6XJTR.js} +2379 -1291
- package/chunks/{chunk-UCTCDLDS.js → chunk-6VGRTGOG.js} +1 -1
- package/chunks/{chunk-KNGZ5EYL.js → chunk-7JQK6FXK.js} +198 -120
- package/chunks/{chunk-2476XGOU.js → chunk-A4TJMY65.js} +1 -1
- package/chunks/{chunk-67Q33DQY.js → chunk-AMRWCMX4.js} +4 -4
- package/chunks/{chunk-XAAEDML2.js → chunk-AYCDXHZB.js} +1 -1
- package/chunks/{chunk-VAJS2E2D.js → chunk-BDBMYST4.js} +1 -1
- package/chunks/{chunk-F2RR4HO2.js → chunk-BVLROR2T.js} +1 -1
- package/chunks/{chunk-UE5TZ55T.js → chunk-C27BYUX6.js} +29 -2
- package/chunks/{chunk-PK7COE5O.js → chunk-CL7IRYTA.js} +1 -1
- package/chunks/{chunk-KMJOMWHE.js → chunk-COWNNAWJ.js} +1 -1
- package/chunks/{chunk-UOA2IHRI.js → chunk-CPCVCKKF.js} +1 -1
- package/chunks/{chunk-4RPARQ5D.js → chunk-D2VIDMVM.js} +2 -2
- package/chunks/{chunk-4MPYGENG.js → chunk-DCCW7CRR.js} +6 -6
- package/chunks/chunk-DIKIJS6Z.js +114 -0
- package/chunks/{chunk-ETN2G32U.js → chunk-DR5AUNJ2.js} +4 -4
- package/chunks/{chunk-6ETOSWAO.js → chunk-DSBCU6JY.js} +3 -3
- package/chunks/{chunk-LKR7QQ63.js → chunk-EAUYY7SS.js} +3 -3
- package/chunks/{chunk-J2MKYJKZ.js → chunk-EIAK6Q2B.js} +2 -2
- package/chunks/{chunk-WEPXQKGP.js → chunk-EZVDJFZ7.js} +1 -1
- package/chunks/{chunk-WHQNBBWW.js → chunk-FLSVD6BS.js} +2 -2
- package/chunks/{chunk-3ESL7JXA.js → chunk-FODJ5Q5K.js} +3 -3
- package/chunks/{chunk-4XCVGEEX.js → chunk-FSL5W5TI.js} +3 -3
- package/chunks/{chunk-NE6HHLL3.js → chunk-FWT66O5E.js} +2 -2
- package/chunks/{chunk-OSSDHJDU.js → chunk-G45X5TRN.js} +1 -1
- package/chunks/{chunk-ZGT623SG.js → chunk-G6MDKXDP.js} +12 -12
- package/chunks/{chunk-KANTXY7B.js → chunk-GKY2OJ7R.js} +2 -2
- package/chunks/chunk-GMGDLUC7.js +37 -0
- package/chunks/{chunk-J6NT5YTN.js → chunk-H2XVO6NE.js} +1 -289
- package/chunks/{chunk-XSEWNUMZ.js → chunk-I4HZ4GOD.js} +8 -8
- package/chunks/{chunk-CPU6I5YV.js → chunk-I6JUVU7J.js} +34 -24
- package/chunks/{chunk-UZC5VPOJ.js → chunk-IDGTC5AS.js} +3 -3
- package/chunks/{chunk-QIFTJDBY.js → chunk-INL2RSLA.js} +1 -1
- package/chunks/{chunk-GSPWDTYY.js → chunk-INQQM52C.js} +18 -16
- package/chunks/{chunk-HVGJWOR6.js → chunk-JBCFW3IL.js} +2 -2
- package/chunks/{chunk-LPHGXXZX.js → chunk-JD3MKVKL.js} +1 -1
- package/chunks/{chunk-GCY7QTCE.js → chunk-JDPCOUZ3.js} +1602 -398
- package/chunks/{chunk-NUHSLBJZ.js → chunk-JNWZQ27S.js} +15 -9
- package/chunks/{chunk-KGWA7XYL.js → chunk-JRJ2LV6P.js} +6 -226
- package/chunks/{chunk-QSG4ZFG4.js → chunk-KTUQMDEP.js} +1 -1
- package/chunks/{chunk-RKUMFUFM.js → chunk-LTQ5C5AB.js} +4 -4
- package/chunks/{chunk-V4PCIS25.js → chunk-MAQQGNQ5.js} +44 -1
- package/chunks/{chunk-EISVEV45.js → chunk-NBMIC7DR.js} +2 -2
- package/chunks/{chunk-GEHSF7MS.js → chunk-NEEB7UEN.js} +2545 -1974
- package/chunks/{chunk-BKNPMEN6.js → chunk-NIJEXGV6.js} +93 -17
- package/chunks/{chunk-PR5XQ73G.js → chunk-NQVA6O7F.js} +2 -2
- package/chunks/{chunk-FUSMC3SZ.js → chunk-NT324EJ6.js} +13 -8
- package/chunks/{chunk-5N7M4XYN.js → chunk-O2SPEQFA.js} +5 -5
- package/chunks/{chunk-OEHCAWUA.js → chunk-OLMETXLX.js} +2 -2
- package/chunks/{chunk-JCJPZMJV.js → chunk-OOCI5VVU.js} +1 -1
- package/chunks/{chunk-XSPFQQRE.js → chunk-OONJNQ42.js} +3 -3
- package/chunks/{chunk-ANRANWVE.js → chunk-OP4MOGXF.js} +1 -1
- package/chunks/{chunk-SGPFJMRP.js → chunk-PBATSWUQ.js} +1 -1
- package/chunks/chunk-QKYTTBYW.js +624 -0
- package/chunks/{chunk-W4UN42YP.js → chunk-QOSKUG5P.js} +77 -20
- package/chunks/{chunk-76BFY7AF.js → chunk-QTERJVPZ.js} +1 -6
- package/chunks/{chunk-WIYV7CSF.js → chunk-RB7NXUP5.js} +3 -3
- package/chunks/{chunk-HCCR43AY.js → chunk-RFIAR4YL.js} +1 -1
- package/chunks/{chunk-GMUPIMHF.js → chunk-RS5JPH6Y.js} +3 -3
- package/chunks/chunk-RS7MT2QG.js +305 -0
- package/chunks/{chunk-GXFYV7MP.js → chunk-SG2PEESS.js} +1106 -592
- package/chunks/{chunk-PUKUUASO.js → chunk-SLLG5XXE.js} +1 -1
- package/chunks/{chunk-GLH2NTPB.js → chunk-SQMTULHJ.js} +1 -1
- package/chunks/{chunk-NPMVLWYL.js → chunk-STFP7PJR.js} +6 -6
- package/chunks/chunk-SV5PQVQE.js +71 -0
- package/chunks/{chunk-HZ4M2UQD.js → chunk-TFNZCC4B.js} +1 -1
- package/chunks/{chunk-5QSVANRT.js → chunk-THNJYTA6.js} +2 -2
- package/chunks/{chunk-MRE77ST5.js → chunk-TN2BYMNH.js} +69 -2216
- package/chunks/{chunk-64GC5EMF.js → chunk-TQBA6DVX.js} +1 -1
- package/chunks/{chunk-VLHQMOZK.js → chunk-U24E4R5U.js} +3 -3
- package/chunks/{chunk-4CA4WUMS.js → chunk-UEY4AYUL.js} +2 -2
- package/chunks/{chunk-42VIHAYT.js → chunk-UGRL5B5F.js} +1 -1
- package/chunks/chunk-V7RNNPGC.js +44 -0
- package/chunks/{chunk-R3EDIMYZ.js → chunk-VGFFYNBD.js} +1 -1
- package/chunks/chunk-VIOFKPPN.js +125 -0
- package/chunks/{chunk-BEZPRKD3.js → chunk-VLDBVLC4.js} +156 -2
- package/chunks/{chunk-HD6EGS5K.js → chunk-VWLLDHAY.js} +6 -6
- package/chunks/chunk-WCDH2CRI.js +1187 -0
- package/chunks/{chunk-7SX6WZNO.js → chunk-XVVH63JG.js} +3 -3
- package/chunks/{chunk-I7RRHHYG.js → chunk-Y2ENGUD6.js} +1 -1
- package/chunks/{chunk-NALRQ3SG.js → chunk-Y5534U4G.js} +332 -116
- package/chunks/{chunk-4SJJT466.js → chunk-YDZ6J2BY.js} +72 -159
- package/chunks/{chunk-APOFULHK.js → chunk-YNBP3YSU.js} +7 -6
- package/chunks/{chunk-EFAXBOQO.js → chunk-YWEW33JY.js} +7 -7
- package/chunks/{chunk-335ECZTA.js → chunk-ZEOZL37W.js} +1 -1
- package/chunks/{chunk-DUR7BZYK.js → chunk-ZGJ4LDD2.js} +53 -28
- package/chunks/{computer-use-4PUGCUQK.js → computer-use-ET5476VX.js} +22 -22
- package/chunks/{config-utils-6PJUXHLI.js → config-utils-AHQ6YZ66.js} +3 -3
- package/chunks/{contextCommand-C57KTWFV.js → contextCommand-QIULFDBF.js} +25 -26
- package/chunks/{create-sub-session-5Q42XR6I.js → create-sub-session-BVL2ZHTM.js} +22 -22
- package/chunks/{create-sub-session-DIJOV6HV.js → create-sub-session-P26FE5GG.js} +2 -2
- package/chunks/{cron-create-X462ERYA.js → cron-create-JWFHBDRQ.js} +4 -4
- package/chunks/{cron-delete-SL5UJUM3.js → cron-delete-GDX4E26G.js} +4 -4
- package/chunks/{cron-list-3MD6SVXI.js → cron-list-USMAIWPT.js} +4 -4
- package/chunks/{daemon-ZW6LHOXT.js → daemon-EE5T3KOW.js} +169 -84
- package/chunks/{daemon-status-provider-YPV3UXHT.js → daemon-status-provider-L5UW7TGV.js} +29 -29
- package/chunks/{dist-3DQNQJ6H.js → dist-2BHAYBKP.js} +1 -1
- package/chunks/{dist-J2H4KTLB.js → dist-2MIU4UUH.js} +1 -1
- package/chunks/{dist-IEQSDXS7.js → dist-53PZYC5B.js} +2 -2
- package/chunks/{dist-NUXRQHC5.js → dist-AU7NQQRP.js} +1 -1
- package/chunks/{dist-XLE6ODMB.js → dist-FUTEXY6A.js} +1 -1
- package/chunks/{dist-IGZMVS5R.js → dist-WGTQO7F2.js} +1 -1
- package/chunks/{earlyInputCapture-5VDWSYAM.js → earlyInputCapture-ZLAL5GTE.js} +23 -23
- package/chunks/{edit-GORZTX2U.js → edit-4ZOPT6OC.js} +23 -23
- package/chunks/{enter-worktree-LJB2AW4L.js → enter-worktree-DFP5CZYS.js} +22 -22
- package/chunks/{enterPlanMode-LIIPP37T.js → enterPlanMode-7VEJ7A2A.js} +22 -22
- package/chunks/{environment-HQ2UHJ35.js → environment-KHS35XJY.js} +24 -24
- package/chunks/{errors-6JD5VMVQ.js → errors-574WBU5R.js} +24 -24
- package/chunks/{exit-worktree-IEP2WHOV.js → exit-worktree-5Q7V6D4C.js} +22 -22
- package/chunks/{exitPlanMode-U5Z6XBLO.js → exitPlanMode-SX2F6PDJ.js} +22 -22
- package/chunks/{fast-path-HFKNMP23.js → fast-path-G7BLOZVF.js} +2 -2
- package/chunks/{gemini-C2SCJH3N.js → gemini-M4JWSTGU.js} +70 -68
- package/chunks/{geminiContentGenerator-ADZTXEKV.js → geminiContentGenerator-MKXLUFUH.js} +4 -4
- package/chunks/{glob-GOAPGD6G.js → glob-FPKZY5W6.js} +22 -22
- package/chunks/{grep-HZLSTX7D.js → grep-RS22OMZG.js} +22 -22
- package/chunks/{handleAutoUpdate-UF74WGFE.js → handleAutoUpdate-RFNQ36JC.js} +27 -28
- package/chunks/{i18n-FMXIYUOC.js → i18n-MAEWSKYF.js} +23 -23
- package/chunks/{initializer-ERDBM3DU.js → initializer-T2BFZJBP.js} +28 -28
- package/chunks/{installationInfo-LROMXYLX.js → installationInfo-3UETF773.js} +25 -23
- package/chunks/{keychain-token-storage-K23CFKGN.js → keychain-token-storage-DWRJMNH3.js} +2 -2
- package/chunks/{list-6JPJROU5.js → list-FWZUKWD2.js} +30 -30
- package/chunks/{loadedSettingsAdapter-QCWYUBBF.js → loadedSettingsAdapter-3DUNHAPX.js} +27 -27
- package/chunks/{loop-wakeup-6H7OENTB.js → loop-wakeup-5GLTUBHA.js} +5 -5
- package/chunks/{ls-APTSOOS5.js → ls-FHBY3Y7I.js} +4 -4
- package/chunks/{lsp-HPACPJAN.js → lsp-B6VMEW6Y.js} +2 -2
- package/chunks/{mcp-3P3KWYWO.js → mcp-POXS7QWD.js} +27 -27
- package/chunks/{monitor-LMYKCF6R.js → monitor-2ZZC2NKH.js} +22 -22
- package/chunks/nonInteractiveCli-WSJVCB2W.js +126 -0
- package/chunks/{notebook-edit-IBEOVZ6A.js → notebook-edit-BMQLME3Q.js} +23 -23
- package/chunks/{openaiContentGenerator-42PZKET5.js → openaiContentGenerator-GOREG72R.js} +11 -11
- package/chunks/{pidfile-VTBDIGOH.js → pidfile-MVZDE5TC.js} +23 -23
- package/chunks/{processUtils-L7ZKOGDG.js → processUtils-RH5KNLDH.js} +2 -2
- package/chunks/{qwenContentGenerator-VR2CNFGI.js → qwenContentGenerator-R55BCLRI.js} +24 -24
- package/chunks/{qwenOAuth2-6LS2T3Q6.js → qwenOAuth2-QZBI2SOZ.js} +11 -11
- package/chunks/react-SG7JAQSZ.js +8 -0
- package/chunks/{read-file-VSKOE22I.js → read-file-CPS2CYYG.js} +8 -8
- package/chunks/{read-mcp-resource-C6NT52T6.js → read-mcp-resource-AKCL7I43.js} +2 -2
- package/chunks/{record-artifact-ENCU7QCL.js → record-artifact-PEUB7727.js} +2 -2
- package/chunks/resumeHistoryUtils-YD6DSYHU.js +78 -0
- package/chunks/{ripGrep-5V5FLW2A.js → ripGrep-UKGJ7RHZ.js} +22 -22
- package/chunks/{run-qwen-serve-LSOPP4R2.js → run-qwen-serve-GFKSKLF6.js} +1442 -148
- package/chunks/{runtime-LT7R4CS5.js → runtime-4KGNL3TP.js} +31 -31
- package/chunks/{scheduler-YOWQ7KZP.js → scheduler-GJ3CELWI.js} +22 -22
- package/chunks/{send-message-5GZ4FX2V.js → send-message-3RHE7HSM.js} +3 -3
- package/chunks/{serve-VWLBXKGK.js → serve-UU6Z4C7W.js} +27 -27
- package/chunks/{server-3RW3FYOH.js → server-RTJUMN24.js} +393 -256
- package/chunks/{session-ZONXFOBQ.js → session-EYD3CEB5.js} +79 -163
- package/chunks/{settings-JC3VC53L.js → settings-H5O22TGQ.js} +26 -26
- package/chunks/{shell-2NGEMAVM.js → shell-KVNHDHMT.js} +22 -22
- package/chunks/{skill-3U2T6H3E.js → skill-32525KCE.js} +10 -10
- package/chunks/{spawnChannel-QEAUPARQ.js → spawnChannel-G7DUQKHL.js} +24 -24
- package/chunks/{src-75ZPXO7B.js → src-DUFUUEHE.js} +52 -22
- package/chunks/{standalone-update-UUJWJWYY.js → standalone-update-UC6CWBLH.js} +24 -24
- package/chunks/{startInteractiveUI-V7XISPQ6.js → startInteractiveUI-A5YYAWLF.js} +5451 -2045
- package/chunks/{syntheticOutput-ULOVVLY4.js → syntheticOutput-FG5PQKIR.js} +3 -3
- package/chunks/{task-create-DUE2PMNI.js → task-create-HX32YXO7.js} +7 -7
- package/chunks/{task-list-WVPNX7BZ.js → task-list-QWSY4ZIU.js} +5 -5
- package/chunks/{task-stop-CPEQWOT6.js → task-stop-GWC6UWAL.js} +2 -2
- package/chunks/{task-update-HY2LNFFB.js → task-update-NCTAB73Q.js} +7 -7
- package/chunks/{team-create-R6AXDYPG.js → team-create-LS2Q32Y4.js} +22 -22
- package/chunks/{team-delete-JJV6IUOA.js → team-delete-KK37HTOG.js} +5 -5
- package/chunks/{team-plan-approval-O2ZPPT64.js → team-plan-approval-DWCZABX6.js} +22 -22
- package/chunks/{theme-manager-YIX2IC2D.js → theme-manager-E22CNBIL.js} +23 -23
- package/chunks/{todoWrite-JHHIDOIV.js → todoWrite-ERCAMLFS.js} +4 -4
- package/chunks/{tool-search-5IE2VO7X.js → tool-search-MHXUDFD2.js} +9 -9
- package/chunks/{total-session-admission-K6APQYEF.js → total-session-admission-KOPTGDJZ.js} +25 -25
- package/chunks/{trustedFolders-GPSSPVBF.js → trustedFolders-ANQXYAQT.js} +23 -23
- package/chunks/{update-relaunch-4BVAPX6Y.js → update-relaunch-HFGRB7PE.js} +9 -9
- package/chunks/{updateCheck-AHTHWLAM.js → updateCheck-EKIPND4B.js} +33 -26
- package/chunks/useAutoAcceptIndicator-EE22V2F5.js +80 -0
- package/chunks/{validateNonInterActiveAuth-UKAPCWDM.js → validateNonInterActiveAuth-RUICXVPH.js} +61 -63
- package/chunks/{version-EXGWKKQE.js → version-QLT755OV.js} +1 -1
- package/chunks/{web-fetch-ZDNE6FF2.js → web-fetch-DINW4Z65.js} +10 -10
- package/chunks/{workflow-G7U6OQWS.js → workflow-GPMXRWKK.js} +23 -23
- package/chunks/{workspace-providers-status-W6CEA6YM.js → workspace-providers-status-XCQKBVSX.js} +30 -30
- package/chunks/{workspace-registration-store-OGBMWCLC.js → workspace-registration-store-4I4KL7TN.js} +1 -1
- package/chunks/{workspace-registry-ZUWQM44P.js → workspace-registry-N4J57SFQ.js} +25 -25
- package/chunks/{workspace-service-UXX5P7GU.js → workspace-service-JJNJWVH3.js} +32 -32
- package/chunks/{workspace-skills-status-635B5R7N.js → workspace-skills-status-CEHLAQ2Y.js} +28 -28
- package/chunks/{write-file-DR3HN7IH.js → write-file-XRGEJRCC.js} +23 -23
- package/cli.js +11 -11
- package/package.json +3 -3
- package/web-shell/assets/{arc-_dVIKMdB.js → arc-DwJhljn9.js} +1 -1
- package/web-shell/assets/{architectureDiagram-3BPJPVTR-MuN3nKpL.js → architectureDiagram-3BPJPVTR-qdxSRav-.js} +1 -1
- package/web-shell/assets/{blockDiagram-GPEHLZMM-BtmvJjzx.js → blockDiagram-GPEHLZMM-2-dKM5aM.js} +1 -1
- package/web-shell/assets/{c4Diagram-AAUBKEIU-Dvi58_BU.js → c4Diagram-AAUBKEIU-Dt_Nu2HD.js} +1 -1
- package/web-shell/assets/channel-C6uyh95L.js +1 -0
- package/web-shell/assets/{chunk-2J33WTMH-YqxOVhS1.js → chunk-2J33WTMH-CBCeeNfD.js} +1 -1
- package/web-shell/assets/{chunk-4BX2VUAB-DoBgbC9z.js → chunk-4BX2VUAB-DPAzjqNs.js} +1 -1
- package/web-shell/assets/{chunk-55IACEB6-3NEQrBAr.js → chunk-55IACEB6-yrqyxvIK.js} +1 -1
- package/web-shell/assets/{chunk-727SXJPM-DrCZQxp0.js → chunk-727SXJPM-DguD_BBT.js} +1 -1
- package/web-shell/assets/{chunk-AQP2D5EJ-m_g3zjgv.js → chunk-AQP2D5EJ-KRUOG9v0.js} +1 -1
- package/web-shell/assets/{chunk-FMBD7UC4-D1_crABJ.js → chunk-FMBD7UC4-C0lilT2U.js} +1 -1
- package/web-shell/assets/{chunk-ND2GUHAM-BdhgVtBx.js → chunk-ND2GUHAM-DG9epIWK.js} +1 -1
- package/web-shell/assets/{chunk-QZHKN3VN-BlmThhm-.js → chunk-QZHKN3VN-PdJDkYHw.js} +1 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-Cv8Ulf-B.js +1 -0
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-Cv8Ulf-B.js +1 -0
- package/web-shell/assets/{cose-bilkent-S5V4N54A-Cbjm_00Z.js → cose-bilkent-S5V4N54A-BAOPPuJm.js} +1 -1
- package/web-shell/assets/{dagre-BM42HDAG-C39QNVgC.js → dagre-BM42HDAG-CDHJv82_.js} +1 -1
- package/web-shell/assets/{diagram-2AECGRRQ-DNXSAixC.js → diagram-2AECGRRQ-C_hkG5fN.js} +1 -1
- package/web-shell/assets/{diagram-5GNKFQAL-BCbGUPEA.js → diagram-5GNKFQAL-e9zo_eKt.js} +1 -1
- package/web-shell/assets/{diagram-KO2AKTUF-1eujKSDC.js → diagram-KO2AKTUF-BFN41SCb.js} +1 -1
- package/web-shell/assets/{diagram-LMA3HP47-DUMKXgql.js → diagram-LMA3HP47-DG72N0W0.js} +1 -1
- package/web-shell/assets/{diagram-OG6HWLK6-BFktU3_u.js → diagram-OG6HWLK6-Dkmp-tdv.js} +1 -1
- package/web-shell/assets/{erDiagram-TEJ5UH35-BvJC7DLk.js → erDiagram-TEJ5UH35-CyS0GnQV.js} +1 -1
- package/web-shell/assets/{flowDiagram-I6XJVG4X-Cgu3PlOt.js → flowDiagram-I6XJVG4X-Cg1SRmzV.js} +1 -1
- package/web-shell/assets/{ganttDiagram-6RSMTGT7-DLNXN5Xh.js → ganttDiagram-6RSMTGT7-CoNkSLs3.js} +1 -1
- package/web-shell/assets/{gitGraphDiagram-PVQCEYII-BQFRDv6R.js → gitGraphDiagram-PVQCEYII-DEA6GWPa.js} +1 -1
- package/web-shell/assets/index-B49xd8_A.css +5 -0
- package/web-shell/assets/{index-CdC3pjP3.js → index-CMaZgs6B.js} +1 -1
- package/web-shell/assets/index-D-cDAZgO.js +1192 -0
- package/web-shell/assets/{infoDiagram-5YYISTIA-DT2mOSvp.js → infoDiagram-5YYISTIA-BZshyoGT.js} +1 -1
- package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-9fy_K4bd.js → ishikawaDiagram-YF4QCWOH-CT2ssZqC.js} +1 -1
- package/web-shell/assets/{journeyDiagram-JHISSGLW-CoGSEuhE.js → journeyDiagram-JHISSGLW-BtMQ0rDG.js} +1 -1
- package/web-shell/assets/{kanban-definition-UN3LZRKU-BP9hHYIj.js → kanban-definition-UN3LZRKU-CoDbK5Db.js} +1 -1
- package/web-shell/assets/{linear-uIroDsmp.js → linear-CwhZ6u7u.js} +1 -1
- package/web-shell/assets/{mermaid.core-BUwoStsA.js → mermaid.core-C9nn0nrr.js} +5 -5
- package/web-shell/assets/{mindmap-definition-RKZ34NQL-DZB-FWim.js → mindmap-definition-RKZ34NQL-BXUbjTeL.js} +1 -1
- package/web-shell/assets/{pieDiagram-4H26LBE5-YPptloKl.js → pieDiagram-4H26LBE5-JddiYlWQ.js} +1 -1
- package/web-shell/assets/{quadrantDiagram-W4KKPZXB-dgk3DSzm.js → quadrantDiagram-W4KKPZXB-DK5HKzXO.js} +1 -1
- package/web-shell/assets/{requirementDiagram-4Y6WPE33-BH2En2i9.js → requirementDiagram-4Y6WPE33-Y-uipa_6.js} +1 -1
- package/web-shell/assets/{sankeyDiagram-5OEKKPKP-BB98feeI.js → sankeyDiagram-5OEKKPKP-BbWeqo8H.js} +1 -1
- package/web-shell/assets/{sequenceDiagram-3UESZ5HK-CunAIGh8.js → sequenceDiagram-3UESZ5HK-tX2gOoo5.js} +1 -1
- package/web-shell/assets/{stateDiagram-AJRCARHV-DTJs_-I2.js → stateDiagram-AJRCARHV-CACN457G.js} +1 -1
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-DaUeO2zt.js +1 -0
- package/web-shell/assets/{timeline-definition-PNZ67QCA-Cd4AN7O0.js → timeline-definition-PNZ67QCA-DnHWKSOq.js} +1 -1
- package/web-shell/assets/{vennDiagram-CIIHVFJN-xIG-rUU9.js → vennDiagram-CIIHVFJN-BO8Yl2FG.js} +1 -1
- package/web-shell/assets/{wardley-L42UT6IY-D1UyjIcG.js → wardley-L42UT6IY-1NMqqrBi.js} +1 -1
- package/web-shell/assets/{wardleyDiagram-YWT4CUSO-BVM0Mb99.js → wardleyDiagram-YWT4CUSO-C3eWgIvD.js} +1 -1
- package/web-shell/assets/{xychartDiagram-2RQKCTM6-BX31JDSz.js → xychartDiagram-2RQKCTM6-D0h8FgFX.js} +1 -1
- package/web-shell/index.html +2 -2
- package/chunks/chunk-EDFD7VOX.js +0 -368
- package/chunks/chunk-GFYFLDEG.js +0 -709
- package/chunks/chunk-LUJQUNKY.js +0 -3288
- package/chunks/nonInteractiveCli-YURFHZV5.js +0 -129
- package/web-shell/assets/channel-Bi5TehaT.js +0 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-BKhhRdd1.js +0 -1
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-BKhhRdd1.js +0 -1
- package/web-shell/assets/index-C_ouplMQ.js +0 -1187
- package/web-shell/assets/index-XGDFJE-X.css +0 -5
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-DrfFMYta.js +0 -1
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
computeCpuPercent
|
|
6
6
|
} from "./chunk-HGT6JR3U.js";
|
|
7
7
|
import {
|
|
8
|
+
ACCESS_LOG_CONTROLLER_LOCAL,
|
|
8
9
|
CAPABILITIES_SCHEMA_VERSION,
|
|
9
10
|
ClientMcpSenderRegistry,
|
|
10
11
|
PathMutexRegistry,
|
|
@@ -29,7 +30,7 @@ import {
|
|
|
29
30
|
require_express,
|
|
30
31
|
resolveWebShellDir,
|
|
31
32
|
setDeferredRuntimeRequestTiming
|
|
32
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-VLDBVLC4.js";
|
|
33
34
|
import {
|
|
34
35
|
isLoopbackBind
|
|
35
36
|
} from "./chunk-RXFQM6FQ.js";
|
|
@@ -46,7 +47,7 @@ import {
|
|
|
46
47
|
import "./chunk-WBL3FJEU.js";
|
|
47
48
|
import {
|
|
48
49
|
resolveChannelCwd
|
|
49
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-4ODB7WIB.js";
|
|
50
51
|
import {
|
|
51
52
|
loadServeFastPathSettings,
|
|
52
53
|
preResolveServeFastPathHomeEnvOverrides
|
|
@@ -55,16 +56,16 @@ import {
|
|
|
55
56
|
MAX_REGISTERED_WORKSPACES,
|
|
56
57
|
resolveWorkspaceInputs,
|
|
57
58
|
workspaceRegistrationId
|
|
58
|
-
} from "./chunk-
|
|
59
|
+
} from "./chunk-6VGRTGOG.js";
|
|
59
60
|
import {
|
|
60
61
|
canonicalizeWorkspace
|
|
61
62
|
} from "./chunk-W7FJ3N32.js";
|
|
62
|
-
import "./chunk-
|
|
63
|
-
import "./chunk-
|
|
63
|
+
import "./chunk-OLMETXLX.js";
|
|
64
|
+
import "./chunk-NBMIC7DR.js";
|
|
64
65
|
import {
|
|
65
66
|
ChannelWebhookEnqueueError,
|
|
66
67
|
QWEN_SERVER_TOKEN_ENV
|
|
67
|
-
} from "./chunk-
|
|
68
|
+
} from "./chunk-Y2ENGUD6.js";
|
|
68
69
|
import {
|
|
69
70
|
channelSelectionNames
|
|
70
71
|
} from "./chunk-TJTKSVIV.js";
|
|
@@ -73,7 +74,7 @@ import "./chunk-5HBA2Z7V.js";
|
|
|
73
74
|
import "./chunk-T2NCM2ET.js";
|
|
74
75
|
import {
|
|
75
76
|
sanitizeLogText
|
|
76
|
-
} from "./chunk-
|
|
77
|
+
} from "./chunk-NIJEXGV6.js";
|
|
77
78
|
import "./chunk-UDXSXLER.js";
|
|
78
79
|
import "./chunk-GOXKNSDZ.js";
|
|
79
80
|
import {
|
|
@@ -83,7 +84,7 @@ import {
|
|
|
83
84
|
import "./chunk-QRUIS3DN.js";
|
|
84
85
|
import {
|
|
85
86
|
getCliVersion
|
|
86
|
-
} from "./chunk-
|
|
87
|
+
} from "./chunk-SQMTULHJ.js";
|
|
87
88
|
import "./chunk-VJNBRRZG.js";
|
|
88
89
|
import "./chunk-ALGGS7UH.js";
|
|
89
90
|
import {
|
|
@@ -96,7 +97,9 @@ import {
|
|
|
96
97
|
import "./chunk-5M6IDOMF.js";
|
|
97
98
|
import "./chunk-T4TZQJ7W.js";
|
|
98
99
|
import "./chunk-H6XPXXMH.js";
|
|
99
|
-
import
|
|
100
|
+
import {
|
|
101
|
+
require_proper_lockfile
|
|
102
|
+
} from "./chunk-E2UVIFI2.js";
|
|
100
103
|
import "./chunk-CR3C7WXL.js";
|
|
101
104
|
import "./chunk-XWRJCPHC.js";
|
|
102
105
|
import {
|
|
@@ -122,7 +125,7 @@ import * as fs from "node:fs";
|
|
|
122
125
|
import * as https from "node:https";
|
|
123
126
|
import * as path from "node:path";
|
|
124
127
|
import * as os from "node:os";
|
|
125
|
-
import { monitorEventLoopDelay, performance } from "node:perf_hooks";
|
|
128
|
+
import { monitorEventLoopDelay, performance as performance2 } from "node:perf_hooks";
|
|
126
129
|
|
|
127
130
|
// packages/cli/src/serve/permission-audit.ts
|
|
128
131
|
init_esbuild_shims();
|
|
@@ -243,9 +246,11 @@ __name(createPermissionAuditPublisher, "createPermissionAuditPublisher");
|
|
|
243
246
|
|
|
244
247
|
// packages/cli/src/serve/daemon-logger.ts
|
|
245
248
|
init_esbuild_shims();
|
|
249
|
+
var import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
|
|
246
250
|
import * as nodeFs from "node:fs";
|
|
247
251
|
import * as nodePath from "node:path";
|
|
248
252
|
import * as crypto from "node:crypto";
|
|
253
|
+
import { performance } from "node:perf_hooks";
|
|
249
254
|
var FIXED_CTX_ORDER = [
|
|
250
255
|
"route",
|
|
251
256
|
"sessionId",
|
|
@@ -254,6 +259,31 @@ var FIXED_CTX_ORDER = [
|
|
|
254
259
|
"channelId"
|
|
255
260
|
];
|
|
256
261
|
var FIXED_CTX_SET = new Set(FIXED_CTX_ORDER);
|
|
262
|
+
var ISSUE_ORDER = [
|
|
263
|
+
"init_failed",
|
|
264
|
+
"rotation_failed",
|
|
265
|
+
"retention_failed",
|
|
266
|
+
"queue_overflow",
|
|
267
|
+
"write_failed",
|
|
268
|
+
"lease_compromised"
|
|
269
|
+
];
|
|
270
|
+
var DEFAULT_POLICY = {
|
|
271
|
+
maxBytes: 10 * 1024 * 1024,
|
|
272
|
+
maxArchives: 4,
|
|
273
|
+
maxRecordBytes: 256 * 1024,
|
|
274
|
+
maxPendingBytes: 4 * 1024 * 1024,
|
|
275
|
+
stableAcquireBudgetMs: 1e3,
|
|
276
|
+
maintenanceAcquireBudgetMs: 250,
|
|
277
|
+
lockStaleMs: 6e4,
|
|
278
|
+
lockUpdateMs: 1e4,
|
|
279
|
+
rotationRetryIntervalMs: 6e4,
|
|
280
|
+
closeDrainBudgetMs: 2e3
|
|
281
|
+
};
|
|
282
|
+
var ARCHIVE_RE = /^daemon-(\d{12})-(\d{8}T\d{9}Z)-([0-9a-f]{8})\.log$/;
|
|
283
|
+
var FALLBACK_DIR_RE = /^run-[0-9a-f]{32}$/;
|
|
284
|
+
var ARCHIVE_NAME_ATTEMPTS = 3;
|
|
285
|
+
var FILE_MODE = 384;
|
|
286
|
+
var DIRECTORY_MODE = 448;
|
|
257
287
|
function renderCtxValue(value) {
|
|
258
288
|
const s = String(value);
|
|
259
289
|
return /[\s=]/.test(s) ? JSON.stringify(s) : s;
|
|
@@ -269,7 +299,7 @@ function renderCtx(ctx) {
|
|
|
269
299
|
}
|
|
270
300
|
}
|
|
271
301
|
const extraKeys = Object.keys(ctx).filter(
|
|
272
|
-
(
|
|
302
|
+
(key) => !FIXED_CTX_SET.has(key) && ctx[key] !== void 0 && ctx[key] !== null
|
|
273
303
|
).sort();
|
|
274
304
|
for (const key of extraKeys) {
|
|
275
305
|
parts.push(`${key}=${renderCtxValue(ctx[key])}`);
|
|
@@ -280,7 +310,7 @@ __name(renderCtx, "renderCtx");
|
|
|
280
310
|
function renderErr(err) {
|
|
281
311
|
if (!err) return "";
|
|
282
312
|
const body = err.stack ?? `${err.name ?? "Error"}: ${err.message}`;
|
|
283
|
-
return body.split("\n").map((
|
|
313
|
+
return body.split("\n").map((line) => ` ${line}`).join("\n") + "\n";
|
|
284
314
|
}
|
|
285
315
|
__name(renderErr, "renderErr");
|
|
286
316
|
function buildDaemonLogLine(args) {
|
|
@@ -290,19 +320,17 @@ function buildDaemonLogLine(args) {
|
|
|
290
320
|
${renderErr(args.err)}`;
|
|
291
321
|
}
|
|
292
322
|
__name(buildDaemonLogLine, "buildDaemonLogLine");
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
flush: /* @__PURE__ */ __name(() => Promise.resolve(), "flush")
|
|
305
|
-
};
|
|
323
|
+
function buildDaemonFileLogLine(args, runId, pid) {
|
|
324
|
+
const callerCtx = args.ctx ? Object.fromEntries(
|
|
325
|
+
Object.entries(args.ctx).filter(
|
|
326
|
+
([key]) => key !== "runId" && key !== "pid"
|
|
327
|
+
)
|
|
328
|
+
) : void 0;
|
|
329
|
+
const ctxStr = renderCtx(callerCtx);
|
|
330
|
+
return `${args.now.toISOString()} [${args.level}] [DAEMON] runId=${runId} pid=${pid} ${ctxStr}${args.message}
|
|
331
|
+
${renderErr(args.err)}`;
|
|
332
|
+
}
|
|
333
|
+
__name(buildDaemonFileLogLine, "buildDaemonFileLogLine");
|
|
306
334
|
function getRuntimeBaseDir(runtimeOutputDir, cwd) {
|
|
307
335
|
const envDir = process.env["QWEN_RUNTIME_DIR"];
|
|
308
336
|
if (envDir) return resolveConfigPathLite(envDir);
|
|
@@ -314,19 +342,6 @@ function resolveDaemonLogBaseDir(runtimeOutputDir, cwd) {
|
|
|
314
342
|
return nodePath.join(getRuntimeBaseDir(runtimeOutputDir, cwd), "debug");
|
|
315
343
|
}
|
|
316
344
|
__name(resolveDaemonLogBaseDir, "resolveDaemonLogBaseDir");
|
|
317
|
-
async function updateSymlinkBestEffort(linkPath, targetPath) {
|
|
318
|
-
const linkDir = nodePath.dirname(linkPath);
|
|
319
|
-
const relativeTarget = nodePath.relative(linkDir, targetPath);
|
|
320
|
-
try {
|
|
321
|
-
await nodeFs.promises.unlink(linkPath);
|
|
322
|
-
} catch {
|
|
323
|
-
}
|
|
324
|
-
try {
|
|
325
|
-
await nodeFs.promises.symlink(relativeTarget, linkPath);
|
|
326
|
-
} catch {
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
__name(updateSymlinkBestEffort, "updateSymlinkBestEffort");
|
|
330
345
|
function isOptedOut() {
|
|
331
346
|
const raw = process.env["QWEN_DAEMON_LOG_FILE"];
|
|
332
347
|
if (!raw) return false;
|
|
@@ -341,73 +356,1252 @@ function computeDaemonId(pid) {
|
|
|
341
356
|
return `daemon:${pid}`;
|
|
342
357
|
}
|
|
343
358
|
__name(computeDaemonId, "computeDaemonId");
|
|
344
|
-
function
|
|
345
|
-
return
|
|
359
|
+
function isErrno(error, code) {
|
|
360
|
+
return error instanceof Error && "code" in error && error.code === code;
|
|
346
361
|
}
|
|
347
|
-
__name(
|
|
348
|
-
function
|
|
349
|
-
|
|
350
|
-
const
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
362
|
+
__name(isErrno, "isErrno");
|
|
363
|
+
function resolvePolicy(overrides) {
|
|
364
|
+
const policy = { ...DEFAULT_POLICY, ...overrides };
|
|
365
|
+
for (const [name, value] of Object.entries(policy)) {
|
|
366
|
+
if (!Number.isFinite(value) || value < 0) {
|
|
367
|
+
throw new TypeError(`Invalid daemon logger policy ${name}=${value}`);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
if (policy.maxBytes === 0 || policy.maxArchives === 0 || policy.maxRecordBytes === 0 || policy.maxPendingBytes === 0) {
|
|
371
|
+
throw new TypeError(
|
|
372
|
+
"Daemon logger size/count policy values must be positive"
|
|
373
|
+
);
|
|
374
|
+
}
|
|
375
|
+
if (policy.maxRecordBytes > policy.maxBytes) {
|
|
376
|
+
throw new TypeError(
|
|
377
|
+
"Daemon logger maxRecordBytes must not exceed maxBytes"
|
|
378
|
+
);
|
|
379
|
+
}
|
|
380
|
+
if (policy.maxRecordBytes > policy.maxPendingBytes) {
|
|
381
|
+
throw new TypeError(
|
|
382
|
+
"Daemon logger maxRecordBytes must not exceed maxPendingBytes"
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
return policy;
|
|
386
|
+
}
|
|
387
|
+
__name(resolvePolicy, "resolvePolicy");
|
|
388
|
+
function statusSnapshot(runId, mode, issues, droppedRecords, droppedBytes) {
|
|
389
|
+
return {
|
|
390
|
+
runId,
|
|
391
|
+
mode,
|
|
392
|
+
health: issues.size === 0 ? "ok" : "degraded",
|
|
393
|
+
issues: ISSUE_ORDER.filter((issue) => issues.has(issue)),
|
|
394
|
+
droppedRecords,
|
|
395
|
+
droppedBytes
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
__name(statusSnapshot, "statusSnapshot");
|
|
399
|
+
function createStderrOnlyLogger(input) {
|
|
400
|
+
const tee = /* @__PURE__ */ __name((level, message, ctx, err) => {
|
|
401
|
+
input.stderr(
|
|
402
|
+
buildDaemonLogLine({
|
|
403
|
+
level,
|
|
404
|
+
message,
|
|
405
|
+
now: input.now(),
|
|
406
|
+
ctx,
|
|
407
|
+
err
|
|
408
|
+
}).trimEnd()
|
|
409
|
+
);
|
|
410
|
+
}, "tee");
|
|
411
|
+
return {
|
|
412
|
+
info: /* @__PURE__ */ __name((message, ctx) => tee("INFO", message, ctx), "info"),
|
|
413
|
+
warn: /* @__PURE__ */ __name((message, ctx) => tee("WARN", message, ctx), "warn"),
|
|
414
|
+
error: /* @__PURE__ */ __name((message, err, ctx) => tee("ERROR", message, ctx, err ?? void 0), "error"),
|
|
415
|
+
raw: /* @__PURE__ */ __name(() => {
|
|
416
|
+
}, "raw"),
|
|
417
|
+
getLogPath: /* @__PURE__ */ __name(() => "", "getLogPath"),
|
|
418
|
+
getDaemonId: /* @__PURE__ */ __name(() => input.daemonId, "getDaemonId"),
|
|
419
|
+
getStatus: /* @__PURE__ */ __name(() => statusSnapshot(input.runId, "stderr-only", input.issues, 0, 0), "getStatus"),
|
|
420
|
+
flush: /* @__PURE__ */ __name(() => Promise.resolve(), "flush"),
|
|
421
|
+
close: /* @__PURE__ */ __name(() => Promise.resolve(), "close")
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
__name(createStderrOnlyLogger, "createStderrOnlyLogger");
|
|
425
|
+
function capUtf8Record(record, maxBytes) {
|
|
426
|
+
const bytes = Buffer.from(record, "utf8");
|
|
427
|
+
if (bytes.length <= maxBytes) return record;
|
|
428
|
+
const marker = `
|
|
429
|
+
[truncated originalBytes=${bytes.length}]
|
|
430
|
+
`;
|
|
431
|
+
const markerBytes = Buffer.from(marker, "utf8");
|
|
432
|
+
if (markerBytes.length >= maxBytes) {
|
|
433
|
+
return Buffer.from("[truncated]\n", "utf8").subarray(0, maxBytes).toString("utf8");
|
|
434
|
+
}
|
|
435
|
+
let prefixBytes = maxBytes - markerBytes.length;
|
|
436
|
+
while (prefixBytes > 0 && (bytes[prefixBytes] & 192) === 128) {
|
|
437
|
+
prefixBytes -= 1;
|
|
438
|
+
}
|
|
439
|
+
return bytes.subarray(0, prefixBytes).toString("utf8") + marker;
|
|
440
|
+
}
|
|
441
|
+
__name(capUtf8Record, "capUtf8Record");
|
|
442
|
+
async function ensureRealDirectory(fs2, dirPath, mutationAllowed = () => true) {
|
|
443
|
+
try {
|
|
444
|
+
const existing = await fs2.lstat(dirPath);
|
|
445
|
+
if (!existing.isDirectory() || existing.isSymbolicLink()) {
|
|
446
|
+
throw new Error(`${dirPath} is not a real directory`);
|
|
447
|
+
}
|
|
448
|
+
return;
|
|
449
|
+
} catch (error) {
|
|
450
|
+
if (!isErrno(error, "ENOENT")) throw error;
|
|
451
|
+
}
|
|
452
|
+
if (!mutationAllowed()) {
|
|
453
|
+
throw new Error(`File mutation is no longer allowed for ${dirPath}`);
|
|
454
|
+
}
|
|
455
|
+
await fs2.mkdir(dirPath, { recursive: true, mode: DIRECTORY_MODE });
|
|
456
|
+
const created = await fs2.lstat(dirPath);
|
|
457
|
+
if (!created.isDirectory() || created.isSymbolicLink()) {
|
|
458
|
+
throw new Error(`${dirPath} is not a real directory`);
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
__name(ensureRealDirectory, "ensureRealDirectory");
|
|
462
|
+
async function activeFileSize(fs2, activePath) {
|
|
358
463
|
try {
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
464
|
+
const stat = await fs2.lstat(activePath);
|
|
465
|
+
if (!stat.isFile() || stat.isSymbolicLink()) {
|
|
466
|
+
throw new Error(`${activePath} is not a regular file`);
|
|
467
|
+
}
|
|
468
|
+
return stat.size;
|
|
469
|
+
} catch (error) {
|
|
470
|
+
if (isErrno(error, "ENOENT")) return 0;
|
|
471
|
+
throw error;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
__name(activeFileSize, "activeFileSize");
|
|
475
|
+
async function lastByteIsNewline(fs2, activePath, size) {
|
|
476
|
+
if (size === 0) return true;
|
|
477
|
+
const handle = await fs2.open(activePath, "r");
|
|
478
|
+
try {
|
|
479
|
+
const buffer = Buffer.allocUnsafe(1);
|
|
480
|
+
const result = await handle.read(buffer, 0, 1, size - 1);
|
|
481
|
+
return result.bytesRead === 1 && buffer[0] === 10;
|
|
482
|
+
} finally {
|
|
483
|
+
await handle.close();
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
__name(lastByteIsNewline, "lastByteIsNewline");
|
|
487
|
+
function archiveTimestamp(now) {
|
|
488
|
+
return now.toISOString().replace(/[-:.]/g, "");
|
|
489
|
+
}
|
|
490
|
+
__name(archiveTimestamp, "archiveTimestamp");
|
|
491
|
+
async function scanArchives(fs2, archiveDir) {
|
|
492
|
+
const entries = await fs2.readdir(archiveDir, { withFileTypes: true });
|
|
493
|
+
const archives = [];
|
|
494
|
+
for (const entry of entries) {
|
|
495
|
+
if (!entry.isFile()) continue;
|
|
496
|
+
const match = ARCHIVE_RE.exec(entry.name);
|
|
497
|
+
if (!match) continue;
|
|
498
|
+
archives.push({ name: entry.name, generation: Number(match[1]) });
|
|
499
|
+
}
|
|
500
|
+
archives.sort(
|
|
501
|
+
(a, b) => a.generation - b.generation || a.name.localeCompare(b.name)
|
|
502
|
+
);
|
|
503
|
+
return archives;
|
|
504
|
+
}
|
|
505
|
+
__name(scanArchives, "scanArchives");
|
|
506
|
+
function lockRetries(maxRetryTime) {
|
|
507
|
+
if (maxRetryTime <= 0) return 0;
|
|
508
|
+
return {
|
|
509
|
+
retries: 4,
|
|
510
|
+
factor: 2,
|
|
511
|
+
minTimeout: 50,
|
|
512
|
+
maxTimeout: 400,
|
|
513
|
+
randomize: true,
|
|
514
|
+
maxRetryTime
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
__name(lockRetries, "lockRetries");
|
|
518
|
+
async function acquireLease(input) {
|
|
519
|
+
const lease = {
|
|
520
|
+
compromised: false,
|
|
521
|
+
released: false,
|
|
522
|
+
release: /* @__PURE__ */ __name(async () => {
|
|
523
|
+
}, "release")
|
|
524
|
+
};
|
|
525
|
+
const release = await input.acquireLock(input.targetPath, {
|
|
526
|
+
lockfilePath: input.lockPath,
|
|
527
|
+
realpath: true,
|
|
528
|
+
stale: input.policy.lockStaleMs,
|
|
529
|
+
update: input.policy.lockUpdateMs,
|
|
530
|
+
retries: lockRetries(input.retryBudgetMs),
|
|
531
|
+
onCompromised: /* @__PURE__ */ __name((error) => {
|
|
532
|
+
if (lease.released) return;
|
|
533
|
+
lease.compromised = true;
|
|
534
|
+
try {
|
|
535
|
+
input.onCompromised?.(error);
|
|
536
|
+
} catch {
|
|
537
|
+
}
|
|
538
|
+
}, "onCompromised")
|
|
539
|
+
});
|
|
540
|
+
try {
|
|
541
|
+
if (lease.compromised) {
|
|
542
|
+
throw new Error(
|
|
543
|
+
`Lease was compromised while acquiring ${input.lockPath}`
|
|
544
|
+
);
|
|
545
|
+
}
|
|
546
|
+
await input.fs.chmod(input.lockPath, DIRECTORY_MODE);
|
|
547
|
+
} catch (error) {
|
|
548
|
+
lease.released = true;
|
|
549
|
+
await release().catch(() => {
|
|
365
550
|
});
|
|
366
|
-
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
|
|
551
|
+
throw error;
|
|
552
|
+
}
|
|
553
|
+
lease.release = async () => {
|
|
554
|
+
if (lease.released) return;
|
|
555
|
+
lease.released = true;
|
|
556
|
+
await release();
|
|
557
|
+
};
|
|
558
|
+
return lease;
|
|
559
|
+
}
|
|
560
|
+
__name(acquireLease, "acquireLease");
|
|
561
|
+
async function updateLatestBestEffort(fs2, daemonDir, targetPath, mutationAllowed) {
|
|
562
|
+
const linkPath = nodePath.join(daemonDir, "latest");
|
|
563
|
+
if (!mutationAllowed()) return;
|
|
564
|
+
try {
|
|
565
|
+
await fs2.unlink(linkPath);
|
|
566
|
+
} catch {
|
|
567
|
+
}
|
|
568
|
+
if (!mutationAllowed()) return;
|
|
569
|
+
try {
|
|
570
|
+
await fs2.symlink(nodePath.relative(daemonDir, targetPath), linkPath);
|
|
571
|
+
} catch {
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
__name(updateLatestBestEffort, "updateLatestBestEffort");
|
|
575
|
+
async function readRecentFallback(fs2, runsDir) {
|
|
576
|
+
try {
|
|
577
|
+
const raw = await fs2.readFile(
|
|
578
|
+
nodePath.join(runsDir, "recent-fallback"),
|
|
579
|
+
"utf8"
|
|
370
580
|
);
|
|
371
|
-
|
|
581
|
+
const name = raw.trim();
|
|
582
|
+
return FALLBACK_DIR_RE.test(name) ? name : void 0;
|
|
583
|
+
} catch {
|
|
584
|
+
return void 0;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
__name(readRecentFallback, "readRecentFallback");
|
|
588
|
+
async function writeRecentFallback(fs2, runsDir, name, mutationAllowed = () => true) {
|
|
589
|
+
const locatorPath = nodePath.join(runsDir, "recent-fallback");
|
|
590
|
+
if (!name) {
|
|
591
|
+
if (!mutationAllowed()) {
|
|
592
|
+
throw new Error("Fallback locator mutation is no longer allowed");
|
|
593
|
+
}
|
|
594
|
+
try {
|
|
595
|
+
await fs2.unlink(locatorPath);
|
|
596
|
+
} catch (error) {
|
|
597
|
+
if (!isErrno(error, "ENOENT")) throw error;
|
|
598
|
+
}
|
|
599
|
+
return;
|
|
600
|
+
}
|
|
601
|
+
if (!FALLBACK_DIR_RE.test(name)) {
|
|
602
|
+
throw new Error(`Invalid fallback locator target: ${name}`);
|
|
372
603
|
}
|
|
604
|
+
const tempPath = nodePath.join(runsDir, ".recent-fallback.tmp");
|
|
373
605
|
try {
|
|
374
|
-
const
|
|
375
|
-
|
|
606
|
+
const tempStat = await fs2.lstat(tempPath);
|
|
607
|
+
if (!tempStat.isFile() || tempStat.isSymbolicLink()) {
|
|
608
|
+
throw new Error(`${tempPath} is not a regular file`);
|
|
609
|
+
}
|
|
610
|
+
if (!mutationAllowed()) {
|
|
611
|
+
throw new Error("Fallback locator mutation is no longer allowed");
|
|
612
|
+
}
|
|
613
|
+
await fs2.unlink(tempPath);
|
|
614
|
+
} catch (error) {
|
|
615
|
+
if (!isErrno(error, "ENOENT")) throw error;
|
|
616
|
+
}
|
|
617
|
+
if (!mutationAllowed()) {
|
|
618
|
+
throw new Error("Fallback locator mutation is no longer allowed");
|
|
619
|
+
}
|
|
620
|
+
await fs2.writeFile(tempPath, `${name}
|
|
621
|
+
`, {
|
|
622
|
+
encoding: "utf8",
|
|
623
|
+
mode: FILE_MODE,
|
|
624
|
+
flag: "wx"
|
|
625
|
+
});
|
|
626
|
+
if (!mutationAllowed()) {
|
|
627
|
+
throw new Error("Fallback locator mutation is no longer allowed");
|
|
628
|
+
}
|
|
629
|
+
await fs2.rename(tempPath, locatorPath);
|
|
630
|
+
}
|
|
631
|
+
__name(writeRecentFallback, "writeRecentFallback");
|
|
632
|
+
async function listFallbackDirectories(fs2, runsDir) {
|
|
633
|
+
const entries = await fs2.readdir(runsDir, { withFileTypes: true });
|
|
634
|
+
return entries.filter((entry) => entry.isDirectory() && FALLBACK_DIR_RE.test(entry.name)).map((entry) => entry.name).sort();
|
|
635
|
+
}
|
|
636
|
+
__name(listFallbackDirectories, "listFallbackDirectories");
|
|
637
|
+
async function fallbackActivityMtime(fs2, familyDir) {
|
|
638
|
+
try {
|
|
639
|
+
return (await fs2.lstat(nodePath.join(familyDir, "daemon.log"))).mtimeMs;
|
|
640
|
+
} catch (error) {
|
|
641
|
+
if (!isErrno(error, "ENOENT")) throw error;
|
|
642
|
+
return (await fs2.lstat(familyDir)).mtimeMs;
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
__name(fallbackActivityMtime, "fallbackActivityMtime");
|
|
646
|
+
async function cleanupFallbackFamilies(input) {
|
|
647
|
+
const mutationAllowed = input.mutationAllowed ?? (() => true);
|
|
648
|
+
const locator = await readRecentFallback(input.fs, input.runsDir);
|
|
649
|
+
const names = await listFallbackDirectories(input.fs, input.runsDir);
|
|
650
|
+
const live = /* @__PURE__ */ new Set();
|
|
651
|
+
const inactive = [];
|
|
652
|
+
try {
|
|
653
|
+
for (const name of names) {
|
|
654
|
+
if (!mutationAllowed()) {
|
|
655
|
+
throw new Error("Fallback cleanup lease was compromised");
|
|
656
|
+
}
|
|
657
|
+
const familyDir = nodePath.join(input.runsDir, name);
|
|
658
|
+
let lease;
|
|
659
|
+
try {
|
|
660
|
+
lease = await acquireLease({
|
|
661
|
+
fs: input.fs,
|
|
662
|
+
acquireLock: input.acquireLock,
|
|
663
|
+
targetPath: familyDir,
|
|
664
|
+
lockPath: nodePath.join(familyDir, ".owner.lock"),
|
|
665
|
+
policy: input.policy,
|
|
666
|
+
retryBudgetMs: 0
|
|
667
|
+
});
|
|
668
|
+
if (!mutationAllowed()) {
|
|
669
|
+
throw new Error("Fallback cleanup lease was compromised");
|
|
670
|
+
}
|
|
671
|
+
if (lease.compromised) {
|
|
672
|
+
await lease.release().catch(() => {
|
|
673
|
+
});
|
|
674
|
+
throw new Error(`Fallback owner lease was compromised: ${familyDir}`);
|
|
675
|
+
}
|
|
676
|
+
inactive.push({
|
|
677
|
+
name,
|
|
678
|
+
mtimeMs: await fallbackActivityMtime(input.fs, familyDir),
|
|
679
|
+
lease
|
|
680
|
+
});
|
|
681
|
+
} catch (error) {
|
|
682
|
+
await lease?.release().catch(() => {
|
|
683
|
+
});
|
|
684
|
+
if (isErrno(error, "ELOCKED")) {
|
|
685
|
+
live.add(name);
|
|
686
|
+
continue;
|
|
687
|
+
}
|
|
688
|
+
throw error;
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
const inactiveNames = new Set(inactive.map((entry) => entry.name));
|
|
692
|
+
const retainedInactive = (input.preferredInactive && inactiveNames.has(input.preferredInactive) ? input.preferredInactive : void 0) ?? (locator && inactiveNames.has(locator) ? locator : void 0) ?? inactive.slice().sort(
|
|
693
|
+
(a, b) => b.mtimeMs - a.mtimeMs || b.name.localeCompare(a.name)
|
|
694
|
+
)[0]?.name;
|
|
695
|
+
for (const entry of inactive) {
|
|
696
|
+
await entry.lease.release();
|
|
697
|
+
if (entry.name === retainedInactive) continue;
|
|
698
|
+
if (!mutationAllowed()) {
|
|
699
|
+
throw new Error("Fallback cleanup lease was compromised");
|
|
700
|
+
}
|
|
701
|
+
await input.fs.rm(nodePath.join(input.runsDir, entry.name), {
|
|
702
|
+
recursive: true,
|
|
703
|
+
force: true
|
|
704
|
+
});
|
|
705
|
+
}
|
|
706
|
+
const remaining = [...live, ...retainedInactive ? [retainedInactive] : []].filter((name, index, all) => all.indexOf(name) === index).sort();
|
|
707
|
+
const nextLocator = retainedInactive ?? (locator && remaining.includes(locator) ? locator : remaining.at(-1));
|
|
708
|
+
if (locator !== nextLocator) {
|
|
709
|
+
await writeRecentFallback(
|
|
710
|
+
input.fs,
|
|
711
|
+
input.runsDir,
|
|
712
|
+
nextLocator,
|
|
713
|
+
mutationAllowed
|
|
714
|
+
).catch(() => {
|
|
715
|
+
});
|
|
716
|
+
}
|
|
717
|
+
} finally {
|
|
718
|
+
await Promise.all(
|
|
719
|
+
inactive.filter((entry) => !entry.lease.released).map((entry) => entry.lease.release().catch(() => {
|
|
720
|
+
}))
|
|
721
|
+
);
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
__name(cleanupFallbackFamilies, "cleanupFallbackFamilies");
|
|
725
|
+
async function acquireMaintenanceLease(input) {
|
|
726
|
+
await ensureRealDirectory(input.fs, input.runsDir);
|
|
727
|
+
return acquireLease({
|
|
728
|
+
fs: input.fs,
|
|
729
|
+
acquireLock: input.acquireLock,
|
|
730
|
+
targetPath: input.runsDir,
|
|
731
|
+
lockPath: nodePath.join(input.runsDir, ".maintenance.lock"),
|
|
732
|
+
policy: input.policy,
|
|
733
|
+
retryBudgetMs: input.retryBudgetMs
|
|
734
|
+
});
|
|
735
|
+
}
|
|
736
|
+
__name(acquireMaintenanceLease, "acquireMaintenanceLease");
|
|
737
|
+
async function allocateFallbackFamily(input) {
|
|
738
|
+
const runsDir = nodePath.join(input.daemonDir, "runs");
|
|
739
|
+
const maintenance = await acquireMaintenanceLease({
|
|
740
|
+
...input,
|
|
741
|
+
runsDir,
|
|
742
|
+
retryBudgetMs: input.policy.maintenanceAcquireBudgetMs
|
|
743
|
+
});
|
|
744
|
+
let familyDir;
|
|
745
|
+
let familyCreated = false;
|
|
746
|
+
let lease;
|
|
747
|
+
const maintenanceAllowsMutation = /* @__PURE__ */ __name(() => !maintenance.compromised && !maintenance.released, "maintenanceAllowsMutation");
|
|
748
|
+
try {
|
|
749
|
+
if (!maintenanceAllowsMutation()) {
|
|
750
|
+
throw new Error("Fallback maintenance lease was compromised");
|
|
751
|
+
}
|
|
752
|
+
await cleanupFallbackFamilies({
|
|
753
|
+
...input,
|
|
754
|
+
runsDir,
|
|
755
|
+
mutationAllowed: maintenanceAllowsMutation
|
|
756
|
+
});
|
|
757
|
+
if (!maintenanceAllowsMutation()) {
|
|
758
|
+
throw new Error("Fallback maintenance lease was compromised");
|
|
759
|
+
}
|
|
760
|
+
const name = `run-${input.runId}`;
|
|
761
|
+
familyDir = nodePath.join(runsDir, name);
|
|
762
|
+
await input.fs.mkdir(familyDir, { mode: DIRECTORY_MODE });
|
|
763
|
+
familyCreated = true;
|
|
764
|
+
if (!maintenanceAllowsMutation()) {
|
|
765
|
+
throw new Error("Fallback maintenance lease was compromised");
|
|
766
|
+
}
|
|
767
|
+
lease = await acquireLease({
|
|
768
|
+
fs: input.fs,
|
|
769
|
+
acquireLock: input.acquireLock,
|
|
770
|
+
targetPath: familyDir,
|
|
771
|
+
lockPath: nodePath.join(familyDir, ".owner.lock"),
|
|
772
|
+
policy: input.policy,
|
|
773
|
+
retryBudgetMs: 0,
|
|
774
|
+
onCompromised: input.onCompromised
|
|
775
|
+
});
|
|
776
|
+
if (!maintenanceAllowsMutation()) {
|
|
777
|
+
throw new Error("Fallback maintenance lease was compromised");
|
|
778
|
+
}
|
|
779
|
+
} catch (error) {
|
|
780
|
+
await lease?.release().catch(() => {
|
|
781
|
+
});
|
|
782
|
+
if (familyCreated && familyDir && maintenanceAllowsMutation()) {
|
|
783
|
+
await input.fs.rm(familyDir, { recursive: true, force: true }).catch(() => {
|
|
784
|
+
});
|
|
785
|
+
}
|
|
786
|
+
await maintenance.release().catch(() => {
|
|
787
|
+
});
|
|
788
|
+
throw error;
|
|
789
|
+
}
|
|
790
|
+
try {
|
|
791
|
+
await maintenance.release();
|
|
792
|
+
} catch (error) {
|
|
793
|
+
await lease.release().catch(() => {
|
|
794
|
+
});
|
|
795
|
+
throw error;
|
|
796
|
+
}
|
|
797
|
+
return {
|
|
798
|
+
mode: "fallback",
|
|
799
|
+
activePath: nodePath.join(familyDir, "daemon.log"),
|
|
800
|
+
archiveDir: nodePath.join(familyDir, "archive"),
|
|
801
|
+
familyDir,
|
|
802
|
+
lease,
|
|
803
|
+
releaseLease: lease.release
|
|
804
|
+
};
|
|
805
|
+
}
|
|
806
|
+
__name(allocateFallbackFamily, "allocateFallbackFamily");
|
|
807
|
+
async function removeFailedFallbackBestEffort(input) {
|
|
808
|
+
if (input.family.lease.compromised) {
|
|
809
|
+
await input.family.releaseLease().catch(() => {
|
|
810
|
+
});
|
|
811
|
+
return;
|
|
812
|
+
}
|
|
813
|
+
const runsDir = nodePath.dirname(input.family.familyDir);
|
|
814
|
+
let maintenance;
|
|
815
|
+
try {
|
|
816
|
+
maintenance = await acquireMaintenanceLease({
|
|
817
|
+
...input,
|
|
818
|
+
runsDir,
|
|
819
|
+
retryBudgetMs: 0
|
|
820
|
+
});
|
|
376
821
|
} catch {
|
|
822
|
+
await input.family.releaseLease().catch(() => {
|
|
823
|
+
});
|
|
824
|
+
return;
|
|
825
|
+
}
|
|
826
|
+
try {
|
|
827
|
+
if (maintenance.compromised) {
|
|
828
|
+
await input.family.releaseLease().catch(() => {
|
|
829
|
+
});
|
|
830
|
+
return;
|
|
831
|
+
}
|
|
832
|
+
try {
|
|
833
|
+
await input.family.releaseLease();
|
|
834
|
+
} catch {
|
|
835
|
+
return;
|
|
836
|
+
}
|
|
837
|
+
if (maintenance.compromised || input.family.lease.compromised) return;
|
|
838
|
+
await input.fs.rm(input.family.familyDir, { recursive: true, force: true }).catch(() => {
|
|
839
|
+
});
|
|
840
|
+
} finally {
|
|
841
|
+
await maintenance.release().catch(() => {
|
|
842
|
+
});
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
__name(removeFailedFallbackBestEffort, "removeFailedFallbackBestEffort");
|
|
846
|
+
async function closeFallbackFamily(input) {
|
|
847
|
+
if (input.family.lease.compromised) {
|
|
848
|
+
await input.family.releaseLease().catch(() => {
|
|
849
|
+
});
|
|
850
|
+
return;
|
|
851
|
+
}
|
|
852
|
+
const runsDir = nodePath.dirname(input.family.familyDir);
|
|
853
|
+
let maintenance;
|
|
854
|
+
try {
|
|
855
|
+
maintenance = await acquireMaintenanceLease({
|
|
856
|
+
...input,
|
|
857
|
+
runsDir,
|
|
858
|
+
retryBudgetMs: 0
|
|
859
|
+
});
|
|
860
|
+
} catch {
|
|
861
|
+
await input.family.releaseLease().catch(input.onRetentionError);
|
|
862
|
+
return;
|
|
377
863
|
}
|
|
864
|
+
try {
|
|
865
|
+
if (maintenance.compromised) {
|
|
866
|
+
throw new Error("Fallback maintenance lease was compromised");
|
|
867
|
+
}
|
|
868
|
+
await input.family.releaseLease();
|
|
869
|
+
const name = nodePath.basename(input.family.familyDir);
|
|
870
|
+
const mutationAllowed = /* @__PURE__ */ __name(() => !maintenance.compromised && !input.family.lease.compromised, "mutationAllowed");
|
|
871
|
+
await cleanupFallbackFamilies({
|
|
872
|
+
...input,
|
|
873
|
+
runsDir,
|
|
874
|
+
preferredInactive: name,
|
|
875
|
+
mutationAllowed
|
|
876
|
+
});
|
|
877
|
+
await writeRecentFallback(input.fs, runsDir, name, mutationAllowed);
|
|
878
|
+
} catch (error) {
|
|
879
|
+
await input.family.releaseLease().catch(input.onRetentionError);
|
|
880
|
+
input.onRetentionError(error);
|
|
881
|
+
} finally {
|
|
882
|
+
await maintenance.release().catch(input.onRetentionError);
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
__name(closeFallbackFamily, "closeFallbackFamily");
|
|
886
|
+
async function cleanupFallbacksBestEffort(input) {
|
|
887
|
+
const runsDir = nodePath.join(input.daemonDir, "runs");
|
|
888
|
+
try {
|
|
889
|
+
const stat = await input.fs.lstat(runsDir);
|
|
890
|
+
if (!stat.isDirectory() || stat.isSymbolicLink()) {
|
|
891
|
+
throw new Error(`${runsDir} is not a real directory`);
|
|
892
|
+
}
|
|
893
|
+
} catch (error) {
|
|
894
|
+
if (isErrno(error, "ENOENT")) return;
|
|
895
|
+
input.onRetentionError(error);
|
|
896
|
+
return;
|
|
897
|
+
}
|
|
898
|
+
let maintenance;
|
|
899
|
+
try {
|
|
900
|
+
const currentMaintenance = await acquireMaintenanceLease({
|
|
901
|
+
...input,
|
|
902
|
+
runsDir,
|
|
903
|
+
retryBudgetMs: 0
|
|
904
|
+
});
|
|
905
|
+
maintenance = currentMaintenance;
|
|
906
|
+
const mutationAllowed = /* @__PURE__ */ __name(() => !currentMaintenance.compromised && !currentMaintenance.released && (input.mutationAllowed?.() ?? true), "mutationAllowed");
|
|
907
|
+
if (!mutationAllowed()) {
|
|
908
|
+
throw new Error("Fallback maintenance lease was compromised");
|
|
909
|
+
}
|
|
910
|
+
await cleanupFallbackFamilies({
|
|
911
|
+
...input,
|
|
912
|
+
runsDir,
|
|
913
|
+
mutationAllowed
|
|
914
|
+
});
|
|
915
|
+
} catch (error) {
|
|
916
|
+
if (!isErrno(error, "ELOCKED")) input.onRetentionError(error);
|
|
917
|
+
} finally {
|
|
918
|
+
await maintenance?.release().catch(input.onRetentionError);
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
__name(cleanupFallbacksBestEffort, "cleanupFallbacksBestEffort");
|
|
922
|
+
function createConcreteLogger(input) {
|
|
378
923
|
let pending = Promise.resolve();
|
|
379
|
-
let
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
924
|
+
let pendingBytes = 0;
|
|
925
|
+
let droppedRecords = 0;
|
|
926
|
+
let droppedBytes = 0;
|
|
927
|
+
let reportedDroppedRecords = 0;
|
|
928
|
+
let reportedDroppedBytes = 0;
|
|
929
|
+
let overflowEpisode = false;
|
|
930
|
+
let dropSummaryPending = false;
|
|
931
|
+
let acceptingFileRecords = true;
|
|
932
|
+
let closePromise;
|
|
933
|
+
const markDropped = /* @__PURE__ */ __name((bytes, queueOverflow = false) => {
|
|
934
|
+
droppedRecords += 1;
|
|
935
|
+
droppedBytes += bytes;
|
|
936
|
+
if (queueOverflow) {
|
|
937
|
+
input.issues.add("queue_overflow");
|
|
938
|
+
if (!overflowEpisode) {
|
|
939
|
+
overflowEpisode = true;
|
|
940
|
+
input.stderr(
|
|
941
|
+
"qwen serve: daemon log queue limit reached; dropping file copies until capacity recovers"
|
|
942
|
+
);
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
}, "markDropped");
|
|
946
|
+
const markRotationFailure = /* @__PURE__ */ __name((message, error) => {
|
|
947
|
+
input.issues.add("rotation_failed");
|
|
948
|
+
input.state.nextRotationRetryAt = input.monotonicNow() + input.policy.rotationRetryIntervalMs;
|
|
949
|
+
input.warnOnce(
|
|
950
|
+
`rotation:${message}`,
|
|
951
|
+
`qwen serve: daemon log rotation failed; ${message}${error ? `: ${error instanceof Error ? error.message : String(error)}` : ""}`
|
|
952
|
+
);
|
|
953
|
+
}, "markRotationFailure");
|
|
954
|
+
const markRetentionFailure = /* @__PURE__ */ __name((error) => {
|
|
955
|
+
input.issues.add("retention_failed");
|
|
956
|
+
input.warnOnce(
|
|
957
|
+
"retention",
|
|
958
|
+
`qwen serve: daemon log retention cleanup failed: ${error instanceof Error ? error.message : String(error)}`
|
|
959
|
+
);
|
|
960
|
+
}, "markRetentionFailure");
|
|
961
|
+
const fileMutationAllowed = /* @__PURE__ */ __name(() => !input.state.poisoned && !input.family.lease.compromised && !input.family.lease.released, "fileMutationAllowed");
|
|
962
|
+
const prepareArchives = /* @__PURE__ */ __name(async () => {
|
|
963
|
+
if (!input.state.archiveAvailable && input.monotonicNow() < input.state.nextRotationRetryAt) {
|
|
964
|
+
return false;
|
|
965
|
+
}
|
|
966
|
+
try {
|
|
967
|
+
await ensureRealDirectory(
|
|
968
|
+
input.fs,
|
|
969
|
+
input.family.archiveDir,
|
|
970
|
+
fileMutationAllowed
|
|
971
|
+
);
|
|
972
|
+
if (!fileMutationAllowed()) return false;
|
|
973
|
+
input.state.archives = await scanArchives(
|
|
974
|
+
input.fs,
|
|
975
|
+
input.family.archiveDir
|
|
976
|
+
);
|
|
977
|
+
input.state.nextArchiveGeneration = (input.state.archives.at(-1)?.generation ?? 0) + 1;
|
|
978
|
+
input.state.archiveAvailable = true;
|
|
979
|
+
input.state.nextRotationRetryAt = 0;
|
|
980
|
+
return true;
|
|
981
|
+
} catch (error) {
|
|
982
|
+
if (!fileMutationAllowed()) return false;
|
|
983
|
+
input.state.archiveAvailable = false;
|
|
984
|
+
markRotationFailure("continuing without file rotation", error);
|
|
985
|
+
return false;
|
|
986
|
+
}
|
|
987
|
+
}, "prepareArchives");
|
|
988
|
+
const pruneForRotation = /* @__PURE__ */ __name(async () => {
|
|
989
|
+
while (input.state.archives.length >= input.policy.maxArchives) {
|
|
990
|
+
if (!fileMutationAllowed()) return false;
|
|
991
|
+
const oldest = input.state.archives[0];
|
|
992
|
+
try {
|
|
993
|
+
await input.fs.unlink(
|
|
994
|
+
nodePath.join(input.family.archiveDir, oldest.name)
|
|
995
|
+
);
|
|
996
|
+
input.state.archives.shift();
|
|
997
|
+
} catch (error) {
|
|
998
|
+
if (isErrno(error, "ENOENT")) {
|
|
999
|
+
input.state.archives.shift();
|
|
1000
|
+
continue;
|
|
388
1001
|
}
|
|
389
|
-
|
|
1002
|
+
markRetentionFailure(error);
|
|
1003
|
+
input.state.nextRotationRetryAt = input.monotonicNow() + input.policy.rotationRetryIntervalMs;
|
|
1004
|
+
return false;
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
return true;
|
|
1008
|
+
}, "pruneForRotation");
|
|
1009
|
+
const archivePath = /* @__PURE__ */ __name(async () => {
|
|
1010
|
+
const generation = input.state.nextArchiveGeneration;
|
|
1011
|
+
if (generation > 999999999999) {
|
|
1012
|
+
markRotationFailure("archive generation limit reached");
|
|
1013
|
+
return void 0;
|
|
1014
|
+
}
|
|
1015
|
+
for (let attempt = 0; attempt < ARCHIVE_NAME_ATTEMPTS; attempt += 1) {
|
|
1016
|
+
let name;
|
|
1017
|
+
try {
|
|
1018
|
+
name = `daemon-${String(generation).padStart(12, "0")}-${archiveTimestamp(input.now())}-${crypto.randomBytes(4).toString("hex")}.log`;
|
|
1019
|
+
} catch (error) {
|
|
1020
|
+
markRotationFailure("archive filename generation failed", error);
|
|
1021
|
+
return void 0;
|
|
1022
|
+
}
|
|
1023
|
+
const candidate = nodePath.join(input.family.archiveDir, name);
|
|
1024
|
+
try {
|
|
1025
|
+
await input.fs.lstat(candidate);
|
|
1026
|
+
} catch (error) {
|
|
1027
|
+
if (isErrno(error, "ENOENT")) return { name, generation };
|
|
1028
|
+
markRotationFailure("archive target validation failed", error);
|
|
1029
|
+
return void 0;
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
markRotationFailure("archive filename collision limit reached");
|
|
1033
|
+
return void 0;
|
|
1034
|
+
}, "archivePath");
|
|
1035
|
+
const appendActive = /* @__PURE__ */ __name(async (record, forceRotation = false) => {
|
|
1036
|
+
if (!fileMutationAllowed()) return "dropped";
|
|
1037
|
+
const bytes = Buffer.byteLength(record, "utf8");
|
|
1038
|
+
const needsRotation = input.state.currentBytes > 0 && (forceRotation || input.state.currentBytes + bytes > input.policy.maxBytes);
|
|
1039
|
+
if (needsRotation) {
|
|
1040
|
+
if (input.monotonicNow() < input.state.nextRotationRetryAt) {
|
|
1041
|
+
return "dropped";
|
|
1042
|
+
}
|
|
1043
|
+
if (!await prepareArchives()) return "dropped";
|
|
1044
|
+
if (!fileMutationAllowed()) return "dropped";
|
|
1045
|
+
if (!await pruneForRotation()) return "dropped";
|
|
1046
|
+
const archive = await archivePath();
|
|
1047
|
+
if (!archive) return "dropped";
|
|
1048
|
+
if (!fileMutationAllowed()) return "dropped";
|
|
1049
|
+
try {
|
|
1050
|
+
await input.fs.rename(
|
|
1051
|
+
input.family.activePath,
|
|
1052
|
+
nodePath.join(input.family.archiveDir, archive.name)
|
|
1053
|
+
);
|
|
1054
|
+
} catch (error) {
|
|
1055
|
+
markRotationFailure("active file rename failed", error);
|
|
1056
|
+
return "dropped";
|
|
1057
|
+
}
|
|
1058
|
+
input.state.archives.push(archive);
|
|
1059
|
+
input.state.archives.sort(
|
|
1060
|
+
(a, b) => a.generation - b.generation || a.name.localeCompare(b.name)
|
|
1061
|
+
);
|
|
1062
|
+
input.state.nextArchiveGeneration = archive.generation + 1;
|
|
1063
|
+
input.state.currentBytes = 0;
|
|
1064
|
+
if (!fileMutationAllowed()) return "dropped";
|
|
1065
|
+
}
|
|
1066
|
+
if (!fileMutationAllowed()) return "dropped";
|
|
1067
|
+
try {
|
|
1068
|
+
if (input.state.exclusiveBootCreate) {
|
|
1069
|
+
await input.fs.writeFile(input.family.activePath, record, {
|
|
1070
|
+
encoding: "utf8",
|
|
1071
|
+
mode: FILE_MODE,
|
|
1072
|
+
flag: "wx"
|
|
1073
|
+
});
|
|
1074
|
+
input.state.exclusiveBootCreate = false;
|
|
1075
|
+
} else {
|
|
1076
|
+
await input.fs.appendFile(input.family.activePath, record, {
|
|
1077
|
+
encoding: "utf8",
|
|
1078
|
+
mode: FILE_MODE,
|
|
1079
|
+
flag: "a"
|
|
1080
|
+
});
|
|
1081
|
+
}
|
|
1082
|
+
input.state.currentBytes += bytes;
|
|
1083
|
+
return "written";
|
|
1084
|
+
} catch (error) {
|
|
1085
|
+
input.state.poisoned = true;
|
|
1086
|
+
input.issues.add("write_failed");
|
|
1087
|
+
input.warnOnce(
|
|
1088
|
+
"write-failed",
|
|
1089
|
+
`qwen serve: daemon log write failed; file logging disabled for this run: ${error instanceof Error ? error.message : String(error)}`
|
|
1090
|
+
);
|
|
1091
|
+
return "unknown";
|
|
1092
|
+
}
|
|
1093
|
+
}, "appendActive");
|
|
1094
|
+
const unreportedDropRecord = /* @__PURE__ */ __name(() => {
|
|
1095
|
+
const records = droppedRecords - reportedDroppedRecords;
|
|
1096
|
+
const bytes = droppedBytes - reportedDroppedBytes;
|
|
1097
|
+
if (records <= 0) return void 0;
|
|
1098
|
+
return capUtf8Record(
|
|
1099
|
+
buildDaemonFileLogLine(
|
|
1100
|
+
{
|
|
1101
|
+
level: "WARN",
|
|
1102
|
+
message: "daemon file log records dropped",
|
|
1103
|
+
now: input.now(),
|
|
1104
|
+
ctx: { droppedRecords: records, droppedBytes: bytes }
|
|
1105
|
+
},
|
|
1106
|
+
input.runId,
|
|
1107
|
+
input.pid
|
|
1108
|
+
),
|
|
1109
|
+
input.policy.maxRecordBytes
|
|
390
1110
|
);
|
|
391
|
-
}, "
|
|
392
|
-
const
|
|
393
|
-
const
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
1111
|
+
}, "unreportedDropRecord");
|
|
1112
|
+
const enqueueRecord = /* @__PURE__ */ __name((record, callerOriginated, onSettled) => {
|
|
1113
|
+
const bytes = Buffer.byteLength(record, "utf8");
|
|
1114
|
+
if (pendingBytes + bytes > input.policy.maxPendingBytes) {
|
|
1115
|
+
if (callerOriginated) markDropped(bytes, true);
|
|
1116
|
+
return false;
|
|
1117
|
+
}
|
|
1118
|
+
pendingBytes += bytes;
|
|
1119
|
+
pending = pending.then(async () => {
|
|
1120
|
+
let outcome = "unknown";
|
|
1121
|
+
try {
|
|
1122
|
+
outcome = await appendActive(record);
|
|
1123
|
+
if (callerOriginated && outcome === "dropped") markDropped(bytes);
|
|
1124
|
+
} catch (error) {
|
|
1125
|
+
input.state.poisoned = true;
|
|
1126
|
+
input.issues.add("write_failed");
|
|
1127
|
+
input.warnOnce(
|
|
1128
|
+
"queue-failed",
|
|
1129
|
+
`qwen serve: daemon log queue failed; file logging disabled for this run: ${error instanceof Error ? error.message : String(error)}`
|
|
1130
|
+
);
|
|
1131
|
+
} finally {
|
|
1132
|
+
onSettled?.(outcome);
|
|
1133
|
+
}
|
|
1134
|
+
}).catch(() => {
|
|
1135
|
+
}).finally(() => {
|
|
1136
|
+
pendingBytes -= bytes;
|
|
1137
|
+
});
|
|
1138
|
+
return true;
|
|
1139
|
+
}, "enqueueRecord");
|
|
1140
|
+
const enqueueDropSummary = /* @__PURE__ */ __name(() => {
|
|
1141
|
+
if (dropSummaryPending) return;
|
|
1142
|
+
const summary = unreportedDropRecord();
|
|
1143
|
+
if (!summary) return;
|
|
1144
|
+
const summaryRecords = droppedRecords;
|
|
1145
|
+
const summaryBytes = droppedBytes;
|
|
1146
|
+
if (enqueueRecord(summary, false, (outcome) => {
|
|
1147
|
+
if (outcome === "written") {
|
|
1148
|
+
reportedDroppedRecords = summaryRecords;
|
|
1149
|
+
reportedDroppedBytes = summaryBytes;
|
|
1150
|
+
}
|
|
1151
|
+
dropSummaryPending = false;
|
|
1152
|
+
})) {
|
|
1153
|
+
dropSummaryPending = true;
|
|
1154
|
+
overflowEpisode = false;
|
|
1155
|
+
}
|
|
1156
|
+
}, "enqueueDropSummary");
|
|
1157
|
+
const submitFileRecord = /* @__PURE__ */ __name((record) => {
|
|
1158
|
+
if (!acceptingFileRecords) return;
|
|
1159
|
+
const bytes = Buffer.byteLength(record, "utf8");
|
|
1160
|
+
if (!fileMutationAllowed()) {
|
|
1161
|
+
markDropped(bytes);
|
|
1162
|
+
return;
|
|
1163
|
+
}
|
|
1164
|
+
enqueueDropSummary();
|
|
1165
|
+
enqueueRecord(record, true);
|
|
1166
|
+
}, "submitFileRecord");
|
|
1167
|
+
const tee = /* @__PURE__ */ __name((level, message, ctx, err) => {
|
|
1168
|
+
const timestamp = input.now();
|
|
1169
|
+
input.stderr(
|
|
1170
|
+
buildDaemonLogLine({
|
|
1171
|
+
level,
|
|
1172
|
+
message,
|
|
1173
|
+
now: timestamp,
|
|
1174
|
+
ctx,
|
|
1175
|
+
err
|
|
1176
|
+
}).trimEnd()
|
|
1177
|
+
);
|
|
1178
|
+
submitFileRecord(
|
|
1179
|
+
capUtf8Record(
|
|
1180
|
+
buildDaemonFileLogLine(
|
|
1181
|
+
{ level, message, now: timestamp, ctx, err },
|
|
1182
|
+
input.runId,
|
|
1183
|
+
input.pid
|
|
1184
|
+
),
|
|
1185
|
+
input.policy.maxRecordBytes
|
|
1186
|
+
)
|
|
1187
|
+
);
|
|
1188
|
+
}, "tee");
|
|
1189
|
+
const finalize = /* @__PURE__ */ __name(async () => {
|
|
1190
|
+
await pending;
|
|
1191
|
+
const summary = unreportedDropRecord();
|
|
1192
|
+
if (summary && !input.state.poisoned && !input.family.lease.compromised) {
|
|
1193
|
+
if (await appendActive(summary) === "written") {
|
|
1194
|
+
reportedDroppedRecords = droppedRecords;
|
|
1195
|
+
reportedDroppedBytes = droppedBytes;
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
if (input.family.mode === "fallback") {
|
|
1199
|
+
await closeFallbackFamily({
|
|
1200
|
+
...input,
|
|
1201
|
+
onRetentionError: markRetentionFailure
|
|
1202
|
+
});
|
|
1203
|
+
} else {
|
|
1204
|
+
await input.family.releaseLease().catch((error) => {
|
|
1205
|
+
input.warnOnce(
|
|
1206
|
+
"release-failed",
|
|
1207
|
+
`qwen serve: daemon log lease release failed: ${error instanceof Error ? error.message : String(error)}`
|
|
1208
|
+
);
|
|
1209
|
+
});
|
|
1210
|
+
}
|
|
1211
|
+
}, "finalize");
|
|
1212
|
+
const logger = {
|
|
1213
|
+
info: /* @__PURE__ */ __name((message, ctx) => tee("INFO", message, ctx), "info"),
|
|
1214
|
+
warn: /* @__PURE__ */ __name((message, ctx) => tee("WARN", message, ctx), "warn"),
|
|
1215
|
+
error: /* @__PURE__ */ __name((message, err, ctx) => tee("ERROR", message, ctx, err ?? void 0), "error"),
|
|
401
1216
|
raw: /* @__PURE__ */ __name((line, level = "info") => {
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
1217
|
+
submitFileRecord(
|
|
1218
|
+
capUtf8Record(
|
|
1219
|
+
buildDaemonFileLogLine(
|
|
1220
|
+
{
|
|
1221
|
+
level: level.toUpperCase(),
|
|
1222
|
+
message: line,
|
|
1223
|
+
now: input.now()
|
|
1224
|
+
},
|
|
1225
|
+
input.runId,
|
|
1226
|
+
input.pid
|
|
1227
|
+
),
|
|
1228
|
+
input.policy.maxRecordBytes
|
|
1229
|
+
)
|
|
1230
|
+
);
|
|
406
1231
|
}, "raw"),
|
|
407
|
-
getLogPath: /* @__PURE__ */ __name(() =>
|
|
408
|
-
getDaemonId: /* @__PURE__ */ __name(() => daemonId, "getDaemonId"),
|
|
409
|
-
|
|
1232
|
+
getLogPath: /* @__PURE__ */ __name(() => input.family.activePath, "getLogPath"),
|
|
1233
|
+
getDaemonId: /* @__PURE__ */ __name(() => input.daemonId, "getDaemonId"),
|
|
1234
|
+
getStatus: /* @__PURE__ */ __name(() => statusSnapshot(
|
|
1235
|
+
input.runId,
|
|
1236
|
+
input.family.mode,
|
|
1237
|
+
input.issues,
|
|
1238
|
+
droppedRecords,
|
|
1239
|
+
droppedBytes
|
|
1240
|
+
), "getStatus"),
|
|
1241
|
+
flush: /* @__PURE__ */ __name(() => pending, "flush"),
|
|
1242
|
+
close: /* @__PURE__ */ __name(() => {
|
|
1243
|
+
if (closePromise) return closePromise;
|
|
1244
|
+
acceptingFileRecords = false;
|
|
1245
|
+
const finalizer = finalize().catch((error) => {
|
|
1246
|
+
try {
|
|
1247
|
+
input.warnOnce(
|
|
1248
|
+
"close-failed",
|
|
1249
|
+
`qwen serve: daemon log close failed: ${error instanceof Error ? error.message : String(error)}`
|
|
1250
|
+
);
|
|
1251
|
+
} catch {
|
|
1252
|
+
}
|
|
1253
|
+
});
|
|
1254
|
+
let timeout;
|
|
1255
|
+
const deadline = new Promise((resolve) => {
|
|
1256
|
+
timeout = setTimeout(() => {
|
|
1257
|
+
try {
|
|
1258
|
+
input.warnOnce(
|
|
1259
|
+
"close-timeout",
|
|
1260
|
+
`qwen serve: daemon log close drain exceeded ${input.policy.closeDrainBudgetMs}ms; ownership will release after pending I/O settles or process exit`
|
|
1261
|
+
);
|
|
1262
|
+
} catch {
|
|
1263
|
+
} finally {
|
|
1264
|
+
resolve();
|
|
1265
|
+
}
|
|
1266
|
+
}, input.policy.closeDrainBudgetMs);
|
|
1267
|
+
timeout.unref();
|
|
1268
|
+
});
|
|
1269
|
+
closePromise = Promise.race([finalizer, deadline]).then(() => {
|
|
1270
|
+
if (timeout) clearTimeout(timeout);
|
|
1271
|
+
});
|
|
1272
|
+
return closePromise;
|
|
1273
|
+
}, "close")
|
|
410
1274
|
};
|
|
1275
|
+
return { logger, writeInitialRecord: appendActive };
|
|
1276
|
+
}
|
|
1277
|
+
__name(createConcreteLogger, "createConcreteLogger");
|
|
1278
|
+
async function initDaemonLogger(opts) {
|
|
1279
|
+
const pid = opts.pid ?? process.pid;
|
|
1280
|
+
const now = opts.now ?? (() => /* @__PURE__ */ new Date());
|
|
1281
|
+
const monotonicNow = opts.monotonicNow ?? (() => performance.now());
|
|
1282
|
+
const stderr = opts.stderr ?? writeStderrLine;
|
|
1283
|
+
const baseDir = opts.baseDir ?? resolveDaemonLogBaseDir();
|
|
1284
|
+
const runId = opts.runId ?? crypto.randomBytes(16).toString("hex");
|
|
1285
|
+
const policy = resolvePolicy(opts.policy);
|
|
1286
|
+
const fs2 = opts.fs ?? nodeFs.promises;
|
|
1287
|
+
const acquireLock = opts.acquireLock ?? import_proper_lockfile.default.lock;
|
|
1288
|
+
const issues = /* @__PURE__ */ new Set();
|
|
1289
|
+
const warned = /* @__PURE__ */ new Set();
|
|
1290
|
+
const warnOnce = /* @__PURE__ */ __name((key, message) => {
|
|
1291
|
+
if (warned.has(key)) return;
|
|
1292
|
+
warned.add(key);
|
|
1293
|
+
try {
|
|
1294
|
+
stderr(message);
|
|
1295
|
+
} catch {
|
|
1296
|
+
}
|
|
1297
|
+
}, "warnOnce");
|
|
1298
|
+
if (isOptedOut()) {
|
|
1299
|
+
return createStderrOnlyLogger({
|
|
1300
|
+
runId,
|
|
1301
|
+
daemonId: computeDaemonId(pid),
|
|
1302
|
+
now,
|
|
1303
|
+
stderr,
|
|
1304
|
+
issues
|
|
1305
|
+
});
|
|
1306
|
+
}
|
|
1307
|
+
const daemonDir = nodePath.join(baseDir, "daemon");
|
|
1308
|
+
try {
|
|
1309
|
+
await ensureRealDirectory(fs2, daemonDir);
|
|
1310
|
+
} catch (error) {
|
|
1311
|
+
issues.add("init_failed");
|
|
1312
|
+
warnOnce(
|
|
1313
|
+
"init",
|
|
1314
|
+
`qwen serve: daemon log disabled \u2014 init failed: ${error instanceof Error ? error.message : String(error)}`
|
|
1315
|
+
);
|
|
1316
|
+
return createStderrOnlyLogger({
|
|
1317
|
+
runId,
|
|
1318
|
+
daemonId: computeDaemonId(pid),
|
|
1319
|
+
now,
|
|
1320
|
+
stderr,
|
|
1321
|
+
issues
|
|
1322
|
+
});
|
|
1323
|
+
}
|
|
1324
|
+
let currentState;
|
|
1325
|
+
const onCompromised = /* @__PURE__ */ __name((error) => {
|
|
1326
|
+
issues.add("lease_compromised");
|
|
1327
|
+
if (currentState) currentState.poisoned = true;
|
|
1328
|
+
warnOnce(
|
|
1329
|
+
"lease-compromised",
|
|
1330
|
+
`qwen serve: daemon log lease compromised; file logging disabled for this run: ${error.message}`
|
|
1331
|
+
);
|
|
1332
|
+
}, "onCompromised");
|
|
1333
|
+
const tryFamily = /* @__PURE__ */ __name(async (family) => {
|
|
1334
|
+
let state;
|
|
1335
|
+
try {
|
|
1336
|
+
const currentBytes = await activeFileSize(fs2, family.activePath);
|
|
1337
|
+
if (family.mode === "fallback" && currentBytes !== 0) {
|
|
1338
|
+
throw new Error(
|
|
1339
|
+
"New fallback family unexpectedly contains an active log"
|
|
1340
|
+
);
|
|
1341
|
+
}
|
|
1342
|
+
const completeTail = await lastByteIsNewline(
|
|
1343
|
+
fs2,
|
|
1344
|
+
family.activePath,
|
|
1345
|
+
currentBytes
|
|
1346
|
+
);
|
|
1347
|
+
let archiveAvailable = true;
|
|
1348
|
+
let archives = [];
|
|
1349
|
+
const familyMutationAllowed = /* @__PURE__ */ __name(() => !family.lease.compromised && !family.lease.released, "familyMutationAllowed");
|
|
1350
|
+
try {
|
|
1351
|
+
await ensureRealDirectory(fs2, family.archiveDir, familyMutationAllowed);
|
|
1352
|
+
if (!familyMutationAllowed()) {
|
|
1353
|
+
throw new Error("Daemon log family lease was compromised");
|
|
1354
|
+
}
|
|
1355
|
+
archives = await scanArchives(fs2, family.archiveDir);
|
|
1356
|
+
} catch (error) {
|
|
1357
|
+
archiveAvailable = false;
|
|
1358
|
+
if (familyMutationAllowed()) {
|
|
1359
|
+
issues.add("rotation_failed");
|
|
1360
|
+
warnOnce(
|
|
1361
|
+
`archive-init:${family.mode}`,
|
|
1362
|
+
`qwen serve: daemon log archive unavailable; active file will remain bounded: ${error instanceof Error ? error.message : String(error)}`
|
|
1363
|
+
);
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
state = {
|
|
1367
|
+
currentBytes,
|
|
1368
|
+
archives,
|
|
1369
|
+
nextArchiveGeneration: (archives.at(-1)?.generation ?? 0) + 1,
|
|
1370
|
+
archiveAvailable,
|
|
1371
|
+
exclusiveBootCreate: family.mode === "fallback",
|
|
1372
|
+
poisoned: false,
|
|
1373
|
+
nextRotationRetryAt: archiveAvailable ? 0 : monotonicNow() + policy.rotationRetryIntervalMs
|
|
1374
|
+
};
|
|
1375
|
+
currentState = state;
|
|
1376
|
+
const concrete = createConcreteLogger({
|
|
1377
|
+
fs: fs2,
|
|
1378
|
+
acquireLock,
|
|
1379
|
+
policy,
|
|
1380
|
+
family,
|
|
1381
|
+
state,
|
|
1382
|
+
runId,
|
|
1383
|
+
pid,
|
|
1384
|
+
daemonId: computeDaemonId(pid),
|
|
1385
|
+
now,
|
|
1386
|
+
monotonicNow,
|
|
1387
|
+
stderr,
|
|
1388
|
+
issues,
|
|
1389
|
+
warnOnce
|
|
1390
|
+
});
|
|
1391
|
+
const bootCtx = {
|
|
1392
|
+
workspace: opts.boundWorkspace,
|
|
1393
|
+
workspaceHash: computeWorkspaceHash(opts.boundWorkspace)
|
|
1394
|
+
};
|
|
1395
|
+
const bootTime = now();
|
|
1396
|
+
const plainBoot = capUtf8Record(
|
|
1397
|
+
buildDaemonFileLogLine(
|
|
1398
|
+
{
|
|
1399
|
+
level: "INFO",
|
|
1400
|
+
message: "daemon started",
|
|
1401
|
+
now: bootTime,
|
|
1402
|
+
ctx: bootCtx
|
|
1403
|
+
},
|
|
1404
|
+
runId,
|
|
1405
|
+
pid
|
|
1406
|
+
),
|
|
1407
|
+
policy.maxRecordBytes
|
|
1408
|
+
);
|
|
1409
|
+
const incompleteTailBoot = !completeTail ? `
|
|
1410
|
+
${capUtf8Record(
|
|
1411
|
+
buildDaemonFileLogLine(
|
|
1412
|
+
{
|
|
1413
|
+
level: "INFO",
|
|
1414
|
+
message: "daemon started",
|
|
1415
|
+
now: bootTime,
|
|
1416
|
+
ctx: { ...bootCtx, previousTailIncomplete: true }
|
|
1417
|
+
},
|
|
1418
|
+
runId,
|
|
1419
|
+
pid
|
|
1420
|
+
),
|
|
1421
|
+
policy.maxRecordBytes - 1
|
|
1422
|
+
)}` : plainBoot;
|
|
1423
|
+
const wouldRotate = currentBytes > 0 && currentBytes + Buffer.byteLength(incompleteTailBoot, "utf8") > policy.maxBytes;
|
|
1424
|
+
const bootRecord = !completeTail && !wouldRotate ? incompleteTailBoot : plainBoot;
|
|
1425
|
+
const bootOutcome = await concrete.writeInitialRecord(
|
|
1426
|
+
bootRecord,
|
|
1427
|
+
wouldRotate
|
|
1428
|
+
);
|
|
1429
|
+
if (bootOutcome !== "written" || state.poisoned || family.lease.compromised) {
|
|
1430
|
+
return void 0;
|
|
1431
|
+
}
|
|
1432
|
+
if (state.archiveAvailable && state.archives.length > policy.maxArchives) {
|
|
1433
|
+
try {
|
|
1434
|
+
while (state.archives.length > policy.maxArchives) {
|
|
1435
|
+
if (family.lease.compromised || family.lease.released) break;
|
|
1436
|
+
const oldest = state.archives[0];
|
|
1437
|
+
if (!oldest) break;
|
|
1438
|
+
try {
|
|
1439
|
+
await fs2.unlink(nodePath.join(family.archiveDir, oldest.name));
|
|
1440
|
+
} catch (error) {
|
|
1441
|
+
if (!isErrno(error, "ENOENT")) throw error;
|
|
1442
|
+
}
|
|
1443
|
+
state.archives.shift();
|
|
1444
|
+
}
|
|
1445
|
+
} catch (error) {
|
|
1446
|
+
issues.add("retention_failed");
|
|
1447
|
+
state.nextRotationRetryAt = monotonicNow() + policy.rotationRetryIntervalMs;
|
|
1448
|
+
warnOnce(
|
|
1449
|
+
"startup-retention",
|
|
1450
|
+
`qwen serve: daemon log retention cleanup failed: ${error instanceof Error ? error.message : String(error)}`
|
|
1451
|
+
);
|
|
1452
|
+
}
|
|
1453
|
+
}
|
|
1454
|
+
return concrete.logger;
|
|
1455
|
+
} catch (error) {
|
|
1456
|
+
warnOnce(
|
|
1457
|
+
`family-init:${family.mode}`,
|
|
1458
|
+
`qwen serve: daemon ${family.mode} log initialization failed: ${error instanceof Error ? error.message : String(error)}`
|
|
1459
|
+
);
|
|
1460
|
+
return void 0;
|
|
1461
|
+
}
|
|
1462
|
+
}, "tryFamily");
|
|
1463
|
+
try {
|
|
1464
|
+
const stableLease = await acquireLease({
|
|
1465
|
+
fs: fs2,
|
|
1466
|
+
acquireLock,
|
|
1467
|
+
targetPath: daemonDir,
|
|
1468
|
+
lockPath: nodePath.join(daemonDir, ".stable-writer.lock"),
|
|
1469
|
+
policy,
|
|
1470
|
+
retryBudgetMs: policy.stableAcquireBudgetMs,
|
|
1471
|
+
onCompromised
|
|
1472
|
+
});
|
|
1473
|
+
const stableFamily = {
|
|
1474
|
+
mode: "stable",
|
|
1475
|
+
activePath: nodePath.join(daemonDir, "daemon.log"),
|
|
1476
|
+
archiveDir: nodePath.join(daemonDir, "archive"),
|
|
1477
|
+
familyDir: daemonDir,
|
|
1478
|
+
lease: stableLease,
|
|
1479
|
+
releaseLease: stableLease.release
|
|
1480
|
+
};
|
|
1481
|
+
const stableLogger = await tryFamily(stableFamily);
|
|
1482
|
+
if (stableLogger) {
|
|
1483
|
+
if (!stableLease.compromised && !stableLease.released) {
|
|
1484
|
+
await updateLatestBestEffort(
|
|
1485
|
+
fs2,
|
|
1486
|
+
daemonDir,
|
|
1487
|
+
stableFamily.activePath,
|
|
1488
|
+
() => !stableLease.compromised && !stableLease.released
|
|
1489
|
+
);
|
|
1490
|
+
}
|
|
1491
|
+
if (!stableLease.compromised && !stableLease.released) {
|
|
1492
|
+
await cleanupFallbacksBestEffort({
|
|
1493
|
+
fs: fs2,
|
|
1494
|
+
acquireLock,
|
|
1495
|
+
policy,
|
|
1496
|
+
daemonDir,
|
|
1497
|
+
mutationAllowed: /* @__PURE__ */ __name(() => !stableLease.compromised && !stableLease.released, "mutationAllowed"),
|
|
1498
|
+
onRetentionError: /* @__PURE__ */ __name((error) => {
|
|
1499
|
+
issues.add("retention_failed");
|
|
1500
|
+
warnOnce(
|
|
1501
|
+
"fallback-retention",
|
|
1502
|
+
`qwen serve: daemon fallback log cleanup failed: ${error instanceof Error ? error.message : String(error)}`
|
|
1503
|
+
);
|
|
1504
|
+
}, "onRetentionError")
|
|
1505
|
+
});
|
|
1506
|
+
}
|
|
1507
|
+
return stableLogger;
|
|
1508
|
+
}
|
|
1509
|
+
issues.add("init_failed");
|
|
1510
|
+
try {
|
|
1511
|
+
await stableLease.release();
|
|
1512
|
+
} catch (error) {
|
|
1513
|
+
warnOnce(
|
|
1514
|
+
"stable-release",
|
|
1515
|
+
`qwen serve: daemon stable log lease release failed; trying fallback: ${error instanceof Error ? error.message : String(error)}`
|
|
1516
|
+
);
|
|
1517
|
+
}
|
|
1518
|
+
} catch (error) {
|
|
1519
|
+
if (isErrno(error, "ELOCKED")) {
|
|
1520
|
+
warnOnce(
|
|
1521
|
+
"stable-contention",
|
|
1522
|
+
`qwen serve: daemon stable log is owned by another daemon instance; using a fallback log for runId=${runId}`
|
|
1523
|
+
);
|
|
1524
|
+
} else {
|
|
1525
|
+
issues.add("init_failed");
|
|
1526
|
+
warnOnce(
|
|
1527
|
+
"stable-lock",
|
|
1528
|
+
`qwen serve: daemon stable log unavailable; trying a fallback: ${error instanceof Error ? error.message : String(error)}`
|
|
1529
|
+
);
|
|
1530
|
+
}
|
|
1531
|
+
}
|
|
1532
|
+
let fallbackFamily;
|
|
1533
|
+
try {
|
|
1534
|
+
fallbackFamily = await allocateFallbackFamily({
|
|
1535
|
+
fs: fs2,
|
|
1536
|
+
acquireLock,
|
|
1537
|
+
policy,
|
|
1538
|
+
daemonDir,
|
|
1539
|
+
runId,
|
|
1540
|
+
onCompromised
|
|
1541
|
+
});
|
|
1542
|
+
const activeFallbackFamily = fallbackFamily;
|
|
1543
|
+
const fallbackLogger = await tryFamily(activeFallbackFamily);
|
|
1544
|
+
if (!fallbackLogger) {
|
|
1545
|
+
issues.add("init_failed");
|
|
1546
|
+
await removeFailedFallbackBestEffort({
|
|
1547
|
+
fs: fs2,
|
|
1548
|
+
acquireLock,
|
|
1549
|
+
policy,
|
|
1550
|
+
family: activeFallbackFamily
|
|
1551
|
+
});
|
|
1552
|
+
return createStderrOnlyLogger({
|
|
1553
|
+
runId,
|
|
1554
|
+
daemonId: computeDaemonId(pid),
|
|
1555
|
+
now,
|
|
1556
|
+
stderr,
|
|
1557
|
+
issues
|
|
1558
|
+
});
|
|
1559
|
+
}
|
|
1560
|
+
const runsDir = nodePath.dirname(activeFallbackFamily.familyDir);
|
|
1561
|
+
try {
|
|
1562
|
+
if (activeFallbackFamily.lease.compromised) return fallbackLogger;
|
|
1563
|
+
const maintenance = await acquireMaintenanceLease({
|
|
1564
|
+
fs: fs2,
|
|
1565
|
+
acquireLock,
|
|
1566
|
+
policy,
|
|
1567
|
+
runsDir,
|
|
1568
|
+
retryBudgetMs: 0
|
|
1569
|
+
});
|
|
1570
|
+
try {
|
|
1571
|
+
if (!activeFallbackFamily.lease.compromised) {
|
|
1572
|
+
await writeRecentFallback(
|
|
1573
|
+
fs2,
|
|
1574
|
+
runsDir,
|
|
1575
|
+
nodePath.basename(activeFallbackFamily.familyDir),
|
|
1576
|
+
() => !maintenance.compromised && !maintenance.released && !activeFallbackFamily.lease.compromised
|
|
1577
|
+
);
|
|
1578
|
+
}
|
|
1579
|
+
} finally {
|
|
1580
|
+
await maintenance.release();
|
|
1581
|
+
}
|
|
1582
|
+
} catch (error) {
|
|
1583
|
+
warnOnce(
|
|
1584
|
+
"fallback-locator",
|
|
1585
|
+
`qwen serve: daemon fallback locator update failed; use ${activeFallbackFamily.activePath}: ${error instanceof Error ? error.message : String(error)}`
|
|
1586
|
+
);
|
|
1587
|
+
}
|
|
1588
|
+
return fallbackLogger;
|
|
1589
|
+
} catch (error) {
|
|
1590
|
+
issues.add("init_failed");
|
|
1591
|
+
await fallbackFamily?.releaseLease().catch(() => {
|
|
1592
|
+
});
|
|
1593
|
+
warnOnce(
|
|
1594
|
+
"fallback-init",
|
|
1595
|
+
`qwen serve: daemon log disabled \u2014 fallback init failed: ${error instanceof Error ? error.message : String(error)}`
|
|
1596
|
+
);
|
|
1597
|
+
return createStderrOnlyLogger({
|
|
1598
|
+
runId,
|
|
1599
|
+
daemonId: computeDaemonId(pid),
|
|
1600
|
+
now,
|
|
1601
|
+
stderr,
|
|
1602
|
+
issues
|
|
1603
|
+
});
|
|
1604
|
+
}
|
|
411
1605
|
}
|
|
412
1606
|
__name(initDaemonLogger, "initDaemonLogger");
|
|
413
1607
|
|
|
@@ -941,6 +2135,30 @@ var QWEN_SERVE_CDP_TUNNEL_OVER_WS_ENV = "QWEN_SERVE_CDP_TUNNEL_OVER_WS";
|
|
|
941
2135
|
var QWEN_SERVE_PROMPT_DEADLINE_MS_ENV = "QWEN_SERVE_PROMPT_DEADLINE_MS";
|
|
942
2136
|
var QWEN_SERVE_WRITER_IDLE_TIMEOUT_MS_ENV = "QWEN_SERVE_WRITER_IDLE_TIMEOUT_MS";
|
|
943
2137
|
var SHUTDOWN_FORCE_CLOSE_MS = 5e3;
|
|
2138
|
+
var DAEMON_LOG_FORCED_FLUSH_BUDGET_MS = 250;
|
|
2139
|
+
async function flushDaemonLogBounded(daemonLog, budgetMs) {
|
|
2140
|
+
let timer;
|
|
2141
|
+
try {
|
|
2142
|
+
await Promise.race([
|
|
2143
|
+
daemonLog.flush().catch(() => {
|
|
2144
|
+
}),
|
|
2145
|
+
new Promise((resolve) => {
|
|
2146
|
+
timer = setTimeout(resolve, budgetMs);
|
|
2147
|
+
timer.unref();
|
|
2148
|
+
})
|
|
2149
|
+
]);
|
|
2150
|
+
} finally {
|
|
2151
|
+
if (timer) clearTimeout(timer);
|
|
2152
|
+
}
|
|
2153
|
+
}
|
|
2154
|
+
__name(flushDaemonLogBounded, "flushDaemonLogBounded");
|
|
2155
|
+
function writeDaemonLifecycleBestEffort(write) {
|
|
2156
|
+
try {
|
|
2157
|
+
write();
|
|
2158
|
+
} catch {
|
|
2159
|
+
}
|
|
2160
|
+
}
|
|
2161
|
+
__name(writeDaemonLifecycleBestEffort, "writeDaemonLifecycleBestEffort");
|
|
944
2162
|
function daemonPipeDirection(direction) {
|
|
945
2163
|
switch (direction) {
|
|
946
2164
|
case "sent":
|
|
@@ -1139,12 +2357,12 @@ __name(withSettingsLock, "withSettingsLock");
|
|
|
1139
2357
|
var channelWorkerRuntimePromise;
|
|
1140
2358
|
async function loadChannelWorkerRuntime() {
|
|
1141
2359
|
channelWorkerRuntimePromise ??= Promise.all([
|
|
1142
|
-
import("./channel-worker-supervisor-
|
|
1143
|
-
import("./pidfile-
|
|
1144
|
-
import("./runtime-
|
|
2360
|
+
import("./channel-worker-supervisor-ZGO2W2MD.js"),
|
|
2361
|
+
import("./pidfile-MVZDE5TC.js"),
|
|
2362
|
+
import("./runtime-4KGNL3TP.js"),
|
|
1145
2363
|
import("./cli-entry-path-4VJ3Y6T2.js"),
|
|
1146
|
-
import("./channel-worker-group-
|
|
1147
|
-
import("./channel-worker-manager-
|
|
2364
|
+
import("./channel-worker-group-53CMOPFT.js"),
|
|
2365
|
+
import("./channel-worker-manager-UTXILKC2.js")
|
|
1148
2366
|
]).then(
|
|
1149
2367
|
([
|
|
1150
2368
|
supervisor,
|
|
@@ -1249,7 +2467,7 @@ function shouldPreheatBridge(deps) {
|
|
|
1249
2467
|
__name(shouldPreheatBridge, "shouldPreheatBridge");
|
|
1250
2468
|
var coreRuntimePromise;
|
|
1251
2469
|
function loadCoreRuntime() {
|
|
1252
|
-
coreRuntimePromise ??= import("./src-
|
|
2470
|
+
coreRuntimePromise ??= import("./src-DUFUUEHE.js");
|
|
1253
2471
|
return coreRuntimePromise;
|
|
1254
2472
|
}
|
|
1255
2473
|
__name(loadCoreRuntime, "loadCoreRuntime");
|
|
@@ -1279,10 +2497,10 @@ __name(resolveDaemonLogBaseDirForRun, "resolveDaemonLogBaseDirForRun");
|
|
|
1279
2497
|
var settingsRuntimePromise;
|
|
1280
2498
|
function loadSettingsRuntimeModules() {
|
|
1281
2499
|
settingsRuntimePromise ??= Promise.all([
|
|
1282
|
-
import("./settings-
|
|
1283
|
-
import("./environment-
|
|
1284
|
-
import("./loadedSettingsAdapter-
|
|
1285
|
-
import("./trustedFolders-
|
|
2500
|
+
import("./settings-H5O22TGQ.js"),
|
|
2501
|
+
import("./environment-KHS35XJY.js"),
|
|
2502
|
+
import("./loadedSettingsAdapter-3DUNHAPX.js"),
|
|
2503
|
+
import("./trustedFolders-ANQXYAQT.js")
|
|
1286
2504
|
]).then(([settings, environment, loadedSettingsAdapter, trustedFolders]) => ({
|
|
1287
2505
|
settings,
|
|
1288
2506
|
environment,
|
|
@@ -1295,8 +2513,8 @@ __name(loadSettingsRuntimeModules, "loadSettingsRuntimeModules");
|
|
|
1295
2513
|
var channelWebhookConfigRuntimePromise;
|
|
1296
2514
|
function loadChannelWebhookConfigRuntime() {
|
|
1297
2515
|
channelWebhookConfigRuntimePromise ??= Promise.all([
|
|
1298
|
-
import("./runtime-
|
|
1299
|
-
import("./config-utils-
|
|
2516
|
+
import("./runtime-4KGNL3TP.js"),
|
|
2517
|
+
import("./config-utils-AHQ6YZ66.js")
|
|
1300
2518
|
]).then(([channelRuntime, configUtils]) => ({
|
|
1301
2519
|
loadChannelsConfig: channelRuntime.loadChannelsConfig,
|
|
1302
2520
|
parseChannelWebhookConfig: configUtils.parseChannelWebhookConfig
|
|
@@ -1320,16 +2538,16 @@ async function loadServeRuntimeModules() {
|
|
|
1320
2538
|
totalSessionAdmissionModule,
|
|
1321
2539
|
workspaceRegistryModule
|
|
1322
2540
|
] = await Promise.all([
|
|
1323
|
-
import("./server-
|
|
1324
|
-
import("./bridge-
|
|
1325
|
-
import("./spawnChannel-
|
|
1326
|
-
import("./workspace-service-
|
|
2541
|
+
import("./server-RTJUMN24.js"),
|
|
2542
|
+
import("./bridge-OW5FZ6BF.js"),
|
|
2543
|
+
import("./spawnChannel-G7DUQKHL.js"),
|
|
2544
|
+
import("./workspace-service-JJNJWVH3.js"),
|
|
1327
2545
|
import("./types-ML3TRJQ5.js"),
|
|
1328
|
-
import("./daemon-status-provider-
|
|
1329
|
-
import("./workspace-providers-status-
|
|
1330
|
-
import("./workspace-skills-status-
|
|
1331
|
-
import("./total-session-admission-
|
|
1332
|
-
import("./workspace-registry-
|
|
2546
|
+
import("./daemon-status-provider-L5UW7TGV.js"),
|
|
2547
|
+
import("./workspace-providers-status-XCQKBVSX.js"),
|
|
2548
|
+
import("./workspace-skills-status-CEHLAQ2Y.js"),
|
|
2549
|
+
import("./total-session-admission-KOPTGDJZ.js"),
|
|
2550
|
+
import("./workspace-registry-N4J57SFQ.js")
|
|
1333
2551
|
]);
|
|
1334
2552
|
return {
|
|
1335
2553
|
createServeApp: serverModule.createServeApp,
|
|
@@ -1640,12 +2858,21 @@ function createBootstrapServeApp(input) {
|
|
|
1640
2858
|
severity: "warning",
|
|
1641
2859
|
message: "Daemon runtime is still starting."
|
|
1642
2860
|
};
|
|
2861
|
+
const daemonLogStatus = daemonLog.getStatus();
|
|
2862
|
+
const issues = [issue];
|
|
2863
|
+
if (daemonLogStatus.health === "degraded") {
|
|
2864
|
+
issues.push({
|
|
2865
|
+
code: "daemon_log_degraded",
|
|
2866
|
+
severity: "warning",
|
|
2867
|
+
message: "Daemon file logging is degraded; inspect full status for details."
|
|
2868
|
+
});
|
|
2869
|
+
}
|
|
1643
2870
|
const response = {
|
|
1644
2871
|
v: 1,
|
|
1645
2872
|
detail: detail.detail,
|
|
1646
2873
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1647
2874
|
status: runtimeFailed ? "error" : "warning",
|
|
1648
|
-
issues
|
|
2875
|
+
issues,
|
|
1649
2876
|
daemon: {
|
|
1650
2877
|
pid: process.pid,
|
|
1651
2878
|
uptimeMs: Math.round(process.uptime() * 1e3),
|
|
@@ -1657,7 +2884,15 @@ function createBootstrapServeApp(input) {
|
|
|
1657
2884
|
},
|
|
1658
2885
|
...qwenCodeVersion ? { qwenCodeVersion } : {},
|
|
1659
2886
|
...daemonLog.getDaemonId() ? { daemonId: daemonLog.getDaemonId() } : {},
|
|
1660
|
-
|
|
2887
|
+
runId: daemonLogStatus.runId,
|
|
2888
|
+
logMode: daemonLogStatus.mode,
|
|
2889
|
+
logHealth: daemonLogStatus.health,
|
|
2890
|
+
...detail.detail === "full" && daemonLog.getLogPath() ? { logPath: daemonLog.getLogPath() } : {},
|
|
2891
|
+
...detail.detail === "full" ? {
|
|
2892
|
+
logIssues: daemonLogStatus.issues,
|
|
2893
|
+
logDroppedRecords: daemonLogStatus.droppedRecords,
|
|
2894
|
+
logDroppedBytes: daemonLogStatus.droppedBytes
|
|
2895
|
+
} : {}
|
|
1661
2896
|
},
|
|
1662
2897
|
security: {
|
|
1663
2898
|
tokenConfigured: Boolean(opts.token),
|
|
@@ -1761,7 +2996,7 @@ function createDelegatingServeApp(bootstrapApp, getRuntimeApp, options = {}) {
|
|
|
1761
2996
|
const dispatch = /* @__PURE__ */ __name(async () => {
|
|
1762
2997
|
let target = getRuntimeApp();
|
|
1763
2998
|
if (!target && options.waitForDeferredRuntimeRoutes === true && !isBootstrapServeRoute(req) && !isCorsPreflightRequest(req) && options.startRuntime && options.runtimeReady) {
|
|
1764
|
-
const waitStartedAt =
|
|
2999
|
+
const waitStartedAt = performance2.now();
|
|
1765
3000
|
const timing = {
|
|
1766
3001
|
startedAt: /* @__PURE__ */ new Date(),
|
|
1767
3002
|
path: "joined"
|
|
@@ -1781,7 +3016,7 @@ function createDelegatingServeApp(bootstrapApp, getRuntimeApp, options = {}) {
|
|
|
1781
3016
|
await options.runtimeReady;
|
|
1782
3017
|
} catch {
|
|
1783
3018
|
} finally {
|
|
1784
|
-
timing.waitMs = Math.round((
|
|
3019
|
+
timing.waitMs = Math.round((performance2.now() - waitStartedAt) * 100) / 100;
|
|
1785
3020
|
}
|
|
1786
3021
|
target = getRuntimeApp();
|
|
1787
3022
|
}
|
|
@@ -1894,7 +3129,37 @@ function runSynchronousRequestGate(handler, req, res, next) {
|
|
|
1894
3129
|
}
|
|
1895
3130
|
__name(runSynchronousRequestGate, "runSynchronousRequestGate");
|
|
1896
3131
|
async function runQwenServe(optsIn, deps = {}) {
|
|
1897
|
-
|
|
3132
|
+
let daemonLog;
|
|
3133
|
+
let owner = "startup";
|
|
3134
|
+
try {
|
|
3135
|
+
return await runQwenServeImpl(optsIn, deps, {
|
|
3136
|
+
initialized: /* @__PURE__ */ __name((logger) => {
|
|
3137
|
+
daemonLog = logger;
|
|
3138
|
+
}, "initialized"),
|
|
3139
|
+
published: /* @__PURE__ */ __name(() => {
|
|
3140
|
+
if (owner === "startup") owner = "handle";
|
|
3141
|
+
}, "published"),
|
|
3142
|
+
signalOwned: /* @__PURE__ */ __name(() => {
|
|
3143
|
+
if (owner === "startup") owner = "signal";
|
|
3144
|
+
}, "signalOwned")
|
|
3145
|
+
});
|
|
3146
|
+
} catch (error) {
|
|
3147
|
+
if (daemonLog && owner === "startup") {
|
|
3148
|
+
const startupLog = daemonLog;
|
|
3149
|
+
writeDaemonLifecycleBestEffort(
|
|
3150
|
+
() => startupLog.error(
|
|
3151
|
+
"daemon startup failed",
|
|
3152
|
+
error instanceof Error ? error : new Error(String(error))
|
|
3153
|
+
)
|
|
3154
|
+
);
|
|
3155
|
+
await startupLog.close();
|
|
3156
|
+
}
|
|
3157
|
+
throw error;
|
|
3158
|
+
}
|
|
3159
|
+
}
|
|
3160
|
+
__name(runQwenServe, "runQwenServe");
|
|
3161
|
+
async function runQwenServeImpl(optsIn, deps, loggerLifecycle) {
|
|
3162
|
+
const runStartedAt = performance2.now();
|
|
1898
3163
|
const shouldPreheat = !deps.bridge && shouldPreheatBridge(deps);
|
|
1899
3164
|
const startup = {
|
|
1900
3165
|
processStartedAt: new Date(
|
|
@@ -2160,7 +3425,7 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
2160
3425
|
}
|
|
2161
3426
|
let workspaceRegistrationStore = deps.workspaceRegistrationStore;
|
|
2162
3427
|
if (workspaceRegistrationStore === void 0 && process.env["QWEN_SERVE_NO_PERSISTENT_REGISTRATION"] !== "1") {
|
|
2163
|
-
const { WorkspaceRegistrationStore } = await import("./workspace-registration-store-
|
|
3428
|
+
const { WorkspaceRegistrationStore } = await import("./workspace-registration-store-4I4KL7TN.js");
|
|
2164
3429
|
workspaceRegistrationStore = new WorkspaceRegistrationStore(boundWorkspace);
|
|
2165
3430
|
}
|
|
2166
3431
|
if (workspaceRegistrationStore) {
|
|
@@ -2251,10 +3516,13 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
2251
3516
|
bootSettings,
|
|
2252
3517
|
boundWorkspace
|
|
2253
3518
|
});
|
|
2254
|
-
const daemonLog = initDaemonLogger({
|
|
3519
|
+
const daemonLog = await initDaemonLogger({
|
|
2255
3520
|
boundWorkspace,
|
|
2256
3521
|
baseDir: daemonLogBaseDir
|
|
2257
3522
|
});
|
|
3523
|
+
loggerLifecycle.initialized(daemonLog);
|
|
3524
|
+
let loggerPublished = false;
|
|
3525
|
+
let loggerSignalOwned = false;
|
|
2258
3526
|
writeStderrLine(
|
|
2259
3527
|
`qwen serve: daemon log \u2192 ${daemonLog.getLogPath() || "(disabled)"}`
|
|
2260
3528
|
);
|
|
@@ -3008,7 +4276,7 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
3008
4276
|
);
|
|
3009
4277
|
}
|
|
3010
4278
|
}), "persistSettingsFn");
|
|
3011
|
-
const { createSubSessionLauncher } = await import("./create-sub-session-
|
|
4279
|
+
const { createSubSessionLauncher } = await import("./create-sub-session-BVL2ZHTM.js");
|
|
3012
4280
|
const subSessionLauncher = createSubSessionLauncher({
|
|
3013
4281
|
getBridge: /* @__PURE__ */ __name(() => bridgeRef, "getBridge"),
|
|
3014
4282
|
boundWorkspace
|
|
@@ -4004,7 +5272,7 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
4004
5272
|
startup.listenerReadyAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
4005
5273
|
startup.processToListenMs = Math.round(process.uptime() * 1e3);
|
|
4006
5274
|
startup.runQwenServeToListenMs = Math.round(
|
|
4007
|
-
|
|
5275
|
+
performance2.now() - runStartedAt
|
|
4008
5276
|
);
|
|
4009
5277
|
profileCheckpoint("serve_listener_ready");
|
|
4010
5278
|
finalizeStartupProfile(`serve-${process.pid}`);
|
|
@@ -4340,17 +5608,17 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
4340
5608
|
}, "completeRuntimeStartup");
|
|
4341
5609
|
const startBridgePreheat = /* @__PURE__ */ __name((bridge) => {
|
|
4342
5610
|
startup.preheat.status = "running";
|
|
4343
|
-
const preheatStartedAt =
|
|
5611
|
+
const preheatStartedAt = performance2.now();
|
|
4344
5612
|
bridge.preheat().then(() => {
|
|
4345
5613
|
startup.preheat.status = "succeeded";
|
|
4346
5614
|
startup.preheat.durationMs = Math.round(
|
|
4347
|
-
|
|
5615
|
+
performance2.now() - preheatStartedAt
|
|
4348
5616
|
);
|
|
4349
5617
|
}).catch((err) => {
|
|
4350
5618
|
const message = err instanceof Error ? err.message : String(err);
|
|
4351
5619
|
startup.preheat.status = "failed";
|
|
4352
5620
|
startup.preheat.durationMs = Math.round(
|
|
4353
|
-
|
|
5621
|
+
performance2.now() - preheatStartedAt
|
|
4354
5622
|
);
|
|
4355
5623
|
startup.preheat.error = message;
|
|
4356
5624
|
writeStderrLine(
|
|
@@ -4430,28 +5698,33 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
4430
5698
|
err instanceof Error ? err : null
|
|
4431
5699
|
);
|
|
4432
5700
|
}
|
|
4433
|
-
await
|
|
4434
|
-
|
|
5701
|
+
await flushDaemonLogBounded(
|
|
5702
|
+
daemonLog,
|
|
5703
|
+
DAEMON_LOG_FORCED_FLUSH_BUDGET_MS
|
|
5704
|
+
);
|
|
4435
5705
|
process.exit(1);
|
|
4436
5706
|
return;
|
|
4437
5707
|
}
|
|
5708
|
+
if (!loggerPublished) {
|
|
5709
|
+
loggerSignalOwned = true;
|
|
5710
|
+
loggerLifecycle.signalOwned();
|
|
5711
|
+
}
|
|
4438
5712
|
daemonLog.warn(`received ${signal}, draining`);
|
|
4439
5713
|
try {
|
|
4440
5714
|
await handle.close();
|
|
4441
|
-
await daemonLog.flush();
|
|
4442
5715
|
process.exit(runtimeStartupError === void 0 ? 0 : 1);
|
|
4443
5716
|
} catch (err) {
|
|
4444
5717
|
daemonLog.error("shutdown error", err instanceof Error ? err : null);
|
|
4445
|
-
await daemonLog.flush().catch(() => {
|
|
4446
|
-
});
|
|
4447
5718
|
if (channelWorkerManager?.state().enabled) {
|
|
4448
5719
|
daemonLog.error(
|
|
4449
5720
|
"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)"
|
|
4450
5721
|
);
|
|
4451
|
-
await daemonLog.flush().catch(() => {
|
|
4452
|
-
});
|
|
4453
5722
|
return;
|
|
4454
5723
|
}
|
|
5724
|
+
await flushDaemonLogBounded(
|
|
5725
|
+
daemonLog,
|
|
5726
|
+
DAEMON_LOG_FORCED_FLUSH_BUDGET_MS
|
|
5727
|
+
);
|
|
4455
5728
|
process.exit(1);
|
|
4456
5729
|
}
|
|
4457
5730
|
}, "onSignal");
|
|
@@ -4484,6 +5757,8 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
4484
5757
|
const finish = /* @__PURE__ */ __name((err) => {
|
|
4485
5758
|
if (settled) return;
|
|
4486
5759
|
settled = true;
|
|
5760
|
+
const accessLogController = (runtimeApp ?? runtimeAppForCleanup)?.locals?.[ACCESS_LOG_CONTROLLER_LOCAL];
|
|
5761
|
+
accessLogController?.sealAndFlushSuppressed();
|
|
4487
5762
|
const preserveSignalHandlers = channelWorkerShutdownError !== void 0 && channelWorkerManager?.state().enabled === true;
|
|
4488
5763
|
if (!preserveSignalHandlers) {
|
|
4489
5764
|
process.removeListener("SIGINT", onSignal);
|
|
@@ -4497,19 +5772,28 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
4497
5772
|
writeStderrLine(
|
|
4498
5773
|
`qwen serve: telemetry shutdown error: ${telemetryErr instanceof Error ? telemetryErr.message : String(telemetryErr)}`
|
|
4499
5774
|
);
|
|
4500
|
-
}).finally(
|
|
4501
|
-
})).finally(() => {
|
|
5775
|
+
}).finally(async () => {
|
|
4502
5776
|
const finalErr = err ?? bridgeShutdownError ?? channelWorkerShutdownError;
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
5777
|
+
const retryableChannelClose = channelWorkerShutdownError !== void 0 && channelWorkerManager?.state().enabled === true;
|
|
5778
|
+
if (retryableChannelClose) {
|
|
5779
|
+
await flushDaemonLogBounded(
|
|
5780
|
+
daemonLog,
|
|
5781
|
+
DAEMON_LOG_FORCED_FLUSH_BUDGET_MS
|
|
5782
|
+
);
|
|
5783
|
+
closePromise = void 0;
|
|
5784
|
+
shuttingDown = false;
|
|
5785
|
+
channelControlDraining = false;
|
|
4509
5786
|
rej(finalErr);
|
|
4510
|
-
|
|
4511
|
-
|
|
5787
|
+
return;
|
|
5788
|
+
}
|
|
5789
|
+
if (loggerPublished || loggerSignalOwned) {
|
|
5790
|
+
writeDaemonLifecycleBestEffort(
|
|
5791
|
+
() => daemonLog.info("daemon stopped")
|
|
5792
|
+
);
|
|
5793
|
+
await daemonLog.close();
|
|
4512
5794
|
}
|
|
5795
|
+
if (finalErr) rej(finalErr);
|
|
5796
|
+
else res();
|
|
4513
5797
|
});
|
|
4514
5798
|
}, "finish");
|
|
4515
5799
|
void (coreRuntimePromise ? coreRuntimePromise.then((core) => core.forceFlushMetrics()) : Promise.resolve()).catch((flushErr) => {
|
|
@@ -4638,23 +5922,33 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
4638
5922
|
startRuntime();
|
|
4639
5923
|
}
|
|
4640
5924
|
if (deps.resolveOnListen) {
|
|
5925
|
+
loggerPublished = true;
|
|
5926
|
+
loggerLifecycle.published();
|
|
4641
5927
|
resolve(handle);
|
|
4642
5928
|
} else {
|
|
4643
5929
|
void runtimeReady.then(
|
|
4644
|
-
() =>
|
|
5930
|
+
() => {
|
|
5931
|
+
loggerPublished = true;
|
|
5932
|
+
loggerLifecycle.published();
|
|
5933
|
+
resolve(handle);
|
|
5934
|
+
},
|
|
4645
5935
|
(err) => {
|
|
4646
5936
|
void handle.close().then(
|
|
4647
5937
|
() => {
|
|
4648
5938
|
reject(err instanceof Error ? err : new Error(String(err)));
|
|
4649
5939
|
},
|
|
4650
5940
|
(closeErr) => {
|
|
4651
|
-
|
|
4652
|
-
|
|
4653
|
-
|
|
5941
|
+
writeDaemonLifecycleBestEffort(
|
|
5942
|
+
() => daemonLog.error(
|
|
5943
|
+
"shutdown after runtime startup error failed",
|
|
5944
|
+
closeErr instanceof Error ? closeErr : null
|
|
5945
|
+
)
|
|
4654
5946
|
);
|
|
4655
5947
|
if (channelWorkerManager?.state().enabled) {
|
|
4656
|
-
|
|
4657
|
-
|
|
5948
|
+
writeDaemonLifecycleBestEffort(
|
|
5949
|
+
() => daemonLog.error(
|
|
5950
|
+
"runtime startup failed, but qwen serve remains alive to retain the channel service lease until worker exit is confirmed"
|
|
5951
|
+
)
|
|
4658
5952
|
);
|
|
4659
5953
|
return;
|
|
4660
5954
|
}
|
|
@@ -4714,7 +6008,7 @@ async function runQwenServe(optsIn, deps = {}) {
|
|
|
4714
6008
|
tryListen(opts.port, 0);
|
|
4715
6009
|
});
|
|
4716
6010
|
}
|
|
4717
|
-
__name(
|
|
6011
|
+
__name(runQwenServeImpl, "runQwenServeImpl");
|
|
4718
6012
|
export {
|
|
4719
6013
|
InvalidPolicyConfigError,
|
|
4720
6014
|
createDisabledChannelWorkerSupervisor,
|