@qwen-code/qwen-code 0.21.1 → 0.21.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundled/qc-helper/docs/configuration/settings.md +1 -0
- package/bundled/qc-helper/docs/features/channels/_meta.ts +1 -0
- package/bundled/qc-helper/docs/features/channels/github.md +42 -10
- package/bundled/qc-helper/docs/features/channels/gitlab.md +171 -0
- package/bundled/qc-helper/docs/features/code-review.md +20 -0
- package/bundled/qc-helper/docs/features/hooks.md +20 -0
- package/bundled/qc-helper/docs/features/sub-agents.md +22 -8
- package/bundled/qc-helper/docs/qwen-serve.md +7 -5
- package/bundled/review/SKILL.md +1 -1
- package/chunks/{MaxSizedBox-VI3ROJJA.js → MaxSizedBox-TQBQ247P.js} +42 -38
- package/chunks/{StandaloneSessionPicker-LYXKD2EV.js → StandaloneSessionPicker-2HPTKCLX.js} +58 -54
- package/chunks/{acp-startup-profiler-DFVPFQ6C.js → acp-startup-profiler-2C4A5ZTJ.js} +2 -2
- package/chunks/{acpAgent-WN5SRDQO.js → acpAgent-PS6EDGH3.js} +431 -168
- package/chunks/{agent-K6ECSM64.js → agent-VDOUB35F.js} +38 -34
- package/chunks/{agent-headless-NO4Y2HOE.js → agent-headless-EO53EFS2.js} +38 -34
- package/chunks/{anthropicContentGenerator-V2QOGVYD.js → anthropicContentGenerator-OFHSZJBF.js} +6 -6
- package/chunks/{artifact-tool-6K6U7XYJ.js → artifact-tool-RDN2W7ND.js} +2 -2
- package/chunks/{askUserQuestion-GD2IJJ7I.js → askUserQuestion-OZERWH5R.js} +2 -2
- package/chunks/{bridge-3KJEWDNE.js → bridge-W7AZSRZQ.js} +42 -38
- package/chunks/{build-S6DO7LMM.js → build-GDBLPA24.js} +1 -1
- package/chunks/{channel-management-service-XR7GZSWF.js → channel-management-service-5S7YCWX5.js} +20 -5
- package/chunks/{channel-settings-store-HW4FXXUA.js → channel-settings-store-JFVRSNER.js} +44 -40
- package/chunks/{channel-worker-group-XDPTDWTX.js → channel-worker-group-OVWGYMZS.js} +5 -5
- package/chunks/{channel-worker-manager-YYEHVRRE.js → channel-worker-manager-H55GKOQA.js} +5 -5
- package/chunks/{channel-worker-supervisor-74HTWA2G.js → channel-worker-supervisor-CABBXYHK.js} +3 -3
- package/chunks/{chunk-UWMLWVCA.js → chunk-2IIJTXYF.js} +26 -10
- package/chunks/{chunk-VYOXCEPJ.js → chunk-2KKCCLPT.js} +1 -1
- package/chunks/{chunk-T4TXDL7G.js → chunk-2LEOZTBT.js} +36 -24
- package/chunks/{chunk-XWWKIXVD.js → chunk-3APUUXRF.js} +1 -1
- package/chunks/{chunk-TCIFAA7K.js → chunk-3F2WDAV6.js} +2 -2
- package/chunks/{chunk-SGFT55XI.js → chunk-3I6DUGQD.js} +1 -1
- package/chunks/{chunk-ZURDMIDR.js → chunk-44F4LBWZ.js} +228 -71
- package/chunks/{chunk-GKX7E4CO.js → chunk-45IOTAUS.js} +1 -1
- package/chunks/{chunk-6QIGFD5W.js → chunk-4KP2F2TE.js} +1 -1
- package/chunks/{chunk-X5WNMMIA.js → chunk-54YCNSK5.js} +4241 -1636
- package/chunks/{chunk-P4WOAOJW.js → chunk-56Z7QEAQ.js} +67 -21
- package/chunks/{chunk-UPUG4GXM.js → chunk-5NNHICSA.js} +3 -3
- package/chunks/{chunk-LGAOC3ZS.js → chunk-675H6PLP.js} +1 -1
- package/chunks/{chunk-5KTQXHPY.js → chunk-6CQWRWUC.js} +3 -3
- package/chunks/chunk-6FMJLI5M.js +1591 -0
- package/chunks/{chunk-GZ3RCT54.js → chunk-6MPDY6ZG.js} +1 -1
- package/chunks/{chunk-RCUQIPTN.js → chunk-6PQPKTXP.js} +1 -1
- package/chunks/{chunk-KCO4FLFJ.js → chunk-6TAASXWL.js} +3 -3
- package/chunks/{chunk-JHNRZMHI.js → chunk-77V3VIKL.js} +9 -9
- package/chunks/{chunk-CAPPWD3X.js → chunk-7KAXXBER.js} +3 -3
- package/chunks/{chunk-A4COXFB3.js → chunk-7SJN2IWT.js} +5 -5
- package/chunks/{chunk-Y4IHBGBP.js → chunk-7ULQIS27.js} +1 -1
- package/chunks/{chunk-5MKRTI4T.js → chunk-A7Y5H4TX.js} +4 -4
- package/chunks/{chunk-CVHIL5IG.js → chunk-AOHY3QJ3.js} +13 -6
- package/chunks/chunk-AQ37AY7B.js +93 -0
- package/chunks/{chunk-OCESJA77.js → chunk-AUOULH6Q.js} +45 -45
- package/chunks/{chunk-UBEPNVDI.js → chunk-BBIQAX4V.js} +3 -3
- package/chunks/{chunk-JSD33JG6.js → chunk-CBBP4BMC.js} +23 -9
- package/chunks/{chunk-ZHBO7WVX.js → chunk-CNTR4GR6.js} +1 -1
- package/chunks/{chunk-PB3MBFKG.js → chunk-CO2U743O.js} +4 -4
- package/chunks/{chunk-XZC5VLBZ.js → chunk-CPZAH673.js} +4 -0
- package/chunks/{chunk-T3O2B4XO.js → chunk-CU47KXB5.js} +3 -3
- package/chunks/{chunk-2LKVPASC.js → chunk-D4HTUMGX.js} +3 -3
- package/chunks/{chunk-BNWB5CYE.js → chunk-D6MDRSZ6.js} +7 -7
- package/chunks/{chunk-7BAU433D.js → chunk-DEEABGH2.js} +867 -91
- package/chunks/{chunk-52ZSWYEG.js → chunk-DQ2O5QOJ.js} +1 -1
- package/chunks/{chunk-WBSMNTSV.js → chunk-DSFHVTWD.js} +2 -2
- package/chunks/{chunk-PT722TDT.js → chunk-DUNI4EBW.js} +701 -86
- package/chunks/{chunk-UHUSJ6X7.js → chunk-E2BHWIDT.js} +19 -4
- package/chunks/{chunk-T2QMKU3R.js → chunk-E2FN6SM7.js} +17 -5
- package/chunks/{chunk-W4MIWP6M.js → chunk-E6CJ2SMM.js} +2 -2
- package/chunks/{chunk-5ZF5XXTS.js → chunk-EQNUDTL6.js} +2 -2
- package/chunks/{chunk-2N7CODY5.js → chunk-EU5TBFJI.js} +2 -2
- package/chunks/{chunk-TFRMVU6R.js → chunk-FANRZEAJ.js} +1 -1
- package/chunks/{chunk-WBL3FJEU.js → chunk-FC4KQFCS.js} +1 -1
- package/chunks/{chunk-GNR2RNMP.js → chunk-FCYYAB4S.js} +2 -2
- package/chunks/{chunk-FNMZK765.js → chunk-FJ5WUMUQ.js} +1 -1
- package/chunks/{chunk-J7OACQDE.js → chunk-FNDXMN7I.js} +71 -49
- package/chunks/{chunk-U3E3UQAA.js → chunk-FS674JW4.js} +3 -3
- package/chunks/{chunk-S7W2GKIO.js → chunk-G7XXKQYS.js} +2 -0
- package/chunks/{chunk-VWOOBLTY.js → chunk-GJ2GBPBD.js} +2 -2
- package/chunks/{chunk-TBBV36Y4.js → chunk-GL4JOZXU.js} +4 -4
- package/chunks/{chunk-FTD6DP4T.js → chunk-GURGAJTX.js} +2 -1
- package/chunks/{chunk-65PQENQP.js → chunk-H6I4PGRV.js} +5 -5
- package/chunks/{chunk-7XATOOE7.js → chunk-HC45LTEN.js} +1 -1
- package/chunks/{chunk-VCPIZRYH.js → chunk-HIVKI6O6.js} +7 -7
- package/chunks/{chunk-HMRM2A3U.js → chunk-HX6RLYUO.js} +3 -3
- package/chunks/{chunk-GZXCZHCT.js → chunk-I3G5JWBV.js} +1 -1
- package/chunks/{chunk-2XSLTRFZ.js → chunk-I5BT7ADR.js} +2 -2
- package/chunks/{chunk-GATT5TKW.js → chunk-IGTHU3T4.js} +1 -1
- package/chunks/{chunk-4G2BISNC.js → chunk-IIUGIWWY.js} +1 -1
- package/chunks/{chunk-7I5GTCT4.js → chunk-JCJ7LKNA.js} +5104 -4817
- package/chunks/{chunk-657BH7VM.js → chunk-JE2CEOBO.js} +2 -2
- package/chunks/{chunk-S3TWXGKA.js → chunk-JE7KQ2UP.js} +4 -2
- package/chunks/{chunk-BPZKP57P.js → chunk-JJPKFJBT.js} +3 -3
- package/chunks/{chunk-6PE7N3A4.js → chunk-JLZ3RBQG.js} +7 -5
- package/chunks/{chunk-2LQTH543.js → chunk-JXVC2PL3.js} +2 -2
- package/chunks/{chunk-JCW2R7WC.js → chunk-K623ENWT.js} +3 -79
- package/chunks/{chunk-T2NCM2ET.js → chunk-K6KS3LTN.js} +2 -749
- package/chunks/{chunk-6RPMI2AB.js → chunk-KR32NIAN.js} +6 -6
- package/chunks/{chunk-XBYYDKAZ.js → chunk-KWHKHSIS.js} +8 -7
- package/chunks/{chunk-EVKE2FZL.js → chunk-KXDONCPU.js} +4 -4
- package/chunks/{chunk-5TBMQLGG.js → chunk-L2E5GFAG.js} +2 -2
- package/chunks/{chunk-MHAIJPTD.js → chunk-L32VV3ZJ.js} +12 -12
- package/chunks/{chunk-OKF7JF3R.js → chunk-LHKCY7DY.js} +3 -3
- package/chunks/{chunk-LW3RFMG7.js → chunk-LOY7RWQG.js} +3 -3
- package/chunks/{chunk-AQIDMUGU.js → chunk-LYI2PZDK.js} +1 -1
- package/chunks/{chunk-YGF33UXG.js → chunk-MB32MS4U.js} +12 -3
- package/chunks/{chunk-Y6AXW2OG.js → chunk-MM7TH7ZM.js} +1 -1
- package/chunks/{chunk-2DN4J57Y.js → chunk-N4ACHWNH.js} +1 -1
- package/chunks/{chunk-M7OONWYU.js → chunk-NBD76HUW.js} +4 -2
- package/chunks/{chunk-A2D5BAVP.js → chunk-NHFEMWAZ.js} +1 -1
- package/chunks/{chunk-3EFXSQCM.js → chunk-NTDH4IML.js} +7 -7
- package/chunks/chunk-O6GEWCJA.js +21 -0
- package/chunks/{chunk-7DXQIJID.js → chunk-OFZKFPYG.js} +3 -3
- package/chunks/{chunk-JTV5K7NH.js → chunk-P5VC5USY.js} +1 -1
- package/chunks/{chunk-Q43KPN7X.js → chunk-P755N4CS.js} +3 -3
- package/chunks/{chunk-XFZYFU3I.js → chunk-PCK4B6LR.js} +1 -1
- package/chunks/{chunk-EJGJIBRS.js → chunk-PJOHNFIY.js} +3 -3
- package/chunks/{chunk-WUZ7H6DP.js → chunk-PVNQRENX.js} +1 -1
- package/chunks/{chunk-LO4ROVP4.js → chunk-PZEXDV3H.js} +106 -8
- package/chunks/{chunk-WZRWHXFE.js → chunk-Q3T5KA2V.js} +1 -1
- package/chunks/{chunk-QIZKCVM3.js → chunk-Q5WZTTWE.js} +4 -4
- package/chunks/{chunk-BGTQCTQW.js → chunk-QARJNL2V.js} +3 -3
- package/chunks/{chunk-GXIJHV66.js → chunk-QCXGC7QB.js} +3 -3
- package/chunks/{chunk-DZLYR4U3.js → chunk-QDK4F2N5.js} +1 -1
- package/chunks/{chunk-NOKIVHOL.js → chunk-QTHQ6Z5X.js} +1 -1
- package/chunks/{chunk-A3NDJ5SB.js → chunk-R2XWGR75.js} +2 -2
- package/chunks/{chunk-JX27F6QS.js → chunk-RDJOB6S3.js} +1 -1
- package/chunks/{chunk-TV64SXKD.js → chunk-RG64CDT2.js} +4 -4
- package/chunks/{chunk-JFMA7Y5M.js → chunk-RSVPYAGK.js} +5 -5
- package/chunks/{chunk-64LQLPL7.js → chunk-SHN4KHDK.js} +3 -3
- package/chunks/chunk-T3CHYWJZ.js +758 -0
- package/chunks/{chunk-PONHVBRT.js → chunk-TEGJSJDF.js} +2 -2
- package/chunks/{chunk-75GFAX4R.js → chunk-THVU3RNH.js} +1 -1
- package/chunks/{record-artifact-XAMSFSW4.js → chunk-TIRRPCFS.js} +22 -7
- package/chunks/{chunk-HV26XH34.js → chunk-TTJZAIFP.js} +3 -3
- package/chunks/{chunk-JMONIXMJ.js → chunk-TZTAV5RH.js} +1 -1
- package/chunks/{chunk-7AEJDLRA.js → chunk-UV6KF7T3.js} +2 -2
- package/chunks/{chunk-PLDQBIO6.js → chunk-V25K5ID7.js} +1 -1
- package/chunks/{chunk-S4WJVPZW.js → chunk-V4XNUDPE.js} +3 -3
- package/chunks/{chunk-2FAK6PNM.js → chunk-VEMNQMHA.js} +2 -2
- package/chunks/{chunk-CQL64ESB.js → chunk-VMX5RZQH.js} +12 -10
- package/chunks/{chunk-EIF3FXTB.js → chunk-W3UKBMSI.js} +63 -18
- package/chunks/{chunk-TDL6LB4K.js → chunk-WWCMSZII.js} +21 -9
- package/chunks/{chunk-5YKDXHUY.js → chunk-XP4L6KS3.js} +2 -2
- package/chunks/{chunk-RPLGZJV2.js → chunk-XQK4XXTN.js} +1 -1
- package/chunks/{chunk-KAMYKP7E.js → chunk-XUGZYLDH.js} +1 -1
- package/chunks/{chunk-MR5EAQ5M.js → chunk-YANIWTRZ.js} +1 -1
- package/chunks/{chunk-3L2SPEBH.js → chunk-YGE3IXJP.js} +1 -1
- package/chunks/{chunk-BCZFQXWK.js → chunk-YUFIEIWC.js} +1 -1
- package/chunks/{chunk-75MIQ3LV.js → chunk-Z3S5EMOW.js} +4 -4
- package/chunks/{chunk-BMFALVGQ.js → chunk-ZMOJ7ISP.js} +1 -1
- package/chunks/{chunk-GEBV2JGB.js → chunk-ZPZ7ZJEE.js} +1 -1
- package/chunks/{computer-use-ZTIDHMMA.js → computer-use-5QWCFNKD.js} +38 -34
- package/chunks/{config-utils-NYSXDMEQ.js → config-utils-WADIDWGG.js} +4 -4
- package/chunks/{contextCommand-2PIEU37Z.js → contextCommand-4Z7T7TUM.js} +40 -36
- package/chunks/{core-runtime-3XEYLQFK.js → core-runtime-6N4EFC2Q.js} +38 -34
- package/chunks/{create-sub-session-SBYUMSSS.js → create-sub-session-62YZWVAY.js} +2 -2
- package/chunks/{create-sub-session-R76FVXCI.js → create-sub-session-AEREHZBQ.js} +38 -34
- package/chunks/{cron-create-2QK6TCEC.js → cron-create-6E7GIQTG.js} +4 -4
- package/chunks/{cron-delete-FDCDFYMG.js → cron-delete-JD26XY3W.js} +4 -4
- package/chunks/{cron-list-XN3WVBTP.js → cron-list-CUWFB44G.js} +4 -4
- package/chunks/{daemon-Q2AB5Z23.js → daemon-PCNCI5YU.js} +72 -3
- package/chunks/{daemon-status-provider-3XJI6CAL.js → daemon-status-provider-DDF7C5M7.js} +46 -42
- package/chunks/{daemon-trust-policy-ILUDTLHD.js → daemon-trust-policy-Q4KSOJTR.js} +43 -39
- package/chunks/{daemon-trust-policy-monitor-HS3PKKRO.js → daemon-trust-policy-monitor-V6FTE3IY.js} +43 -39
- package/chunks/{deferred-core-runtime-X4QV662U.js → deferred-core-runtime-GHJ5GQHK.js} +38 -34
- package/chunks/{dist-BSTVRPMT.js → dist-26BIMQT6.js} +276 -16
- package/chunks/{dist-SV7Q3AWJ.js → dist-2PERFI23.js} +12 -9
- package/chunks/{dist-DOLYHMXE.js → dist-OAOC5OV4.js} +2 -2
- package/chunks/{dist-YGBBMK3Z.js → dist-PVEAFLHY.js} +5 -4
- package/chunks/{dist-HVRQ2CFL.js → dist-SL2LUMML.js} +1180 -5
- package/chunks/dist-ULIG4M5H.js +13415 -0
- package/chunks/{dist-IXQEQWRG.js → dist-WGMNT3JQ.js} +1 -1
- package/chunks/{dist-SSU66DM4.js → dist-ZHXOBXDN.js} +1 -1
- package/chunks/{earlyInputCapture-XKLZT7ZD.js → earlyInputCapture-TQXLLISD.js} +39 -35
- package/chunks/{edit-HHGIOTQ2.js → edit-FJEUV6KZ.js} +38 -34
- package/chunks/{enter-worktree-ZN7PUQ46.js → enter-worktree-7GE3TZ4P.js} +38 -34
- package/chunks/{enterPlanMode-EIFIDSIV.js → enterPlanMode-KR5TMPCJ.js} +38 -34
- package/chunks/{environment-XXQ75D2Q.js → environment-SWL3CMB3.js} +40 -36
- package/chunks/{errors-4GMVU7CK.js → errors-XQE7BGZV.js} +40 -36
- package/chunks/{exit-worktree-GXMI4ATY.js → exit-worktree-CHKTYNCV.js} +38 -34
- package/chunks/{exitPlanMode-34UVY7M6.js → exitPlanMode-QYAG6LWX.js} +38 -34
- package/chunks/{fast-path-VPIVA7L6.js → fast-path-Z2K7W6DC.js} +2 -2
- package/chunks/{gemini-4BWIK4WD.js → gemini-YU4XKEDG.js} +91 -87
- package/chunks/{geminiContentGenerator-3XVV5MSS.js → geminiContentGenerator-ZZX6NBO4.js} +6 -6
- package/chunks/{glob-TZ2ABCJG.js → glob-VYF5CXSX.js} +38 -34
- package/chunks/goal-tools-HGO6VXPB.js +335 -0
- package/chunks/{grep-BEF463NA.js → grep-5DP5ZUTW.js} +38 -34
- package/chunks/{handleAutoUpdate-L6ERF36Y.js → handleAutoUpdate-UVBJ56DL.js} +42 -38
- package/chunks/{i18n-FMM5FDXR.js → i18n-UQNYHEUD.js} +39 -35
- package/chunks/{image-gen-HHVLF7HS.js → image-gen-WHPIZNWF.js} +9 -9
- package/chunks/{initializer-625TIAIO.js → initializer-GMIICF4W.js} +44 -40
- package/chunks/{installationInfo-6AM4I2Y3.js → installationInfo-4MGG4WVI.js} +39 -35
- package/chunks/{keychain-token-storage-72IYCAZV.js → keychain-token-storage-IKO4G53C.js} +2 -2
- package/chunks/list-CPN2W334.js +92 -0
- package/chunks/{list-agents-R6KDXQR3.js → list-agents-PXJ7ZUFB.js} +2 -2
- package/chunks/{loadedSettingsAdapter-SPUTNKAV.js → loadedSettingsAdapter-ZQAV5NDO.js} +43 -39
- package/chunks/{loggingContentGenerator-LKOF7XI7.js → loggingContentGenerator-5E7W4IEP.js} +18 -18
- package/chunks/{loop-wakeup-3IQKCYAH.js → loop-wakeup-Y26NQZ5I.js} +13 -6
- package/chunks/{ls-DKZ37A7N.js → ls-ONQTTMQR.js} +4 -4
- package/chunks/{lsp-QNWN7KN3.js → lsp-YGHHRGMD.js} +2 -2
- package/chunks/{managed-npm-update-ACQGGIN5.js → managed-npm-update-MKKAXYXA.js} +39 -35
- package/chunks/{mcp-SZLHKFJW.js → mcp-V5NTJF6X.js} +43 -39
- package/chunks/{monitor-DF52UVHI.js → monitor-CO3ASY6E.js} +38 -34
- package/chunks/nonInteractiveCli-ZJYEOO7U.js +148 -0
- package/chunks/{notebook-edit-FCWS4XVN.js → notebook-edit-Z7AEE6FM.js} +38 -34
- package/chunks/{openaiContentGenerator-7LDK3DCJ.js → openaiContentGenerator-CA3MQOP3.js} +19 -19
- package/chunks/{pidfile-6ERW3DF4.js → pidfile-NL7MKDRU.js} +39 -35
- package/chunks/{processUtils-COKZAMUP.js → processUtils-PB5K2DYH.js} +2 -2
- package/chunks/{qwenContentGenerator-TKWUMR7N.js → qwenContentGenerator-JYFNDCOS.js} +44 -40
- package/chunks/{qwenOAuth2-7HMU47SF.js → qwenOAuth2-W2ALKQDD.js} +8 -8
- package/chunks/{read-file-X6DRC574.js → read-file-IEOR5H5W.js} +11 -11
- package/chunks/{read-mcp-resource-GFTWYXMK.js → read-mcp-resource-U2IJN5HM.js} +2 -2
- package/chunks/record-artifact-MGPJ7EG4.js +21 -0
- package/chunks/{resumeHistoryUtils-PFPM2GWM.js → resumeHistoryUtils-BNBTP5AS.js} +44 -40
- package/chunks/{ripGrep-OWV2IVJC.js → ripGrep-UMQODKEB.js} +38 -34
- package/chunks/{run-qwen-serve-TSTCO4XE.js → run-qwen-serve-RN2R6QQW.js} +116 -65
- package/chunks/{runtime-DAUPSUKI.js → runtime-QFJ2MJF5.js} +48 -44
- package/chunks/{scheduler-KMADMT26.js → scheduler-AMYUFOZI.js} +38 -34
- package/chunks/{sdk-exporters-http-WO556XNU.js → sdk-exporters-http-4BQANSJ6.js} +3 -3
- package/chunks/{sdk-impl-LPAVACSF.js → sdk-impl-Z4VXWVFX.js} +3 -3
- package/chunks/{send-message-SAWK4DZX.js → send-message-PMP4ATVM.js} +6 -11
- package/chunks/{serve-NNRWS6F4.js → serve-EIIYJVX3.js} +43 -39
- package/chunks/{server-WEH7DVCH.js → server-EP2LLAPD.js} +1768 -712
- package/chunks/{session-WXC56V2I.js → session-GMPZBLOW.js} +83 -79
- package/chunks/{settings-DJDXFDZ3.js → settings-LN7RNKBS.js} +47 -43
- package/chunks/{shell-JN5VRQXD.js → shell-EM2OWU5X.js} +38 -34
- package/chunks/{skill-SGXPKJCS.js → skill-T5VPSK73.js} +17 -16
- package/chunks/{skill-settings-VJ5PDMZI.js → skill-settings-GMR3GMNY.js} +42 -38
- package/chunks/{spawnChannel-ETMJW7YX.js → spawnChannel-YPCU62DI.js} +40 -36
- package/chunks/{standalone-update-MK3Z7KBI.js → standalone-update-JAKIM2NF.js} +40 -36
- package/chunks/{startInteractiveUI-ZCGIXPGT.js → startInteractiveUI-YETQWGYF.js} +774 -779
- package/chunks/{syntheticOutput-355CB6CJ.js → syntheticOutput-D7E6ZFKR.js} +3 -3
- package/chunks/{task-create-INGWNUG4.js → task-create-NFCYD43L.js} +10 -9
- package/chunks/{task-list-5XNNGTF4.js → task-list-TAVMGEVD.js} +5 -5
- package/chunks/{task-stop-4ROAOBXH.js → task-stop-ZDF2UJRM.js} +2 -2
- package/chunks/{task-update-CRK5VWWZ.js → task-update-6L7LHGEX.js} +10 -9
- package/chunks/{team-create-QQGAJG7P.js → team-create-LFJ6HGNY.js} +38 -34
- package/chunks/{team-delete-S2RCXA4P.js → team-delete-DPGGRQBU.js} +5 -5
- package/chunks/{team-plan-approval-RT7Q5R6O.js → team-plan-approval-C2KLSDGO.js} +38 -34
- package/chunks/{theme-manager-EEWIQJ7J.js → theme-manager-JQ3ZGBP5.js} +39 -35
- package/chunks/{todoWrite-7WM3VDMY.js → todoWrite-2UO5G6G6.js} +32 -4
- package/chunks/{tool-search-Z3Z4AYKP.js → tool-search-FAZBFRJZ.js} +15 -14
- package/chunks/{total-session-admission-44JKRWQD.js → total-session-admission-5CALIVYO.js} +42 -38
- package/chunks/{trustedFolders-X2JEIO57.js → trustedFolders-KOPSP44S.js} +39 -35
- package/chunks/{update-relaunch-VWNPYDIP.js → update-relaunch-6QL2TICS.js} +5 -5
- package/chunks/{updateCheck-KAQH67DV.js → updateCheck-4Q6RIKFW.js} +41 -37
- package/chunks/{useAutoAcceptIndicator-JH6BCF7S.js → useAutoAcceptIndicator-Q5BMKZV3.js} +47 -43
- package/chunks/{validateNonInterActiveAuth-GIUJ2UFS.js → validateNonInterActiveAuth-GKOC5F6Z.js} +79 -75
- package/chunks/{version-BGLYIJUY.js → version-VSATY2LD.js} +1 -1
- package/chunks/{web-fetch-OTDU4VQF.js → web-fetch-JCLKL6NL.js} +14 -14
- package/chunks/{web-search-FP6SIHPR.js → web-search-DSQTFUBX.js} +8 -8
- package/chunks/{workflow-YCIVBYSB.js → workflow-M6QAVKVJ.js} +41 -37
- package/chunks/workspace-providers-status-YKLTLMJA.js +89 -0
- package/chunks/{workspace-registration-store-OTMS3H4C.js → workspace-registration-store-5DMGKU64.js} +1 -1
- package/chunks/{workspace-registry-O63R6IZ4.js → workspace-registry-PTYUSYXX.js} +42 -38
- package/chunks/{workspace-service-M6LLHKJ5.js → workspace-service-25ML3T47.js} +48 -44
- package/chunks/{workspace-skills-status-C2V7BAIS.js → workspace-skills-status-YKZWOYRX.js} +44 -40
- package/chunks/{workspace-trust-reconciler-IBUPOUJN.js → workspace-trust-reconciler-5FI2S3OS.js} +47 -43
- package/chunks/write-file-AY7VLP5X.js +78 -0
- package/chunks/zoom-image-S4LJZMD5.js +224 -0
- package/cli.js +50 -16
- package/package.json +3 -3
- package/web-shell/assets/{arc-75-Wdeo3.js → arc-xjArKHU2.js} +1 -1
- package/web-shell/assets/{architectureDiagram-3BPJPVTR-FKeXQbyP.js → architectureDiagram-3BPJPVTR-BgrQDNYG.js} +1 -1
- package/web-shell/assets/{blockDiagram-GPEHLZMM-CY0vc-A3.js → blockDiagram-GPEHLZMM-CXxWC-1_.js} +1 -1
- package/web-shell/assets/{c4Diagram-AAUBKEIU-CNP-A-8u.js → c4Diagram-AAUBKEIU-Dx1tLm3v.js} +1 -1
- package/web-shell/assets/channel-B1cyk94G.js +1 -0
- package/web-shell/assets/{chunk-2J33WTMH-GybS4Gii.js → chunk-2J33WTMH-CBxjogVR.js} +1 -1
- package/web-shell/assets/{chunk-4BX2VUAB-02H91V8v.js → chunk-4BX2VUAB-izb-rY5W.js} +1 -1
- package/web-shell/assets/{chunk-55IACEB6-D3M-2VT6.js → chunk-55IACEB6-NzLyvSb8.js} +1 -1
- package/web-shell/assets/{chunk-727SXJPM-CCu29u4H.js → chunk-727SXJPM-DVyKb0dl.js} +1 -1
- package/web-shell/assets/{chunk-AQP2D5EJ-CaFKWgrn.js → chunk-AQP2D5EJ-BtqL7NzB.js} +1 -1
- package/web-shell/assets/{chunk-FMBD7UC4-ZZpPqIwQ.js → chunk-FMBD7UC4-iNpdKIO0.js} +1 -1
- package/web-shell/assets/{chunk-ND2GUHAM-D22DqGs8.js → chunk-ND2GUHAM-DI7cbFmX.js} +1 -1
- package/web-shell/assets/{chunk-QZHKN3VN-Bu85S0fw.js → chunk-QZHKN3VN-3Y_-xFYs.js} +1 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-BpBYZoRE.js +1 -0
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-BpBYZoRE.js +1 -0
- package/web-shell/assets/{cose-bilkent-S5V4N54A-f1CK1Gwe.js → cose-bilkent-S5V4N54A--raRatZn.js} +1 -1
- package/web-shell/assets/{dagre-BM42HDAG-D0Ow8F_n.js → dagre-BM42HDAG-B8SU70mO.js} +1 -1
- package/web-shell/assets/{diagram-2AECGRRQ-BPrmTWp8.js → diagram-2AECGRRQ-ewgoakXo.js} +1 -1
- package/web-shell/assets/{diagram-5GNKFQAL-HccuFAzy.js → diagram-5GNKFQAL-Bm_JLTnS.js} +1 -1
- package/web-shell/assets/{diagram-KO2AKTUF-BrS76mbA.js → diagram-KO2AKTUF-DEIUjUy9.js} +1 -1
- package/web-shell/assets/{diagram-LMA3HP47-V7T9lU-5.js → diagram-LMA3HP47-C2Wmrpj-.js} +1 -1
- package/web-shell/assets/{diagram-OG6HWLK6-DKidyJMR.js → diagram-OG6HWLK6-CtYe6bFx.js} +1 -1
- package/web-shell/assets/{erDiagram-TEJ5UH35-DBadZIkp.js → erDiagram-TEJ5UH35-DfpHcWLV.js} +1 -1
- package/web-shell/assets/{flowDiagram-I6XJVG4X-BymfqdNJ.js → flowDiagram-I6XJVG4X-CAiUhio5.js} +1 -1
- package/web-shell/assets/{ganttDiagram-6RSMTGT7-DOw340jf.js → ganttDiagram-6RSMTGT7-CYc7ezr4.js} +1 -1
- package/web-shell/assets/{gitGraphDiagram-PVQCEYII-_8EiD8sl.js → gitGraphDiagram-PVQCEYII-70lbkcRS.js} +1 -1
- package/web-shell/assets/index-C1k3PDuU.css +5 -0
- package/web-shell/assets/index-C2GE3DAF.js +74 -0
- package/web-shell/assets/index-DZLIXILO.js +1750 -0
- package/web-shell/assets/{index-CKIadvET.js → index-Ww86nT9f.js} +1 -1
- package/web-shell/assets/{infoDiagram-5YYISTIA-D61KYQBu.js → infoDiagram-5YYISTIA-C7e8DWPa.js} +1 -1
- package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-CsiXSpNx.js → ishikawaDiagram-YF4QCWOH-BYLr2op-.js} +1 -1
- package/web-shell/assets/{journeyDiagram-JHISSGLW-Sdfionyh.js → journeyDiagram-JHISSGLW-hEibAHKX.js} +1 -1
- package/web-shell/assets/{kanban-definition-UN3LZRKU-C3WI3Cnl.js → kanban-definition-UN3LZRKU-F2rt8Uhp.js} +1 -1
- package/web-shell/assets/{linear-Dpigcc62.js → linear-DPhyNezd.js} +1 -1
- package/web-shell/assets/{mermaid.core-Ct97pqgW.js → mermaid.core-ZUtnug0n.js} +5 -5
- package/web-shell/assets/{mindmap-definition-RKZ34NQL-BzeaN0rB.js → mindmap-definition-RKZ34NQL-DDWcMoi8.js} +1 -1
- package/web-shell/assets/{pieDiagram-4H26LBE5-CvjgcbVD.js → pieDiagram-4H26LBE5-CTRKzw1_.js} +1 -1
- package/web-shell/assets/{quadrantDiagram-W4KKPZXB-BUzgTNdH.js → quadrantDiagram-W4KKPZXB-CAEwYG_z.js} +1 -1
- package/web-shell/assets/{requirementDiagram-4Y6WPE33-B7zKlgUQ.js → requirementDiagram-4Y6WPE33-CRjnH9D9.js} +1 -1
- package/web-shell/assets/{sankeyDiagram-5OEKKPKP-Bb9CQgrT.js → sankeyDiagram-5OEKKPKP-LPQT_sOd.js} +1 -1
- package/web-shell/assets/{sequenceDiagram-3UESZ5HK-DJ6V7itG.js → sequenceDiagram-3UESZ5HK-Ht2Iqvb0.js} +1 -1
- package/web-shell/assets/{stateDiagram-AJRCARHV-IImflERY.js → stateDiagram-AJRCARHV-CIUdqOXu.js} +1 -1
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-BmqqQZ6w.js +1 -0
- package/web-shell/assets/{timeline-definition-PNZ67QCA-6Q_uWHKh.js → timeline-definition-PNZ67QCA-BcilneZF.js} +1 -1
- package/web-shell/assets/{vennDiagram-CIIHVFJN-TmyKyjwv.js → vennDiagram-CIIHVFJN-BljwiiH1.js} +1 -1
- package/web-shell/assets/{wardley-L42UT6IY-CRh9uiPv.js → wardley-L42UT6IY-DeKjkYjq.js} +1 -1
- package/web-shell/assets/{wardleyDiagram-YWT4CUSO-59TKAW8w.js → wardleyDiagram-YWT4CUSO-L3U1H7KG.js} +1 -1
- package/web-shell/assets/{xychartDiagram-2RQKCTM6-GCSUIK2L.js → xychartDiagram-2RQKCTM6-IJnWsgMT.js} +1 -1
- package/web-shell/index.html +2 -2
- package/chunks/list-L2GA674Y.js +0 -88
- package/chunks/nonInteractiveCli-5T7KYKLK.js +0 -144
- package/chunks/workspace-providers-status-S35YAIUS.js +0 -85
- package/chunks/write-file-3BZC3EAE.js +0 -72
- package/chunks/zoom-image-TZ6S2O57.js +0 -351
- package/web-shell/assets/channel-DPYMT76A.js +0 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK--JstsIgL.js +0 -1
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2--JstsIgL.js +0 -1
- package/web-shell/assets/index-D1eXNRHe.js +0 -1389
- package/web-shell/assets/index-DVLD4CQq.css +0 -5
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-CYI_YoNR.js +0 -1
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
// Force strict mode and setup for ESM
|
|
2
2
|
"use strict";
|
|
3
|
-
import {
|
|
4
|
-
openQwenAsrRealtimeStream,
|
|
5
|
-
openVoiceStream,
|
|
6
|
-
openVoiceStreamWithRetry
|
|
7
|
-
} from "./chunk-BCZFQXWK.js";
|
|
8
3
|
import {
|
|
9
4
|
GENERATION_MAX_PROMPT_BYTES,
|
|
10
5
|
MAX_REMEMBER_CONTENT_BYTES,
|
|
@@ -21,7 +16,12 @@ import {
|
|
|
21
16
|
shouldSuppressRememberErrorDetails,
|
|
22
17
|
workspaceMemoryFailureCode,
|
|
23
18
|
workspaceMemoryFailureDiagnostics
|
|
24
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-JLZ3RBQG.js";
|
|
20
|
+
import {
|
|
21
|
+
openQwenAsrRealtimeStream,
|
|
22
|
+
openVoiceStream,
|
|
23
|
+
openVoiceStreamWithRetry
|
|
24
|
+
} from "./chunk-YUFIEIWC.js";
|
|
25
25
|
import {
|
|
26
26
|
SetupGithubError,
|
|
27
27
|
collectSessionData,
|
|
@@ -33,13 +33,13 @@ import {
|
|
|
33
33
|
toJson,
|
|
34
34
|
toJsonl,
|
|
35
35
|
toMarkdown
|
|
36
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-PZEXDV3H.js";
|
|
37
37
|
import {
|
|
38
38
|
OBSERVED_CONTACT_MAX_FRESH_WITHIN_SECONDS,
|
|
39
39
|
ObservedChannelContactStore
|
|
40
|
-
} from "./chunk-
|
|
41
|
-
import "./chunk-XFZYFU3I.js";
|
|
40
|
+
} from "./chunk-675H6PLP.js";
|
|
42
41
|
import "./chunk-YDLJGZHL.js";
|
|
42
|
+
import "./chunk-PCK4B6LR.js";
|
|
43
43
|
import "./chunk-2MIN6GRR.js";
|
|
44
44
|
import "./chunk-QHTIBUWB.js";
|
|
45
45
|
import "./chunk-QTERJVPZ.js";
|
|
@@ -101,14 +101,18 @@ import {
|
|
|
101
101
|
setRateLimiter,
|
|
102
102
|
unsafeRevealSecret,
|
|
103
103
|
validateMcpRuntimeServerName
|
|
104
|
-
} from "./chunk-
|
|
104
|
+
} from "./chunk-MB32MS4U.js";
|
|
105
105
|
import {
|
|
106
106
|
isLoopbackBind
|
|
107
107
|
} from "./chunk-RXFQM6FQ.js";
|
|
108
|
+
import {
|
|
109
|
+
createWorkspaceSkillsStatusProvider
|
|
110
|
+
} from "./chunk-BBIQAX4V.js";
|
|
111
|
+
import "./chunk-L55JWS76.js";
|
|
108
112
|
import {
|
|
109
113
|
evaluateDaemonWorkspaceTrust,
|
|
110
114
|
readDaemonTrustPolicySnapshot
|
|
111
|
-
} from "./chunk-
|
|
115
|
+
} from "./chunk-TTJZAIFP.js";
|
|
112
116
|
import {
|
|
113
117
|
EMPTY_WORKSPACE_VOICE_UPDATE_ERROR,
|
|
114
118
|
MAX_WORKSPACE_SKILL_NAME_LENGTH,
|
|
@@ -122,14 +126,14 @@ import {
|
|
|
122
126
|
validateWorkspaceSkillName,
|
|
123
127
|
validateWorkspaceVoiceState,
|
|
124
128
|
voiceSettingsScopeToWire
|
|
125
|
-
} from "./chunk-
|
|
129
|
+
} from "./chunk-56Z7QEAQ.js";
|
|
126
130
|
import {
|
|
127
131
|
PermissionRulesValidationError,
|
|
128
132
|
buildPermissionSettings,
|
|
129
133
|
isPermissionRuleType,
|
|
130
134
|
normalizePermissionRules,
|
|
131
135
|
readPermissionRuleSet
|
|
132
|
-
} from "./chunk-
|
|
136
|
+
} from "./chunk-YANIWTRZ.js";
|
|
133
137
|
import {
|
|
134
138
|
assertVoiceBaseUrlNetworkAllowed,
|
|
135
139
|
isStreamingVoiceModel,
|
|
@@ -137,13 +141,13 @@ import {
|
|
|
137
141
|
resolveVoiceTranscriptionConfig,
|
|
138
142
|
sanitizeVoiceErrorMessage,
|
|
139
143
|
transcribeVoiceAudio
|
|
140
|
-
} from "./chunk-
|
|
144
|
+
} from "./chunk-7KAXXBER.js";
|
|
141
145
|
import {
|
|
142
146
|
isVoiceEnabled,
|
|
143
147
|
isVoiceMode,
|
|
144
148
|
readVoiceModel
|
|
145
|
-
} from "./chunk-
|
|
146
|
-
import "./chunk-
|
|
149
|
+
} from "./chunk-P5VC5USY.js";
|
|
150
|
+
import "./chunk-CNTR4GR6.js";
|
|
147
151
|
import {
|
|
148
152
|
WorkspacePermissionRulesSessionRequiredError,
|
|
149
153
|
WorkspaceSettingsPartialPersistError,
|
|
@@ -161,19 +165,19 @@ import {
|
|
|
161
165
|
import "./chunk-GRC5HGPI.js";
|
|
162
166
|
import {
|
|
163
167
|
assertValidChannelSecretUpdates
|
|
164
|
-
} from "./chunk-
|
|
168
|
+
} from "./chunk-EQNUDTL6.js";
|
|
165
169
|
import {
|
|
166
170
|
createDaemonStatusProvider
|
|
167
|
-
} from "./chunk-
|
|
171
|
+
} from "./chunk-GL4JOZXU.js";
|
|
168
172
|
import "./chunk-VXZBKKQR.js";
|
|
169
|
-
import "./chunk-
|
|
173
|
+
import "./chunk-Q5WZTTWE.js";
|
|
170
174
|
import "./chunk-E5Z2AVNV.js";
|
|
171
175
|
import {
|
|
172
176
|
SessionArtifactAuthorizationError,
|
|
173
177
|
SessionArtifactValidationError,
|
|
174
178
|
createAcpSessionBridge,
|
|
175
179
|
parseSessionSource
|
|
176
|
-
} from "./chunk-
|
|
180
|
+
} from "./chunk-44F4LBWZ.js";
|
|
177
181
|
import {
|
|
178
182
|
EVENT_SCHEMA_VERSION,
|
|
179
183
|
EventBus,
|
|
@@ -181,41 +185,37 @@ import {
|
|
|
181
185
|
} from "./chunk-GLWP3FDB.js";
|
|
182
186
|
import "./chunk-XCGIMOLN.js";
|
|
183
187
|
import "./chunk-OCPBI7J5.js";
|
|
184
|
-
import "./chunk-
|
|
188
|
+
import "./chunk-XUGZYLDH.js";
|
|
185
189
|
import {
|
|
186
190
|
createWorkspaceProvidersStatusProvider
|
|
187
|
-
} from "./chunk-
|
|
191
|
+
} from "./chunk-NTDH4IML.js";
|
|
188
192
|
import {
|
|
189
193
|
getAuthTypeFromEnv,
|
|
190
194
|
resolveCliGenerationConfig
|
|
191
|
-
} from "./chunk-
|
|
195
|
+
} from "./chunk-6TAASXWL.js";
|
|
192
196
|
import {
|
|
193
197
|
snapshotProcessEnv
|
|
194
|
-
} from "./chunk-
|
|
195
|
-
import {
|
|
196
|
-
createWorkspaceSkillsStatusProvider
|
|
197
|
-
} from "./chunk-UBEPNVDI.js";
|
|
198
|
-
import "./chunk-L55JWS76.js";
|
|
198
|
+
} from "./chunk-VEMNQMHA.js";
|
|
199
199
|
import {
|
|
200
200
|
STATUS_SCHEMA_VERSION,
|
|
201
201
|
createIdleWorkspaceMemoryStatus,
|
|
202
202
|
mapDomainErrorToErrorKind
|
|
203
|
-
} from "./chunk-
|
|
203
|
+
} from "./chunk-GURGAJTX.js";
|
|
204
204
|
import "./chunk-Z4X5MTRT.js";
|
|
205
|
-
import "./chunk-
|
|
205
|
+
import "./chunk-FC4KQFCS.js";
|
|
206
206
|
import {
|
|
207
207
|
daemonObservedContactsPath,
|
|
208
208
|
loadChannelsConfig
|
|
209
|
-
} from "./chunk-
|
|
210
|
-
import "./chunk-
|
|
209
|
+
} from "./chunk-D6MDRSZ6.js";
|
|
210
|
+
import "./chunk-A7Y5H4TX.js";
|
|
211
211
|
import "./chunk-57OAHC2Y.js";
|
|
212
212
|
import {
|
|
213
213
|
parseChannelWebhookConfigLenient
|
|
214
|
-
} from "./chunk-
|
|
215
|
-
import "./chunk-
|
|
214
|
+
} from "./chunk-I5BT7ADR.js";
|
|
215
|
+
import "./chunk-FANRZEAJ.js";
|
|
216
216
|
import {
|
|
217
217
|
supportedChannelCatalog
|
|
218
|
-
} from "./chunk-
|
|
218
|
+
} from "./chunk-KWHKHSIS.js";
|
|
219
219
|
import "./chunk-V6WHFGST.js";
|
|
220
220
|
import {
|
|
221
221
|
MAX_REGISTERED_WORKSPACES,
|
|
@@ -224,8 +224,8 @@ import {
|
|
|
224
224
|
WorkspaceRegistrationStoreLimitError,
|
|
225
225
|
normalizeWorkspaceDisplayName,
|
|
226
226
|
workspaceRegistrationId
|
|
227
|
-
} from "./chunk-
|
|
228
|
-
import "./chunk-
|
|
227
|
+
} from "./chunk-LYI2PZDK.js";
|
|
228
|
+
import "./chunk-CPZAH673.js";
|
|
229
229
|
import {
|
|
230
230
|
BranchWhilePromptActiveError,
|
|
231
231
|
CancelSentinelCollisionError,
|
|
@@ -277,7 +277,7 @@ import {
|
|
|
277
277
|
} from "./chunk-U4VTUMMK.js";
|
|
278
278
|
import {
|
|
279
279
|
normalizeWorkerDiagnostic
|
|
280
|
-
} from "./chunk-
|
|
280
|
+
} from "./chunk-6MPDY6ZG.js";
|
|
281
281
|
import {
|
|
282
282
|
normalizeServeChannelSelection
|
|
283
283
|
} from "./chunk-ALMR3E6Q.js";
|
|
@@ -286,10 +286,11 @@ import {
|
|
|
286
286
|
redactLogCredentials
|
|
287
287
|
} from "./chunk-M5GB774H.js";
|
|
288
288
|
import "./chunk-5HBA2Z7V.js";
|
|
289
|
-
import "./chunk-
|
|
289
|
+
import "./chunk-K6KS3LTN.js";
|
|
290
|
+
import "./chunk-T3CHYWJZ.js";
|
|
290
291
|
import {
|
|
291
292
|
sanitizeLogText
|
|
292
|
-
} from "./chunk-
|
|
293
|
+
} from "./chunk-JCJ7LKNA.js";
|
|
293
294
|
import "./chunk-UDXSXLER.js";
|
|
294
295
|
import {
|
|
295
296
|
getDialogSettingKeys,
|
|
@@ -300,27 +301,27 @@ import {
|
|
|
300
301
|
getWritableScopes,
|
|
301
302
|
loadSettings,
|
|
302
303
|
validateSettingValue
|
|
303
|
-
} from "./chunk-
|
|
304
|
+
} from "./chunk-W3UKBMSI.js";
|
|
304
305
|
import "./chunk-RKUWKYED.js";
|
|
306
|
+
import "./chunk-GOXKNSDZ.js";
|
|
307
|
+
import "./chunk-IDS7MSUP.js";
|
|
305
308
|
import {
|
|
306
309
|
SUPPORTED_LANGUAGES,
|
|
307
310
|
detectSystemLanguage,
|
|
308
311
|
resolveLanguageSetting,
|
|
309
312
|
resolveSupportedLanguage
|
|
310
|
-
} from "./chunk-
|
|
311
|
-
import "./chunk-
|
|
312
|
-
import "./chunk-GOXKNSDZ.js";
|
|
313
|
-
import "./chunk-IDS7MSUP.js";
|
|
313
|
+
} from "./chunk-3F2WDAV6.js";
|
|
314
|
+
import "./chunk-EU5TBFJI.js";
|
|
314
315
|
import "./chunk-6PEXNQTX.js";
|
|
315
|
-
import "./chunk-VYOXCEPJ.js";
|
|
316
|
-
import "./chunk-VJNBRRZG.js";
|
|
317
316
|
import {
|
|
318
317
|
getWorkspaceTrustStatus
|
|
319
|
-
} from "./chunk-
|
|
318
|
+
} from "./chunk-P755N4CS.js";
|
|
320
319
|
import "./chunk-ALGGS7UH.js";
|
|
321
320
|
import {
|
|
322
321
|
isWithinRoot as isWithinRoot2
|
|
323
322
|
} from "./chunk-MR3PXB6E.js";
|
|
323
|
+
import "./chunk-2KKCCLPT.js";
|
|
324
|
+
import "./chunk-VJNBRRZG.js";
|
|
324
325
|
import {
|
|
325
326
|
writeStderrLine,
|
|
326
327
|
writeStderrLineSafe
|
|
@@ -398,19 +399,20 @@ import {
|
|
|
398
399
|
writeWorkspaceContextFile,
|
|
399
400
|
writeWorktreeSession,
|
|
400
401
|
writeWorktreeSessionMarker
|
|
401
|
-
} from "./chunk-
|
|
402
|
+
} from "./chunk-54YCNSK5.js";
|
|
403
|
+
import "./chunk-5M6IDOMF.js";
|
|
402
404
|
import "./chunk-TWPJO254.js";
|
|
403
405
|
import "./chunk-H6XPXXMH.js";
|
|
404
|
-
import "./chunk-5M6IDOMF.js";
|
|
405
|
-
import "./chunk-UPUG4GXM.js";
|
|
406
|
-
import "./chunk-64LQLPL7.js";
|
|
407
|
-
import "./chunk-2LQTH543.js";
|
|
408
|
-
import "./chunk-KRXPRVGL.js";
|
|
409
|
-
import "./chunk-BMFALVGQ.js";
|
|
410
406
|
import {
|
|
411
407
|
MAX_JOBS,
|
|
412
408
|
nextDurableFireMs
|
|
413
|
-
} from "./chunk-
|
|
409
|
+
} from "./chunk-AOHY3QJ3.js";
|
|
410
|
+
import "./chunk-5NNHICSA.js";
|
|
411
|
+
import "./chunk-SHN4KHDK.js";
|
|
412
|
+
import "./chunk-JXVC2PL3.js";
|
|
413
|
+
import "./chunk-KRXPRVGL.js";
|
|
414
|
+
import "./chunk-6PVPNMXU.js";
|
|
415
|
+
import "./chunk-ZMOJ7ISP.js";
|
|
414
416
|
import {
|
|
415
417
|
nextFireTime,
|
|
416
418
|
parseCron
|
|
@@ -423,22 +425,25 @@ import {
|
|
|
423
425
|
readCronTasks,
|
|
424
426
|
taskHasLegacyCondition,
|
|
425
427
|
updateCronTasks
|
|
426
|
-
} from "./chunk-
|
|
428
|
+
} from "./chunk-TEGJSJDF.js";
|
|
429
|
+
import "./chunk-TIRRPCFS.js";
|
|
430
|
+
import "./chunk-O6GEWCJA.js";
|
|
427
431
|
import "./chunk-T26EAKDL.js";
|
|
428
|
-
import "./chunk-6PVPNMXU.js";
|
|
429
432
|
import "./chunk-CPBF7KYF.js";
|
|
430
|
-
import "./chunk-
|
|
431
|
-
import "./chunk-
|
|
432
|
-
import "./chunk-
|
|
433
|
-
import "./chunk-
|
|
433
|
+
import "./chunk-4KP2F2TE.js";
|
|
434
|
+
import "./chunk-3APUUXRF.js";
|
|
435
|
+
import "./chunk-THVU3RNH.js";
|
|
436
|
+
import "./chunk-LHKCY7DY.js";
|
|
437
|
+
import "./chunk-6FMJLI5M.js";
|
|
434
438
|
import {
|
|
435
439
|
APPROVAL_MODES,
|
|
436
440
|
SubagentError,
|
|
437
441
|
SubagentErrorCode
|
|
438
|
-
} from "./chunk-
|
|
442
|
+
} from "./chunk-CBBP4BMC.js";
|
|
439
443
|
import "./chunk-S6LOFUVP.js";
|
|
440
|
-
import "./chunk-
|
|
441
|
-
import "./chunk-
|
|
444
|
+
import "./chunk-K623ENWT.js";
|
|
445
|
+
import "./chunk-AQ37AY7B.js";
|
|
446
|
+
import "./chunk-N4ACHWNH.js";
|
|
442
447
|
import "./chunk-ZPJWUGCS.js";
|
|
443
448
|
import {
|
|
444
449
|
QwenOAuth2Client,
|
|
@@ -448,15 +453,15 @@ import {
|
|
|
448
453
|
isDeviceAuthorizationSuccess,
|
|
449
454
|
isDeviceTokenPending,
|
|
450
455
|
isDeviceTokenSuccess
|
|
451
|
-
} from "./chunk-
|
|
456
|
+
} from "./chunk-D4HTUMGX.js";
|
|
452
457
|
import "./chunk-NAVJD2PQ.js";
|
|
453
|
-
import "./chunk-
|
|
454
|
-
import "./chunk-
|
|
458
|
+
import "./chunk-LOY7RWQG.js";
|
|
459
|
+
import "./chunk-E6CJ2SMM.js";
|
|
455
460
|
import "./chunk-DGEIYUC3.js";
|
|
456
461
|
import "./chunk-MPHPFVKK.js";
|
|
457
462
|
import "./chunk-GLNBDYUX.js";
|
|
458
463
|
import "./chunk-DJ2GSRLV.js";
|
|
459
|
-
import "./chunk-
|
|
464
|
+
import "./chunk-6CQWRWUC.js";
|
|
460
465
|
import {
|
|
461
466
|
addDaemonRequestAttribute,
|
|
462
467
|
emitDaemonLog,
|
|
@@ -466,40 +471,44 @@ import {
|
|
|
466
471
|
recordDaemonHttpRequest,
|
|
467
472
|
recordDaemonHttpResponse,
|
|
468
473
|
withDaemonRequestSpan
|
|
469
|
-
} from "./chunk-
|
|
474
|
+
} from "./chunk-Z3S5EMOW.js";
|
|
470
475
|
import "./chunk-2J3OJGTL.js";
|
|
471
476
|
import "./chunk-P3QQPMQA.js";
|
|
472
|
-
import "./chunk-
|
|
477
|
+
import "./chunk-XQK4XXTN.js";
|
|
473
478
|
import "./chunk-GLCZKT5V.js";
|
|
474
|
-
import "./chunk-
|
|
479
|
+
import "./chunk-QDK4F2N5.js";
|
|
475
480
|
import "./chunk-CR3C7WXL.js";
|
|
476
481
|
import "./chunk-XWRJCPHC.js";
|
|
477
482
|
import {
|
|
483
|
+
CursorNotAtLineBoundaryError,
|
|
484
|
+
LargeNonUtf8TextError,
|
|
485
|
+
TextScanBudgetExceededError,
|
|
478
486
|
decodeBufferWithEncodingInfoAsync,
|
|
479
487
|
getAllGeminiMdFilenames,
|
|
488
|
+
isUtf8CompatibleEncoding,
|
|
480
489
|
isWithinRoot,
|
|
481
490
|
parseLineTolerant,
|
|
482
491
|
read
|
|
483
|
-
} from "./chunk-
|
|
492
|
+
} from "./chunk-DUNI4EBW.js";
|
|
484
493
|
import "./chunk-VGC4I5JJ.js";
|
|
485
|
-
import "./chunk-
|
|
486
|
-
import "./chunk-
|
|
487
|
-
import "./chunk-
|
|
488
|
-
import "./chunk-
|
|
494
|
+
import "./chunk-3I6DUGQD.js";
|
|
495
|
+
import "./chunk-7ULQIS27.js";
|
|
496
|
+
import "./chunk-MM7TH7ZM.js";
|
|
497
|
+
import "./chunk-HIVKI6O6.js";
|
|
489
498
|
import "./chunk-46UV252V.js";
|
|
490
499
|
import "./chunk-ZBVS26BY.js";
|
|
491
|
-
import "./chunk-
|
|
492
|
-
import "./chunk-
|
|
493
|
-
import "./chunk-
|
|
494
|
-
import "./chunk-
|
|
500
|
+
import "./chunk-Q3T5KA2V.js";
|
|
501
|
+
import "./chunk-R2XWGR75.js";
|
|
502
|
+
import "./chunk-HC45LTEN.js";
|
|
503
|
+
import "./chunk-QARJNL2V.js";
|
|
495
504
|
import "./chunk-W4RQUHY3.js";
|
|
496
|
-
import "./chunk-
|
|
505
|
+
import "./chunk-G7XXKQYS.js";
|
|
497
506
|
import {
|
|
498
507
|
FatalConfigError,
|
|
499
508
|
Storage,
|
|
500
509
|
createDebugLogger,
|
|
501
510
|
runWithoutDebugLogSession
|
|
502
|
-
} from "./chunk-
|
|
511
|
+
} from "./chunk-E2BHWIDT.js";
|
|
503
512
|
import "./chunk-VOQXFAY5.js";
|
|
504
513
|
import "./chunk-75DOP5OR.js";
|
|
505
514
|
import "./chunk-DMTGGOSA.js";
|
|
@@ -936,7 +945,9 @@ init_esbuild_shims();
|
|
|
936
945
|
init_esbuild_shims();
|
|
937
946
|
import * as path2 from "node:path";
|
|
938
947
|
var MAX_READ_BYTES = 256 * 1024;
|
|
948
|
+
var MAX_TEXT_SCAN_BYTES = 8 * 1024 * 1024;
|
|
939
949
|
var MAX_WRITE_BYTES = 5 * 1024 * 1024;
|
|
950
|
+
var BINARY_PROBE_BYTES = 4096;
|
|
940
951
|
function shouldIgnore(absolute, boundWorkspace, ignore, kind = "file") {
|
|
941
952
|
const rel = path2.relative(boundWorkspace, absolute);
|
|
942
953
|
if (rel === "" || rel.startsWith("..")) return { ignored: false };
|
|
@@ -1089,6 +1100,64 @@ init_esbuild_shims();
|
|
|
1089
1100
|
import { createHash as createHash2, randomBytes } from "node:crypto";
|
|
1090
1101
|
import { constants as fsConstants, promises as fsp2 } from "node:fs";
|
|
1091
1102
|
import * as path4 from "node:path";
|
|
1103
|
+
|
|
1104
|
+
// packages/cli/src/serve/fs/text-cursor.ts
|
|
1105
|
+
init_esbuild_shims();
|
|
1106
|
+
var CURSOR_VERSION = 1;
|
|
1107
|
+
var MAX_TEXT_CURSOR_CHARS = 1024;
|
|
1108
|
+
function encodeTextCursor(state) {
|
|
1109
|
+
return Buffer.from(
|
|
1110
|
+
JSON.stringify({ v: CURSOR_VERSION, ...state }),
|
|
1111
|
+
"utf8"
|
|
1112
|
+
).toString("base64url");
|
|
1113
|
+
}
|
|
1114
|
+
__name(encodeTextCursor, "encodeTextCursor");
|
|
1115
|
+
function decodeTextCursor(cursor) {
|
|
1116
|
+
if (cursor.length === 0 || cursor.length > MAX_TEXT_CURSOR_CHARS) {
|
|
1117
|
+
throw new FsError(
|
|
1118
|
+
"parse_error",
|
|
1119
|
+
`cursor must be a non-empty string of at most ${MAX_TEXT_CURSOR_CHARS} characters`,
|
|
1120
|
+
{ hint: "pass a cursor returned by a previous read" }
|
|
1121
|
+
);
|
|
1122
|
+
}
|
|
1123
|
+
let parsed;
|
|
1124
|
+
try {
|
|
1125
|
+
parsed = JSON.parse(Buffer.from(cursor, "base64url").toString("utf8"));
|
|
1126
|
+
} catch {
|
|
1127
|
+
throw new FsError("parse_error", "cursor is not a valid read cursor", {
|
|
1128
|
+
hint: "pass a cursor returned by a previous read"
|
|
1129
|
+
});
|
|
1130
|
+
}
|
|
1131
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
1132
|
+
throw new FsError("parse_error", "cursor is not a valid read cursor", {
|
|
1133
|
+
hint: "pass a cursor returned by a previous read"
|
|
1134
|
+
});
|
|
1135
|
+
}
|
|
1136
|
+
const raw = parsed;
|
|
1137
|
+
const off = raw["off"];
|
|
1138
|
+
const size = raw["size"];
|
|
1139
|
+
const dev = raw["dev"];
|
|
1140
|
+
const ino = raw["ino"];
|
|
1141
|
+
if (raw["v"] !== CURSOR_VERSION || !Number.isSafeInteger(off) || off < 0 || !Number.isSafeInteger(size) || size < 0 || typeof dev !== "string" || typeof ino !== "string") {
|
|
1142
|
+
throw new FsError("parse_error", "cursor is not a valid read cursor", {
|
|
1143
|
+
hint: "pass a cursor returned by a previous read"
|
|
1144
|
+
});
|
|
1145
|
+
}
|
|
1146
|
+
return { off, size, dev, ino };
|
|
1147
|
+
}
|
|
1148
|
+
__name(decodeTextCursor, "decodeTextCursor");
|
|
1149
|
+
function assertCursorMatchesFile(cursor, stats, path14) {
|
|
1150
|
+
if (String(stats.dev) !== cursor.dev || String(stats.ino) !== cursor.ino || stats.size < cursor.size) {
|
|
1151
|
+
throw new FsError(
|
|
1152
|
+
"hash_mismatch",
|
|
1153
|
+
`cursor no longer matches the file it was issued for: ${path14}`,
|
|
1154
|
+
{ hint: "re-read the file from the beginning to get a fresh cursor" }
|
|
1155
|
+
);
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
__name(assertCursorMatchesFile, "assertCursorMatchesFile");
|
|
1159
|
+
|
|
1160
|
+
// packages/cli/src/serve/fs/workspace-file-system.ts
|
|
1092
1161
|
function createWorkspaceFileSystemFactory(deps) {
|
|
1093
1162
|
const boundWorkspaces = canonicalizeWorkspaces(deps.boundWorkspaces);
|
|
1094
1163
|
if (boundWorkspaces.length === 0) {
|
|
@@ -1227,7 +1296,19 @@ var WorkspaceFileSystemImpl = class {
|
|
|
1227
1296
|
`limit must be a positive integer, got ${opts.limit}`
|
|
1228
1297
|
);
|
|
1229
1298
|
}
|
|
1230
|
-
|
|
1299
|
+
if (opts.cursor !== void 0 && opts.line !== void 0) {
|
|
1300
|
+
throw new FsError(
|
|
1301
|
+
"parse_error",
|
|
1302
|
+
"cursor and line are mutually exclusive; a cursor already encodes where to resume"
|
|
1303
|
+
);
|
|
1304
|
+
}
|
|
1305
|
+
if (opts.maxBytes !== void 0 && (!Number.isSafeInteger(opts.maxBytes) || opts.maxBytes < 1 || opts.maxBytes > MAX_READ_BYTES)) {
|
|
1306
|
+
throw new FsError(
|
|
1307
|
+
"parse_error",
|
|
1308
|
+
`maxBytes must be a positive integer in [1, ${MAX_READ_BYTES}], got ${opts.maxBytes}`
|
|
1309
|
+
);
|
|
1310
|
+
}
|
|
1311
|
+
const snapshot = await readTextFromResolvedFile(p, opts, this.deps.lowFs);
|
|
1231
1312
|
this.deps.generationGuard?.assertOpen();
|
|
1232
1313
|
const ignoreVerdict = this.ignoreVerdict(p, "file");
|
|
1233
1314
|
const meta = snapshot.meta;
|
|
@@ -1882,7 +1963,7 @@ function validateWriteTextAtomicOptions(opts) {
|
|
|
1882
1963
|
}
|
|
1883
1964
|
}
|
|
1884
1965
|
__name(validateWriteTextAtomicOptions, "validateWriteTextAtomicOptions");
|
|
1885
|
-
async function
|
|
1966
|
+
async function readTextFromResolvedFile(p, opts, lowFs) {
|
|
1886
1967
|
const pre = await fsp2.lstat(p);
|
|
1887
1968
|
if (pre.isSymbolicLink()) {
|
|
1888
1969
|
throw new FsError("symlink_escape", `path is a symlink: ${p}`, {
|
|
@@ -1892,12 +1973,32 @@ async function readTextSnapshotFromResolvedFile(p, opts = {}) {
|
|
|
1892
1973
|
if (!pre.isFile()) {
|
|
1893
1974
|
throw new FsError("parse_error", `path is not a regular file: ${p}`);
|
|
1894
1975
|
}
|
|
1976
|
+
if (opts.cursor !== void 0) {
|
|
1977
|
+
return readTextCursorWindowFromResolvedFile(p, pre, opts, lowFs);
|
|
1978
|
+
}
|
|
1979
|
+
const wantsWindow = opts.limit !== void 0 || opts.maxBytes !== void 0 || opts.line !== void 0;
|
|
1980
|
+
if (pre.size > MAX_READ_BYTES && wantsWindow) {
|
|
1981
|
+
return readLargeTextWindowFromResolvedFile(p, pre, opts, lowFs);
|
|
1982
|
+
}
|
|
1983
|
+
return readTextSnapshotFromResolvedFile(p, opts, pre);
|
|
1984
|
+
}
|
|
1985
|
+
__name(readTextFromResolvedFile, "readTextFromResolvedFile");
|
|
1986
|
+
async function readTextSnapshotFromResolvedFile(p, opts = {}, knownPre) {
|
|
1987
|
+
const pre = knownPre ?? await fsp2.lstat(p);
|
|
1988
|
+
if (pre.isSymbolicLink()) {
|
|
1989
|
+
throw new FsError("symlink_escape", `path is a symlink: ${p}`, {
|
|
1990
|
+
hint: "re-resolve the target file instead of reading through a link"
|
|
1991
|
+
});
|
|
1992
|
+
}
|
|
1993
|
+
if (!pre.isFile()) {
|
|
1994
|
+
throw new FsError("parse_error", `path is not a regular file: ${p}`);
|
|
1995
|
+
}
|
|
1895
1996
|
if (pre.size > MAX_READ_BYTES) {
|
|
1896
1997
|
throw new FsError(
|
|
1897
1998
|
"file_too_large",
|
|
1898
1999
|
`file of ${pre.size} bytes exceeds read cap of ${MAX_READ_BYTES} bytes`,
|
|
1899
2000
|
{
|
|
1900
|
-
hint: "use readBytes for explicit byte-windowed access
|
|
2001
|
+
hint: "use a finite line limit for large UTF-8 text, or readBytes for explicit byte-windowed access"
|
|
1901
2002
|
}
|
|
1902
2003
|
);
|
|
1903
2004
|
}
|
|
@@ -1914,8 +2015,10 @@ async function readTextSnapshotFromResolvedFile(p, opts = {}) {
|
|
|
1914
2015
|
startLineIndex,
|
|
1915
2016
|
opts.limit ?? Number.POSITIVE_INFINITY
|
|
1916
2017
|
);
|
|
1917
|
-
const
|
|
2018
|
+
const maxOutputBytes = opts.maxBytes ?? MAX_READ_BYTES;
|
|
2019
|
+
const sizeOutcome = enforceReadSize(raw.length, maxOutputBytes);
|
|
1918
2020
|
let content = sliced.content;
|
|
2021
|
+
let byteTruncated = false;
|
|
1919
2022
|
const meta = {
|
|
1920
2023
|
encoding: decoded.encoding,
|
|
1921
2024
|
bom: decoded.bom,
|
|
@@ -1924,22 +2027,243 @@ async function readTextSnapshotFromResolvedFile(p, opts = {}) {
|
|
|
1924
2027
|
originalLineCount: sliced.originalLineCount,
|
|
1925
2028
|
hash: hashBuffer(raw)
|
|
1926
2029
|
};
|
|
2030
|
+
const output = Buffer.from(content, "utf-8");
|
|
2031
|
+
if (output.length > maxOutputBytes) {
|
|
2032
|
+
content = safeUtf8Truncate(output, maxOutputBytes).toString("utf-8");
|
|
2033
|
+
meta.lineEnding = detectLineEnding(content);
|
|
2034
|
+
meta.truncated = true;
|
|
2035
|
+
byteTruncated = true;
|
|
2036
|
+
}
|
|
1927
2037
|
if (sizeOutcome.truncated) {
|
|
1928
|
-
const buf = Buffer.from(content, "utf-8");
|
|
1929
|
-
if (buf.length > sizeOutcome.bytesToRead) {
|
|
1930
|
-
content = safeUtf8Truncate(buf, sizeOutcome.bytesToRead).toString(
|
|
1931
|
-
"utf-8"
|
|
1932
|
-
);
|
|
1933
|
-
meta.lineEnding = detectLineEnding(content);
|
|
1934
|
-
}
|
|
1935
2038
|
meta.truncated = true;
|
|
1936
2039
|
}
|
|
1937
2040
|
if (opts.limit !== void 0 && Number.isFinite(opts.limit) && sliced.originalLineCount > opts.limit + startLineIndex) {
|
|
1938
2041
|
meta.truncated = true;
|
|
1939
2042
|
}
|
|
2043
|
+
const pageableLineCount = sliced.originalLineCount - (decoded.content.endsWith("\n") ? 1 : 0);
|
|
2044
|
+
meta.hasMore = byteTruncated || sliced.endLine < pageableLineCount;
|
|
2045
|
+
const bomBytes = decoded.bom ? 3 : 0;
|
|
2046
|
+
const decodedBytesMatchSource = isUtf8CompatibleEncoding(decoded.encoding) && Buffer.from(decoded.content, "utf-8").equals(raw.subarray(bomBytes));
|
|
2047
|
+
if (meta.hasMore && !byteTruncated && decodedBytesMatchSource) {
|
|
2048
|
+
const startByte = bomBytes + sliced.startByteOffset;
|
|
2049
|
+
const contentBytes = Buffer.byteLength(content, "utf-8");
|
|
2050
|
+
const nextOffset = startByte + contentBytes + 1;
|
|
2051
|
+
if (nextOffset < raw.length) {
|
|
2052
|
+
meta.nextCursor = encodeTextCursor({
|
|
2053
|
+
off: nextOffset,
|
|
2054
|
+
size: raw.length,
|
|
2055
|
+
dev: String(pre.dev),
|
|
2056
|
+
ino: String(pre.ino)
|
|
2057
|
+
});
|
|
2058
|
+
}
|
|
2059
|
+
}
|
|
1940
2060
|
return { content, meta };
|
|
1941
2061
|
}
|
|
1942
2062
|
__name(readTextSnapshotFromResolvedFile, "readTextSnapshotFromResolvedFile");
|
|
2063
|
+
function assertStreamWindowStable(before, after, p, reason) {
|
|
2064
|
+
const beforeSize = toBigInt(before.size);
|
|
2065
|
+
const afterSize = toBigInt(after.size);
|
|
2066
|
+
if (afterSize < beforeSize || afterSize === beforeSize && (after.mtimeMs !== before.mtimeMs || after.ctimeMs !== before.ctimeMs)) {
|
|
2067
|
+
throw new FsError("hash_mismatch", `${reason}: ${p}`, {
|
|
2068
|
+
hint: "retry after re-reading the latest file"
|
|
2069
|
+
});
|
|
2070
|
+
}
|
|
2071
|
+
}
|
|
2072
|
+
__name(assertStreamWindowStable, "assertStreamWindowStable");
|
|
2073
|
+
async function readTextCursorWindowFromResolvedFile(p, pre, opts, lowFs) {
|
|
2074
|
+
const cursor = decodeTextCursor(opts.cursor);
|
|
2075
|
+
const fh = await fsp2.open(p, "r");
|
|
2076
|
+
let opened;
|
|
2077
|
+
let afterRead;
|
|
2078
|
+
let window;
|
|
2079
|
+
let primaryError;
|
|
2080
|
+
let hasPrimaryError = false;
|
|
2081
|
+
try {
|
|
2082
|
+
opened = await fh.stat();
|
|
2083
|
+
assertSameFile(pre, opened, p, "read");
|
|
2084
|
+
assertStreamWindowStable(pre, opened, p, "file changed before read");
|
|
2085
|
+
assertCursorMatchesFile(cursor, opened, p);
|
|
2086
|
+
try {
|
|
2087
|
+
const probe = Buffer.alloc(Math.min(BINARY_PROBE_BYTES, opened.size));
|
|
2088
|
+
if (probe.length > 0) {
|
|
2089
|
+
const { bytesRead } = await fh.read(probe, 0, probe.length, 0);
|
|
2090
|
+
if (looksBinary(probe.subarray(0, bytesRead))) {
|
|
2091
|
+
throw new FsError("binary_file", `binary file: ${p}`, {
|
|
2092
|
+
hint: "use readBytes for binary content"
|
|
2093
|
+
});
|
|
2094
|
+
}
|
|
2095
|
+
}
|
|
2096
|
+
window = await lowFs.readTextCursorFromHandle({
|
|
2097
|
+
fileHandle: fh,
|
|
2098
|
+
startOffset: cursor.off,
|
|
2099
|
+
fileSize: opened.size,
|
|
2100
|
+
maxOutputBytes: opts.maxBytes ?? MAX_READ_BYTES,
|
|
2101
|
+
maxSnapBytes: MAX_TEXT_SCAN_BYTES,
|
|
2102
|
+
...opts.limit !== void 0 ? { limit: opts.limit } : {}
|
|
2103
|
+
});
|
|
2104
|
+
} catch (err) {
|
|
2105
|
+
hasPrimaryError = true;
|
|
2106
|
+
primaryError = err;
|
|
2107
|
+
}
|
|
2108
|
+
afterRead = await fh.stat();
|
|
2109
|
+
} finally {
|
|
2110
|
+
await fh.close();
|
|
2111
|
+
}
|
|
2112
|
+
if (opened === void 0 || afterRead === void 0) {
|
|
2113
|
+
throw new FsError("internal_error", `failed to stat opened file: ${p}`);
|
|
2114
|
+
}
|
|
2115
|
+
const post = await fsp2.lstat(p);
|
|
2116
|
+
if (post.isSymbolicLink()) {
|
|
2117
|
+
throw new FsError(
|
|
2118
|
+
"symlink_escape",
|
|
2119
|
+
`path was replaced with a symlink during read: ${p}`,
|
|
2120
|
+
{ hint: "TOCTOU swap detected via post-read lstat" }
|
|
2121
|
+
);
|
|
2122
|
+
}
|
|
2123
|
+
assertSameFile(opened, afterRead, p, "read");
|
|
2124
|
+
assertStreamWindowStable(opened, afterRead, p, "file changed during read");
|
|
2125
|
+
assertSameFile(opened, post, p, "read");
|
|
2126
|
+
assertStreamWindowStable(opened, post, p, "file changed during read");
|
|
2127
|
+
if (hasPrimaryError) {
|
|
2128
|
+
if (primaryError instanceof LargeNonUtf8TextError) {
|
|
2129
|
+
throw new FsError("binary_file", primaryError.message, {
|
|
2130
|
+
cause: primaryError,
|
|
2131
|
+
hint: "convert the file to UTF-8, or use readBytes for the raw bytes"
|
|
2132
|
+
});
|
|
2133
|
+
}
|
|
2134
|
+
if (primaryError instanceof CursorNotAtLineBoundaryError) {
|
|
2135
|
+
throw new FsError("parse_error", primaryError.message, {
|
|
2136
|
+
cause: primaryError,
|
|
2137
|
+
hint: "pass a cursor returned by a previous read"
|
|
2138
|
+
});
|
|
2139
|
+
}
|
|
2140
|
+
throw primaryError;
|
|
2141
|
+
}
|
|
2142
|
+
if (window === void 0) {
|
|
2143
|
+
throw new FsError(
|
|
2144
|
+
"internal_error",
|
|
2145
|
+
`cursor text read returned no result: ${p}`
|
|
2146
|
+
);
|
|
2147
|
+
}
|
|
2148
|
+
const meta = {
|
|
2149
|
+
encoding: window.encoding,
|
|
2150
|
+
bom: window.bom,
|
|
2151
|
+
lineEnding: window.lineEnding,
|
|
2152
|
+
sizeBytes: opened.size,
|
|
2153
|
+
truncated: true,
|
|
2154
|
+
hasMore: window.nextOffset !== void 0 || window.truncatedByBytes === true
|
|
2155
|
+
};
|
|
2156
|
+
if (window.nextOffset !== void 0) {
|
|
2157
|
+
meta.nextCursor = encodeTextCursor({
|
|
2158
|
+
off: window.nextOffset,
|
|
2159
|
+
size: opened.size,
|
|
2160
|
+
dev: String(opened.dev),
|
|
2161
|
+
ino: String(opened.ino)
|
|
2162
|
+
});
|
|
2163
|
+
}
|
|
2164
|
+
return { content: window.content, meta };
|
|
2165
|
+
}
|
|
2166
|
+
__name(readTextCursorWindowFromResolvedFile, "readTextCursorWindowFromResolvedFile");
|
|
2167
|
+
async function readLargeTextWindowFromResolvedFile(p, pre, opts, lowFs) {
|
|
2168
|
+
const fh = await fsp2.open(p, "r");
|
|
2169
|
+
let opened;
|
|
2170
|
+
let afterRead;
|
|
2171
|
+
let result;
|
|
2172
|
+
let primaryError;
|
|
2173
|
+
let hasPrimaryError = false;
|
|
2174
|
+
try {
|
|
2175
|
+
opened = await fh.stat();
|
|
2176
|
+
assertSameFile(pre, opened, p, "read");
|
|
2177
|
+
assertStreamWindowStable(pre, opened, p, "file changed before read");
|
|
2178
|
+
try {
|
|
2179
|
+
const probe = Buffer.alloc(Math.min(BINARY_PROBE_BYTES, opened.size));
|
|
2180
|
+
if (probe.length > 0) {
|
|
2181
|
+
const { bytesRead } = await fh.read(probe, 0, probe.length, 0);
|
|
2182
|
+
if (looksBinary(probe.subarray(0, bytesRead))) {
|
|
2183
|
+
throw new FsError("binary_file", `binary file: ${p}`, {
|
|
2184
|
+
hint: "use readBytes for binary content"
|
|
2185
|
+
});
|
|
2186
|
+
}
|
|
2187
|
+
}
|
|
2188
|
+
result = await lowFs.readTextFileFromHandle({
|
|
2189
|
+
fileHandle: fh,
|
|
2190
|
+
fileSize: opened.size,
|
|
2191
|
+
limit: opts.limit ?? Number.POSITIVE_INFINITY,
|
|
2192
|
+
line: opts.line !== void 0 ? opts.line - 1 : 0,
|
|
2193
|
+
maxOutputBytes: opts.maxBytes ?? MAX_READ_BYTES,
|
|
2194
|
+
maxScanBytes: MAX_TEXT_SCAN_BYTES
|
|
2195
|
+
});
|
|
2196
|
+
} catch (err) {
|
|
2197
|
+
hasPrimaryError = true;
|
|
2198
|
+
primaryError = err;
|
|
2199
|
+
}
|
|
2200
|
+
afterRead = await fh.stat();
|
|
2201
|
+
} finally {
|
|
2202
|
+
await fh.close();
|
|
2203
|
+
}
|
|
2204
|
+
if (opened === void 0 || afterRead === void 0) {
|
|
2205
|
+
throw new FsError("internal_error", `failed to stat opened file: ${p}`);
|
|
2206
|
+
}
|
|
2207
|
+
const post = await fsp2.lstat(p);
|
|
2208
|
+
if (post.isSymbolicLink()) {
|
|
2209
|
+
throw new FsError(
|
|
2210
|
+
"symlink_escape",
|
|
2211
|
+
`path was replaced with a symlink during read: ${p}`,
|
|
2212
|
+
{ hint: "TOCTOU swap detected via post-read lstat" }
|
|
2213
|
+
);
|
|
2214
|
+
}
|
|
2215
|
+
assertSameFile(opened, afterRead, p, "read");
|
|
2216
|
+
assertStreamWindowStable(opened, afterRead, p, "file changed during read");
|
|
2217
|
+
assertSameFile(opened, post, p, "read");
|
|
2218
|
+
assertStreamWindowStable(opened, post, p, "file changed during read");
|
|
2219
|
+
if (hasPrimaryError) {
|
|
2220
|
+
if (primaryError instanceof LargeNonUtf8TextError) {
|
|
2221
|
+
throw new FsError("binary_file", primaryError.message, {
|
|
2222
|
+
cause: primaryError,
|
|
2223
|
+
hint: "convert the file to UTF-8, or use readBytes for the raw bytes"
|
|
2224
|
+
});
|
|
2225
|
+
}
|
|
2226
|
+
if (primaryError instanceof TextScanBudgetExceededError) {
|
|
2227
|
+
throw new FsError("file_too_large", primaryError.message, {
|
|
2228
|
+
cause: primaryError,
|
|
2229
|
+
hint: `line offsets are resolved by scanning from byte 0 and stop after ${MAX_TEXT_SCAN_BYTES} bytes; page with the cursor from a shallower read to reach this offset in O(1), or use readBytes for raw bytes`
|
|
2230
|
+
});
|
|
2231
|
+
}
|
|
2232
|
+
throw primaryError;
|
|
2233
|
+
}
|
|
2234
|
+
if (result === void 0) {
|
|
2235
|
+
throw new FsError(
|
|
2236
|
+
"internal_error",
|
|
2237
|
+
`large text range read returned no result: ${p}`
|
|
2238
|
+
);
|
|
2239
|
+
}
|
|
2240
|
+
const content = result.content;
|
|
2241
|
+
const readMeta = result._meta;
|
|
2242
|
+
const meta = {
|
|
2243
|
+
encoding: readMeta?.encoding,
|
|
2244
|
+
bom: readMeta?.bom,
|
|
2245
|
+
lineEnding: readMeta?.lineEnding ?? detectLineEnding(content),
|
|
2246
|
+
// Size as of `open`, not as of now: it describes the snapshot the
|
|
2247
|
+
// returned window was cut from. A file that grew during the read
|
|
2248
|
+
// reports the smaller, consistent number.
|
|
2249
|
+
sizeBytes: opened.size,
|
|
2250
|
+
truncated: true,
|
|
2251
|
+
hasMore: readMeta?.nextByteOffset !== void 0 || readMeta?.truncatedByBytes === true
|
|
2252
|
+
};
|
|
2253
|
+
if (readMeta?.nextByteOffset !== void 0) {
|
|
2254
|
+
meta.nextCursor = encodeTextCursor({
|
|
2255
|
+
off: readMeta.nextByteOffset,
|
|
2256
|
+
size: opened.size,
|
|
2257
|
+
dev: String(opened.dev),
|
|
2258
|
+
ino: String(opened.ino)
|
|
2259
|
+
});
|
|
2260
|
+
}
|
|
2261
|
+
if (readMeta?.originalLineCountExact === true && readMeta?.originalLineCount !== void 0) {
|
|
2262
|
+
meta.originalLineCount = readMeta.originalLineCount;
|
|
2263
|
+
}
|
|
2264
|
+
return { content, meta };
|
|
2265
|
+
}
|
|
2266
|
+
__name(readLargeTextWindowFromResolvedFile, "readLargeTextWindowFromResolvedFile");
|
|
1943
2267
|
async function readStableRegularFileBuffer(p, pre) {
|
|
1944
2268
|
const fh = await fsp2.open(p, "r");
|
|
1945
2269
|
let opened;
|
|
@@ -1951,7 +2275,7 @@ async function readStableRegularFileBuffer(p, pre) {
|
|
|
1951
2275
|
"file_too_large",
|
|
1952
2276
|
`file of ${opened.size} bytes exceeds read cap of ${MAX_READ_BYTES} bytes`,
|
|
1953
2277
|
{
|
|
1954
|
-
hint: "use readBytes for explicit byte-windowed access
|
|
2278
|
+
hint: "use a finite line limit for large UTF-8 text, or readBytes for explicit byte-windowed access"
|
|
1955
2279
|
}
|
|
1956
2280
|
);
|
|
1957
2281
|
}
|
|
@@ -1987,9 +2311,15 @@ function sliceDecodedText(content, startLine, limit) {
|
|
|
1987
2311
|
const originalLineCount = lines.length;
|
|
1988
2312
|
const endLine = Math.min(startLine + limit, originalLineCount);
|
|
1989
2313
|
const actualStartLine = Math.min(startLine, originalLineCount);
|
|
2314
|
+
let startByteOffset = 0;
|
|
2315
|
+
for (let i = 0; i < actualStartLine; i++) {
|
|
2316
|
+
startByteOffset += Buffer.byteLength(lines[i], "utf-8") + 1;
|
|
2317
|
+
}
|
|
1990
2318
|
return {
|
|
1991
2319
|
content: lines.slice(actualStartLine, endLine).join("\n"),
|
|
1992
|
-
originalLineCount
|
|
2320
|
+
originalLineCount,
|
|
2321
|
+
startByteOffset,
|
|
2322
|
+
endLine
|
|
1993
2323
|
};
|
|
1994
2324
|
}
|
|
1995
2325
|
__name(sliceDecodedText, "sliceDecodedText");
|
|
@@ -2780,13 +3110,29 @@ async function handleGetFile(req, res, deps) {
|
|
|
2780
3110
|
});
|
|
2781
3111
|
return;
|
|
2782
3112
|
}
|
|
3113
|
+
const rawCursor = req.query["cursor"];
|
|
3114
|
+
if (rawCursor !== void 0 && (typeof rawCursor !== "string" || rawCursor.length === 0 || rawCursor.length > MAX_TEXT_CURSOR_CHARS)) {
|
|
3115
|
+
applyReadHeaders(res);
|
|
3116
|
+
res.status(400).json({
|
|
3117
|
+
errorKind: "parse_error",
|
|
3118
|
+
error: `\`cursor\` must be a non-empty string of at most ${MAX_TEXT_CURSOR_CHARS} characters`,
|
|
3119
|
+
status: 400
|
|
3120
|
+
});
|
|
3121
|
+
return;
|
|
3122
|
+
}
|
|
3123
|
+
const cursor = rawCursor;
|
|
2783
3124
|
const fs6 = factory.forRequest({
|
|
2784
3125
|
originatorClientId: clientId ?? void 0,
|
|
2785
3126
|
route: ROUTE2
|
|
2786
3127
|
});
|
|
2787
3128
|
try {
|
|
2788
3129
|
const resolved = await fs6.resolve(queryPath, "read");
|
|
2789
|
-
const out = await fs6.readText(resolved, {
|
|
3130
|
+
const out = await fs6.readText(resolved, {
|
|
3131
|
+
maxBytes,
|
|
3132
|
+
line,
|
|
3133
|
+
limit,
|
|
3134
|
+
cursor
|
|
3135
|
+
});
|
|
2790
3136
|
const returnedBytes = Buffer.byteLength(out.content, "utf-8");
|
|
2791
3137
|
applyReadHeaders(res);
|
|
2792
3138
|
res.status(200).json({
|
|
@@ -2801,7 +3147,9 @@ async function handleGetFile(req, res, deps) {
|
|
|
2801
3147
|
truncated: out.meta.truncated === true,
|
|
2802
3148
|
hash: out.meta.hash,
|
|
2803
3149
|
matchedIgnore: out.meta.matchedIgnore ?? null,
|
|
2804
|
-
originalLineCount: out.meta.originalLineCount ?? null
|
|
3150
|
+
originalLineCount: out.meta.originalLineCount ?? null,
|
|
3151
|
+
nextCursor: out.meta.nextCursor ?? null,
|
|
3152
|
+
hasMore: out.meta.hasMore === true
|
|
2805
3153
|
});
|
|
2806
3154
|
} catch (err) {
|
|
2807
3155
|
sendFsError(res, err, ROUTE2);
|
|
@@ -6851,18 +7199,34 @@ async function removeTasksForSessions(projectRoot, sessionIds) {
|
|
|
6851
7199
|
__name(removeTasksForSessions, "removeTasksForSessions");
|
|
6852
7200
|
|
|
6853
7201
|
// packages/cli/src/serve/server/session-archive.ts
|
|
7202
|
+
var DaemonDrainingError = class extends Error {
|
|
7203
|
+
static {
|
|
7204
|
+
__name(this, "DaemonDrainingError");
|
|
7205
|
+
}
|
|
7206
|
+
name = "DaemonDrainingError";
|
|
7207
|
+
code = "daemon_draining";
|
|
7208
|
+
constructor() {
|
|
7209
|
+
super("The daemon is draining and no longer accepts session maintenance.");
|
|
7210
|
+
}
|
|
7211
|
+
};
|
|
6854
7212
|
var SessionArchiveCoordinator = class {
|
|
6855
7213
|
static {
|
|
6856
7214
|
__name(this, "SessionArchiveCoordinator");
|
|
6857
7215
|
}
|
|
6858
7216
|
exclusive = /* @__PURE__ */ new Set();
|
|
6859
7217
|
shared = /* @__PURE__ */ new Map();
|
|
7218
|
+
maintenanceSealed = false;
|
|
7219
|
+
activeMaintenance = 0;
|
|
7220
|
+
maintenanceDrain;
|
|
6860
7221
|
assertNotTransitioning(sessionId) {
|
|
6861
7222
|
if (this.exclusive.has(sessionId)) {
|
|
6862
7223
|
throw new SessionArchivingError(sessionId);
|
|
6863
7224
|
}
|
|
6864
7225
|
}
|
|
6865
7226
|
async runExclusiveMany(sessionIds, fn) {
|
|
7227
|
+
if (this.maintenanceSealed) {
|
|
7228
|
+
throw new DaemonDrainingError();
|
|
7229
|
+
}
|
|
6866
7230
|
const uniqueSessionIds = [...new Set(sessionIds)];
|
|
6867
7231
|
for (const sessionId of uniqueSessionIds) {
|
|
6868
7232
|
this.assertNotTransitioning(sessionId);
|
|
@@ -6873,13 +7237,33 @@ var SessionArchiveCoordinator = class {
|
|
|
6873
7237
|
for (const sessionId of uniqueSessionIds) {
|
|
6874
7238
|
this.exclusive.add(sessionId);
|
|
6875
7239
|
}
|
|
7240
|
+
this.activeMaintenance++;
|
|
6876
7241
|
try {
|
|
6877
7242
|
return await fn();
|
|
6878
7243
|
} finally {
|
|
6879
7244
|
for (const sessionId of uniqueSessionIds) {
|
|
6880
7245
|
this.exclusive.delete(sessionId);
|
|
6881
7246
|
}
|
|
7247
|
+
this.activeMaintenance--;
|
|
7248
|
+
if (this.activeMaintenance === 0) {
|
|
7249
|
+
this.maintenanceDrain?.resolve();
|
|
7250
|
+
this.maintenanceDrain = void 0;
|
|
7251
|
+
}
|
|
7252
|
+
}
|
|
7253
|
+
}
|
|
7254
|
+
sealMaintenanceAndWait() {
|
|
7255
|
+
this.maintenanceSealed = true;
|
|
7256
|
+
if (this.activeMaintenance === 0) {
|
|
7257
|
+
return Promise.resolve();
|
|
7258
|
+
}
|
|
7259
|
+
if (!this.maintenanceDrain) {
|
|
7260
|
+
let resolve5;
|
|
7261
|
+
const promise = new Promise((done) => {
|
|
7262
|
+
resolve5 = done;
|
|
7263
|
+
});
|
|
7264
|
+
this.maintenanceDrain = { promise, resolve: resolve5 };
|
|
6882
7265
|
}
|
|
7266
|
+
return this.maintenanceDrain.promise;
|
|
6883
7267
|
}
|
|
6884
7268
|
async runSharedMany(sessionIds, fn) {
|
|
6885
7269
|
const uniqueSessionIds = [...new Set(sessionIds)];
|
|
@@ -6903,70 +7287,280 @@ var SessionArchiveCoordinator = class {
|
|
|
6903
7287
|
}
|
|
6904
7288
|
}
|
|
6905
7289
|
};
|
|
7290
|
+
async function runWithDaemonWriterLease(params) {
|
|
7291
|
+
const {
|
|
7292
|
+
action,
|
|
7293
|
+
sessionId,
|
|
7294
|
+
service,
|
|
7295
|
+
mutate,
|
|
7296
|
+
mutationAppliedAfterError,
|
|
7297
|
+
afterMutationApplied
|
|
7298
|
+
} = params;
|
|
7299
|
+
let lease;
|
|
7300
|
+
try {
|
|
7301
|
+
lease = await service.acquireSessionWriterLease(sessionId, {
|
|
7302
|
+
processKind: "daemon",
|
|
7303
|
+
reclaimPolicy: "never"
|
|
7304
|
+
});
|
|
7305
|
+
} catch (error2) {
|
|
7306
|
+
return { mutationApplied: false, error: error2 };
|
|
7307
|
+
}
|
|
7308
|
+
let value;
|
|
7309
|
+
let mutationApplied = false;
|
|
7310
|
+
let mutationError;
|
|
7311
|
+
try {
|
|
7312
|
+
const mutation = await mutate(() => lease.assertOwnedAndUnchanged());
|
|
7313
|
+
value = mutation.value;
|
|
7314
|
+
mutationApplied = mutation.mutationApplied;
|
|
7315
|
+
} catch (error2) {
|
|
7316
|
+
mutationError = error2;
|
|
7317
|
+
try {
|
|
7318
|
+
mutationApplied = await mutationAppliedAfterError();
|
|
7319
|
+
} catch {
|
|
7320
|
+
mutationApplied = false;
|
|
7321
|
+
}
|
|
7322
|
+
}
|
|
7323
|
+
let maintenanceError;
|
|
7324
|
+
if (mutationApplied) {
|
|
7325
|
+
try {
|
|
7326
|
+
await afterMutationApplied();
|
|
7327
|
+
} catch (error2) {
|
|
7328
|
+
maintenanceError = error2;
|
|
7329
|
+
logSessionArchiveWarning(
|
|
7330
|
+
`scheduled task lifecycle update failed action=${action} workspace=${safeLogValue(
|
|
7331
|
+
service.getProjectRoot()
|
|
7332
|
+
)} session=${safeLogValue(sessionId)} error=${safeLogValue(
|
|
7333
|
+
errorMessage(error2)
|
|
7334
|
+
)}`
|
|
7335
|
+
);
|
|
7336
|
+
}
|
|
7337
|
+
}
|
|
7338
|
+
let releaseError;
|
|
7339
|
+
try {
|
|
7340
|
+
await lease.release();
|
|
7341
|
+
} catch (error2) {
|
|
7342
|
+
releaseError = error2;
|
|
7343
|
+
}
|
|
7344
|
+
if (releaseError !== void 0) {
|
|
7345
|
+
logMaintenanceLeaseReleaseFailure({
|
|
7346
|
+
action,
|
|
7347
|
+
workspace: service.getProjectRoot(),
|
|
7348
|
+
sessionId,
|
|
7349
|
+
error: releaseError,
|
|
7350
|
+
mutationApplied
|
|
7351
|
+
});
|
|
7352
|
+
if (mutationError !== void 0) {
|
|
7353
|
+
logSessionArchiveWarning(
|
|
7354
|
+
`session maintenance mutation also failed action=${action} workspace=${safeLogValue(
|
|
7355
|
+
service.getProjectRoot()
|
|
7356
|
+
)} session=${safeLogValue(sessionId)} error=${safeLogValue(
|
|
7357
|
+
errorMessage(mutationError)
|
|
7358
|
+
)}`
|
|
7359
|
+
);
|
|
7360
|
+
}
|
|
7361
|
+
return { mutationApplied, error: releaseError, maintenanceError };
|
|
7362
|
+
}
|
|
7363
|
+
if (mutationError !== void 0) {
|
|
7364
|
+
return { mutationApplied, error: mutationError, maintenanceError };
|
|
7365
|
+
}
|
|
7366
|
+
return { value, mutationApplied, maintenanceError };
|
|
7367
|
+
}
|
|
7368
|
+
__name(runWithDaemonWriterLease, "runWithDaemonWriterLease");
|
|
7369
|
+
function logMaintenanceLeaseReleaseFailure(params) {
|
|
7370
|
+
const errorKind = typeof params.error === "object" && params.error !== null && typeof params.error.errorKind === "string" ? params.error.errorKind : "unknown";
|
|
7371
|
+
logSessionArchiveWarning(
|
|
7372
|
+
`session maintenance lease release failed action=${params.action} workspace=${safeLogValue(
|
|
7373
|
+
params.workspace
|
|
7374
|
+
)} session=${safeLogValue(params.sessionId)} errorKind=${safeLogValue(
|
|
7375
|
+
errorKind
|
|
7376
|
+
)} mutationApplied=${params.mutationApplied}`
|
|
7377
|
+
);
|
|
7378
|
+
}
|
|
7379
|
+
__name(logMaintenanceLeaseReleaseFailure, "logMaintenanceLeaseReleaseFailure");
|
|
7380
|
+
async function classifySessionLocation(service, sessionId) {
|
|
7381
|
+
return service.getSessionLocation(sessionId);
|
|
7382
|
+
}
|
|
7383
|
+
__name(classifySessionLocation, "classifySessionLocation");
|
|
7384
|
+
function sessionLocationError(sessionId) {
|
|
7385
|
+
return new Error(`Session archive conflict: ${sessionId}`);
|
|
7386
|
+
}
|
|
7387
|
+
__name(sessionLocationError, "sessionLocationError");
|
|
7388
|
+
function updateScheduledTaskForMaintenance(service, sessionId, action) {
|
|
7389
|
+
if (action === "archive") {
|
|
7390
|
+
return disableTasksForSessions(service.getProjectRoot(), [sessionId]);
|
|
7391
|
+
}
|
|
7392
|
+
if (action === "unarchive") {
|
|
7393
|
+
return enableTasksForSessions(service.getProjectRoot(), [sessionId]);
|
|
7394
|
+
}
|
|
7395
|
+
return removeTasksForSessions(service.getProjectRoot(), [sessionId]);
|
|
7396
|
+
}
|
|
7397
|
+
__name(updateScheduledTaskForMaintenance, "updateScheduledTaskForMaintenance");
|
|
7398
|
+
async function deletePersistedSessionWithLease(service, sessionId) {
|
|
7399
|
+
const initialLocation = await classifySessionLocation(service, sessionId);
|
|
7400
|
+
if (initialLocation === void 0) {
|
|
7401
|
+
return { kind: "notFound", mutationApplied: false };
|
|
7402
|
+
}
|
|
7403
|
+
if (initialLocation === "conflict") {
|
|
7404
|
+
return {
|
|
7405
|
+
kind: "error",
|
|
7406
|
+
error: sessionLocationError(sessionId),
|
|
7407
|
+
mutationApplied: false
|
|
7408
|
+
};
|
|
7409
|
+
}
|
|
7410
|
+
const mutation = await runWithDaemonWriterLease({
|
|
7411
|
+
action: "delete",
|
|
7412
|
+
sessionId,
|
|
7413
|
+
service,
|
|
7414
|
+
mutate: /* @__PURE__ */ __name(async (assertOwnedAndUnchanged) => {
|
|
7415
|
+
const lockedLocation = await classifySessionLocation(service, sessionId);
|
|
7416
|
+
if (lockedLocation === void 0) {
|
|
7417
|
+
return {
|
|
7418
|
+
value: "notFound",
|
|
7419
|
+
mutationApplied: false
|
|
7420
|
+
};
|
|
7421
|
+
}
|
|
7422
|
+
if (lockedLocation === "conflict") {
|
|
7423
|
+
throw sessionLocationError(sessionId);
|
|
7424
|
+
}
|
|
7425
|
+
await assertOwnedAndUnchanged();
|
|
7426
|
+
const removed = await service.removeSession(sessionId);
|
|
7427
|
+
return {
|
|
7428
|
+
value: removed ? "removed" : "notFound",
|
|
7429
|
+
mutationApplied: removed
|
|
7430
|
+
};
|
|
7431
|
+
}, "mutate"),
|
|
7432
|
+
mutationAppliedAfterError: /* @__PURE__ */ __name(async () => await classifySessionLocation(service, sessionId) === void 0, "mutationAppliedAfterError"),
|
|
7433
|
+
afterMutationApplied: /* @__PURE__ */ __name(() => updateScheduledTaskForMaintenance(service, sessionId, "delete"), "afterMutationApplied")
|
|
7434
|
+
});
|
|
7435
|
+
if (mutation.error !== void 0) {
|
|
7436
|
+
return {
|
|
7437
|
+
kind: "error",
|
|
7438
|
+
error: mutation.error,
|
|
7439
|
+
mutationApplied: mutation.mutationApplied
|
|
7440
|
+
};
|
|
7441
|
+
}
|
|
7442
|
+
return {
|
|
7443
|
+
kind: mutation.value ?? "notFound",
|
|
7444
|
+
mutationApplied: mutation.mutationApplied
|
|
7445
|
+
};
|
|
7446
|
+
}
|
|
7447
|
+
__name(deletePersistedSessionWithLease, "deletePersistedSessionWithLease");
|
|
6906
7448
|
async function deleteDaemonSessions(params) {
|
|
6907
7449
|
const { sessionIds, service, bridge, coordinator, onError } = params;
|
|
6908
7450
|
const uniqueSessionIds = [...new Set(sessionIds)];
|
|
6909
|
-
const closeErrors = [];
|
|
6910
|
-
const removed = [];
|
|
6911
|
-
const notFound = [];
|
|
6912
|
-
const removeErrors = [];
|
|
6913
7451
|
for (const sessionId of uniqueSessionIds) {
|
|
6914
7452
|
coordinator.assertNotTransitioning(sessionId);
|
|
6915
7453
|
}
|
|
6916
|
-
await Promise.all(
|
|
7454
|
+
const results = await Promise.all(
|
|
6917
7455
|
uniqueSessionIds.map(async (sessionId) => {
|
|
6918
7456
|
try {
|
|
6919
|
-
await coordinator.runExclusiveMany([sessionId], async () => {
|
|
6920
|
-
let shouldRemove = false;
|
|
7457
|
+
return await coordinator.runExclusiveMany([sessionId], async () => {
|
|
6921
7458
|
try {
|
|
6922
7459
|
await bridge.closeSession(sessionId);
|
|
6923
|
-
|
|
6924
|
-
|
|
6925
|
-
|
|
6926
|
-
|
|
6927
|
-
|
|
6928
|
-
|
|
6929
|
-
|
|
6930
|
-
|
|
7460
|
+
} catch (error2) {
|
|
7461
|
+
if (isSessionNotFoundError(error2)) {
|
|
7462
|
+
const result2 = await deletePersistedSessionWithLease(
|
|
7463
|
+
service,
|
|
7464
|
+
sessionId
|
|
7465
|
+
);
|
|
7466
|
+
if (result2.kind === "error") {
|
|
7467
|
+
onError?.({
|
|
7468
|
+
phase: "remove",
|
|
7469
|
+
sessionId,
|
|
7470
|
+
error: errorMessage(result2.error)
|
|
7471
|
+
});
|
|
7472
|
+
}
|
|
7473
|
+
return result2;
|
|
6931
7474
|
}
|
|
7475
|
+
onError?.({
|
|
7476
|
+
phase: "close",
|
|
7477
|
+
sessionId,
|
|
7478
|
+
error: errorMessage(error2)
|
|
7479
|
+
});
|
|
7480
|
+
return {
|
|
7481
|
+
kind: "error",
|
|
7482
|
+
error: error2,
|
|
7483
|
+
mutationApplied: false
|
|
7484
|
+
};
|
|
6932
7485
|
}
|
|
6933
|
-
|
|
6934
|
-
|
|
6935
|
-
|
|
6936
|
-
|
|
6937
|
-
|
|
6938
|
-
|
|
6939
|
-
|
|
6940
|
-
|
|
6941
|
-
|
|
6942
|
-
|
|
6943
|
-
removeErrors.push({ sessionId, error: message });
|
|
7486
|
+
const result = await deletePersistedSessionWithLease(
|
|
7487
|
+
service,
|
|
7488
|
+
sessionId
|
|
7489
|
+
);
|
|
7490
|
+
if (result.kind === "error") {
|
|
7491
|
+
onError?.({
|
|
7492
|
+
phase: "remove",
|
|
7493
|
+
sessionId,
|
|
7494
|
+
error: errorMessage(result.error)
|
|
7495
|
+
});
|
|
6944
7496
|
}
|
|
7497
|
+
return result;
|
|
6945
7498
|
});
|
|
6946
|
-
} catch (
|
|
6947
|
-
if (
|
|
6948
|
-
throw
|
|
7499
|
+
} catch (error2) {
|
|
7500
|
+
if (error2 instanceof DaemonDrainingError) {
|
|
7501
|
+
throw error2;
|
|
6949
7502
|
}
|
|
6950
|
-
|
|
6951
|
-
|
|
6952
|
-
|
|
7503
|
+
onError?.({
|
|
7504
|
+
phase: "delete",
|
|
7505
|
+
sessionId,
|
|
7506
|
+
error: errorMessage(error2)
|
|
7507
|
+
});
|
|
7508
|
+
return {
|
|
7509
|
+
kind: "error",
|
|
7510
|
+
error: error2,
|
|
7511
|
+
mutationApplied: false
|
|
7512
|
+
};
|
|
6953
7513
|
}
|
|
6954
7514
|
})
|
|
6955
7515
|
);
|
|
6956
|
-
|
|
6957
|
-
|
|
6958
|
-
|
|
6959
|
-
|
|
6960
|
-
|
|
7516
|
+
const removed = [];
|
|
7517
|
+
const notFound = [];
|
|
7518
|
+
const errors = [];
|
|
7519
|
+
for (let i = 0; i < results.length; i++) {
|
|
7520
|
+
const sessionId = uniqueSessionIds[i];
|
|
7521
|
+
const result = results[i];
|
|
7522
|
+
if (result.kind === "removed") {
|
|
7523
|
+
removed.push(sessionId);
|
|
7524
|
+
} else if (result.kind === "notFound") {
|
|
7525
|
+
notFound.push(sessionId);
|
|
7526
|
+
} else {
|
|
7527
|
+
errors.push({ sessionId, error: errorMessage(result.error) });
|
|
6961
7528
|
}
|
|
6962
|
-
|
|
6963
|
-
return { removed, notFound, errors
|
|
7529
|
+
}
|
|
7530
|
+
return { removed, notFound, errors };
|
|
6964
7531
|
}
|
|
6965
7532
|
__name(deleteDaemonSessions, "deleteDaemonSessions");
|
|
6966
|
-
async function
|
|
6967
|
-
const
|
|
6968
|
-
|
|
6969
|
-
)
|
|
7533
|
+
async function deleteDaemonSessionIfOrphan(params) {
|
|
7534
|
+
const { sessionId, service, bridge, coordinator } = params;
|
|
7535
|
+
coordinator.assertNotTransitioning(sessionId);
|
|
7536
|
+
const result = await coordinator.runExclusiveMany([sessionId], async () => {
|
|
7537
|
+
let killed = false;
|
|
7538
|
+
try {
|
|
7539
|
+
killed = await bridge.killSession(sessionId, {
|
|
7540
|
+
requireZeroAttaches: true
|
|
7541
|
+
});
|
|
7542
|
+
} catch (error2) {
|
|
7543
|
+
if (!isSessionNotFoundError(error2)) throw error2;
|
|
7544
|
+
killed = true;
|
|
7545
|
+
}
|
|
7546
|
+
if (!killed) {
|
|
7547
|
+
return void 0;
|
|
7548
|
+
}
|
|
7549
|
+
return deletePersistedSessionWithLease(service, sessionId);
|
|
7550
|
+
});
|
|
7551
|
+
if (result === void 0) {
|
|
7552
|
+
return false;
|
|
7553
|
+
}
|
|
7554
|
+
if (result.kind === "error") {
|
|
7555
|
+
throw result.error;
|
|
7556
|
+
}
|
|
7557
|
+
return true;
|
|
7558
|
+
}
|
|
7559
|
+
__name(deleteDaemonSessionIfOrphan, "deleteDaemonSessionIfOrphan");
|
|
7560
|
+
async function assertSessionLoadable(workspaceCwd, sessionId, runtimeBaseDir) {
|
|
7561
|
+
const location = await new SessionService(workspaceCwd, {
|
|
7562
|
+
runtimeBaseDir
|
|
7563
|
+
}).getSessionLocation(sessionId);
|
|
6970
7564
|
if (location === "archived") {
|
|
6971
7565
|
throw new SessionArchivedError(sessionId);
|
|
6972
7566
|
}
|
|
@@ -6976,10 +7570,10 @@ async function assertSessionLoadable(workspaceCwd, sessionId) {
|
|
|
6976
7570
|
return location;
|
|
6977
7571
|
}
|
|
6978
7572
|
__name(assertSessionLoadable, "assertSessionLoadable");
|
|
6979
|
-
async function assertSessionArchived(workspaceCwd, sessionId) {
|
|
6980
|
-
const location = await new SessionService(workspaceCwd
|
|
6981
|
-
|
|
6982
|
-
);
|
|
7573
|
+
async function assertSessionArchived(workspaceCwd, sessionId, runtimeBaseDir) {
|
|
7574
|
+
const location = await new SessionService(workspaceCwd, {
|
|
7575
|
+
runtimeBaseDir
|
|
7576
|
+
}).getSessionLocation(sessionId);
|
|
6983
7577
|
if (location === "active") {
|
|
6984
7578
|
throw new SessionNotArchivedError(sessionId);
|
|
6985
7579
|
}
|
|
@@ -6995,43 +7589,6 @@ function isSessionNotFoundError(err) {
|
|
|
6995
7589
|
return err instanceof SessionNotFoundError || err instanceof Error && err.name === "SessionNotFoundError";
|
|
6996
7590
|
}
|
|
6997
7591
|
__name(isSessionNotFoundError, "isSessionNotFoundError");
|
|
6998
|
-
async function classifySessionLocations(service, sessionIds) {
|
|
6999
|
-
const result = {
|
|
7000
|
-
active: [],
|
|
7001
|
-
archived: [],
|
|
7002
|
-
notFound: [],
|
|
7003
|
-
errors: []
|
|
7004
|
-
};
|
|
7005
|
-
const locationResults = await Promise.allSettled(
|
|
7006
|
-
sessionIds.map(async (sessionId) => ({
|
|
7007
|
-
sessionId,
|
|
7008
|
-
location: await service.getSessionLocation(sessionId)
|
|
7009
|
-
}))
|
|
7010
|
-
);
|
|
7011
|
-
for (let i = 0; i < locationResults.length; i++) {
|
|
7012
|
-
const sessionId = sessionIds[i];
|
|
7013
|
-
const locationResult = locationResults[i];
|
|
7014
|
-
if (locationResult.status === "rejected") {
|
|
7015
|
-
result.errors.push({ sessionId, error: locationResult.reason });
|
|
7016
|
-
continue;
|
|
7017
|
-
}
|
|
7018
|
-
const location = locationResult.value.location;
|
|
7019
|
-
if (location === void 0) {
|
|
7020
|
-
result.notFound.push(sessionId);
|
|
7021
|
-
} else if (location === "archived") {
|
|
7022
|
-
result.archived.push(sessionId);
|
|
7023
|
-
} else if (location === "conflict") {
|
|
7024
|
-
result.errors.push({
|
|
7025
|
-
sessionId,
|
|
7026
|
-
error: new Error(`Session archive conflict: ${sessionId}`)
|
|
7027
|
-
});
|
|
7028
|
-
} else {
|
|
7029
|
-
result.active.push(sessionId);
|
|
7030
|
-
}
|
|
7031
|
-
}
|
|
7032
|
-
return result;
|
|
7033
|
-
}
|
|
7034
|
-
__name(classifySessionLocations, "classifySessionLocations");
|
|
7035
7592
|
function logSessionArchiveResult(action, result) {
|
|
7036
7593
|
const changedLabel = action === "archive" ? "archived" : "unarchived";
|
|
7037
7594
|
const alreadyLabel = action === "archive" ? "alreadyArchived" : "alreadyActive";
|
|
@@ -7071,59 +7628,126 @@ __name(sanitizeLogLine, "sanitizeLogLine");
|
|
|
7071
7628
|
async function archiveDaemonSessions(params) {
|
|
7072
7629
|
const { sessionIds, service, bridge, coordinator } = params;
|
|
7073
7630
|
const uniqueSessionIds = [...new Set(sessionIds)];
|
|
7074
|
-
const
|
|
7075
|
-
|
|
7076
|
-
|
|
7077
|
-
const
|
|
7078
|
-
|
|
7079
|
-
|
|
7080
|
-
|
|
7081
|
-
notFound.push(...initial.notFound);
|
|
7082
|
-
errors.push(...initial.errors);
|
|
7083
|
-
if (activeIds.length > 0) {
|
|
7084
|
-
await coordinator.runExclusiveMany(activeIds, async () => {
|
|
7085
|
-
const locked = await classifySessionLocations(service, activeIds);
|
|
7086
|
-
const closableIds = locked.active;
|
|
7087
|
-
alreadyArchived.push(...locked.archived);
|
|
7088
|
-
notFound.push(...locked.notFound);
|
|
7089
|
-
errors.push(...locked.errors);
|
|
7090
|
-
const closeResults = await Promise.allSettled(
|
|
7091
|
-
closableIds.map(async (sessionId) => {
|
|
7631
|
+
for (const sessionId of uniqueSessionIds) {
|
|
7632
|
+
coordinator.assertNotTransitioning(sessionId);
|
|
7633
|
+
}
|
|
7634
|
+
const results = await Promise.all(
|
|
7635
|
+
uniqueSessionIds.map(async (sessionId) => {
|
|
7636
|
+
try {
|
|
7637
|
+
return await coordinator.runExclusiveMany([sessionId], async () => {
|
|
7092
7638
|
try {
|
|
7093
7639
|
await bridge.closeSession(sessionId, void 0, {
|
|
7094
7640
|
requireAgentClose: true
|
|
7095
7641
|
});
|
|
7096
|
-
} catch (
|
|
7097
|
-
if (!isSessionNotFoundError(
|
|
7098
|
-
|
|
7642
|
+
} catch (error2) {
|
|
7643
|
+
if (!isSessionNotFoundError(error2)) {
|
|
7644
|
+
return {
|
|
7645
|
+
kind: "error",
|
|
7646
|
+
error: error2,
|
|
7647
|
+
mutationApplied: false
|
|
7648
|
+
};
|
|
7099
7649
|
}
|
|
7100
7650
|
}
|
|
7101
|
-
|
|
7102
|
-
|
|
7103
|
-
|
|
7104
|
-
|
|
7105
|
-
|
|
7106
|
-
|
|
7107
|
-
|
|
7108
|
-
|
|
7109
|
-
|
|
7110
|
-
|
|
7111
|
-
|
|
7112
|
-
|
|
7113
|
-
|
|
7114
|
-
|
|
7115
|
-
|
|
7651
|
+
const initialLocation = await classifySessionLocation(
|
|
7652
|
+
service,
|
|
7653
|
+
sessionId
|
|
7654
|
+
);
|
|
7655
|
+
if (initialLocation === void 0) {
|
|
7656
|
+
return { kind: "notFound", mutationApplied: false };
|
|
7657
|
+
}
|
|
7658
|
+
if (initialLocation === "archived") {
|
|
7659
|
+
return {
|
|
7660
|
+
kind: "alreadyArchived",
|
|
7661
|
+
mutationApplied: false
|
|
7662
|
+
};
|
|
7663
|
+
}
|
|
7664
|
+
if (initialLocation === "conflict") {
|
|
7665
|
+
return {
|
|
7666
|
+
kind: "error",
|
|
7667
|
+
error: sessionLocationError(sessionId),
|
|
7668
|
+
mutationApplied: false
|
|
7669
|
+
};
|
|
7670
|
+
}
|
|
7671
|
+
const mutation = await runWithDaemonWriterLease({
|
|
7672
|
+
action: "archive",
|
|
7673
|
+
sessionId,
|
|
7674
|
+
service,
|
|
7675
|
+
mutate: /* @__PURE__ */ __name(async (assertOwnedAndUnchanged) => {
|
|
7676
|
+
const lockedLocation = await classifySessionLocation(
|
|
7677
|
+
service,
|
|
7678
|
+
sessionId
|
|
7679
|
+
);
|
|
7680
|
+
if (lockedLocation === void 0) {
|
|
7681
|
+
return {
|
|
7682
|
+
value: "notFound",
|
|
7683
|
+
mutationApplied: false
|
|
7684
|
+
};
|
|
7685
|
+
}
|
|
7686
|
+
if (lockedLocation === "archived") {
|
|
7687
|
+
return {
|
|
7688
|
+
value: "alreadyArchived",
|
|
7689
|
+
mutationApplied: false
|
|
7690
|
+
};
|
|
7691
|
+
}
|
|
7692
|
+
if (lockedLocation === "conflict") {
|
|
7693
|
+
throw sessionLocationError(sessionId);
|
|
7694
|
+
}
|
|
7695
|
+
await assertOwnedAndUnchanged();
|
|
7696
|
+
const result = await service.archiveSessions([sessionId], {
|
|
7697
|
+
knownLocation: "active"
|
|
7698
|
+
});
|
|
7699
|
+
if (result.errors[0]) throw result.errors[0].error;
|
|
7700
|
+
if (result.archived.length > 0) {
|
|
7701
|
+
return {
|
|
7702
|
+
value: "archived",
|
|
7703
|
+
mutationApplied: true
|
|
7704
|
+
};
|
|
7705
|
+
}
|
|
7706
|
+
return {
|
|
7707
|
+
value: result.alreadyArchived.length > 0 ? "alreadyArchived" : "notFound",
|
|
7708
|
+
mutationApplied: false
|
|
7709
|
+
};
|
|
7710
|
+
}, "mutate"),
|
|
7711
|
+
mutationAppliedAfterError: /* @__PURE__ */ __name(async () => await classifySessionLocation(service, sessionId) === "archived", "mutationAppliedAfterError"),
|
|
7712
|
+
afterMutationApplied: /* @__PURE__ */ __name(() => updateScheduledTaskForMaintenance(service, sessionId, "archive"), "afterMutationApplied")
|
|
7713
|
+
});
|
|
7714
|
+
if (mutation.error !== void 0) {
|
|
7715
|
+
return {
|
|
7716
|
+
kind: "error",
|
|
7717
|
+
error: mutation.error,
|
|
7718
|
+
mutationApplied: mutation.mutationApplied
|
|
7719
|
+
};
|
|
7720
|
+
}
|
|
7721
|
+
return {
|
|
7722
|
+
kind: mutation.value ?? "notFound",
|
|
7723
|
+
mutationApplied: mutation.mutationApplied
|
|
7724
|
+
};
|
|
7116
7725
|
});
|
|
7117
|
-
|
|
7118
|
-
|
|
7119
|
-
|
|
7120
|
-
errors.push(...archiveResult.errors);
|
|
7121
|
-
} catch (err) {
|
|
7122
|
-
for (const sessionId of archiveIds) {
|
|
7123
|
-
errors.push({ sessionId, error: err });
|
|
7726
|
+
} catch (error2) {
|
|
7727
|
+
if (error2 instanceof DaemonDrainingError) {
|
|
7728
|
+
throw error2;
|
|
7124
7729
|
}
|
|
7730
|
+
return {
|
|
7731
|
+
kind: "error",
|
|
7732
|
+
error: error2,
|
|
7733
|
+
mutationApplied: false,
|
|
7734
|
+
maintenanceError: void 0
|
|
7735
|
+
};
|
|
7125
7736
|
}
|
|
7126
|
-
})
|
|
7737
|
+
})
|
|
7738
|
+
);
|
|
7739
|
+
const archived = [];
|
|
7740
|
+
const alreadyArchived = [];
|
|
7741
|
+
const notFound = [];
|
|
7742
|
+
const errors = [];
|
|
7743
|
+
for (let i = 0; i < results.length; i++) {
|
|
7744
|
+
const sessionId = uniqueSessionIds[i];
|
|
7745
|
+
const result = results[i];
|
|
7746
|
+
if (result.kind === "archived") archived.push(sessionId);
|
|
7747
|
+
else if (result.kind === "alreadyArchived") {
|
|
7748
|
+
alreadyArchived.push(sessionId);
|
|
7749
|
+
} else if (result.kind === "notFound") notFound.push(sessionId);
|
|
7750
|
+
else errors.push({ sessionId, error: result.error });
|
|
7127
7751
|
}
|
|
7128
7752
|
logSessionArchiveResult("archive", {
|
|
7129
7753
|
requested: uniqueSessionIds,
|
|
@@ -7132,51 +7756,144 @@ async function archiveDaemonSessions(params) {
|
|
|
7132
7756
|
notFound,
|
|
7133
7757
|
errors
|
|
7134
7758
|
});
|
|
7135
|
-
await disableTasksForSessions(service.getProjectRoot(), archived).catch(
|
|
7136
|
-
(err) => {
|
|
7137
|
-
logSessionArchiveWarning(
|
|
7138
|
-
`disableTasksForSessions failed for [${archived.join(", ")}]: ${err instanceof Error ? err.message : String(err)} \u2014 bound tasks may keep firing until reconciled`
|
|
7139
|
-
);
|
|
7140
|
-
}
|
|
7141
|
-
);
|
|
7142
7759
|
return { archived, alreadyArchived, notFound, errors };
|
|
7143
7760
|
}
|
|
7144
7761
|
__name(archiveDaemonSessions, "archiveDaemonSessions");
|
|
7145
7762
|
async function unarchiveDaemonSessions(params) {
|
|
7146
7763
|
const { sessionIds, service, coordinator } = params;
|
|
7147
7764
|
const uniqueSessionIds = [...new Set(sessionIds)];
|
|
7148
|
-
const
|
|
7149
|
-
|
|
7150
|
-
|
|
7151
|
-
const
|
|
7152
|
-
|
|
7153
|
-
|
|
7154
|
-
|
|
7155
|
-
|
|
7156
|
-
|
|
7157
|
-
|
|
7158
|
-
|
|
7159
|
-
|
|
7160
|
-
|
|
7161
|
-
|
|
7162
|
-
|
|
7163
|
-
|
|
7164
|
-
|
|
7165
|
-
|
|
7166
|
-
|
|
7167
|
-
|
|
7765
|
+
for (const sessionId of uniqueSessionIds) {
|
|
7766
|
+
coordinator.assertNotTransitioning(sessionId);
|
|
7767
|
+
}
|
|
7768
|
+
const results = await Promise.all(
|
|
7769
|
+
uniqueSessionIds.map(async (sessionId) => {
|
|
7770
|
+
try {
|
|
7771
|
+
return await coordinator.runExclusiveMany([sessionId], async () => {
|
|
7772
|
+
const initialLocation = await classifySessionLocation(
|
|
7773
|
+
service,
|
|
7774
|
+
sessionId
|
|
7775
|
+
);
|
|
7776
|
+
if (initialLocation === void 0) {
|
|
7777
|
+
return { kind: "notFound", mutationApplied: false };
|
|
7778
|
+
}
|
|
7779
|
+
if (initialLocation === "active") {
|
|
7780
|
+
let maintenanceError;
|
|
7781
|
+
try {
|
|
7782
|
+
await updateScheduledTaskForMaintenance(
|
|
7783
|
+
service,
|
|
7784
|
+
sessionId,
|
|
7785
|
+
"unarchive"
|
|
7786
|
+
);
|
|
7787
|
+
} catch (error2) {
|
|
7788
|
+
maintenanceError = error2;
|
|
7789
|
+
logSessionArchiveWarning(
|
|
7790
|
+
`scheduled task lifecycle update failed action=unarchive workspace=${safeLogValue(
|
|
7791
|
+
service.getProjectRoot()
|
|
7792
|
+
)} session=${safeLogValue(sessionId)} error=${safeLogValue(
|
|
7793
|
+
errorMessage(error2)
|
|
7794
|
+
)}`
|
|
7795
|
+
);
|
|
7796
|
+
}
|
|
7797
|
+
return {
|
|
7798
|
+
kind: "alreadyActive",
|
|
7799
|
+
mutationApplied: false,
|
|
7800
|
+
maintenanceError
|
|
7801
|
+
};
|
|
7802
|
+
}
|
|
7803
|
+
if (initialLocation === "conflict") {
|
|
7804
|
+
return {
|
|
7805
|
+
kind: "error",
|
|
7806
|
+
error: sessionLocationError(sessionId),
|
|
7807
|
+
mutationApplied: false
|
|
7808
|
+
};
|
|
7809
|
+
}
|
|
7810
|
+
const mutation = await runWithDaemonWriterLease({
|
|
7811
|
+
action: "unarchive",
|
|
7812
|
+
sessionId,
|
|
7813
|
+
service,
|
|
7814
|
+
mutate: /* @__PURE__ */ __name(async (assertOwnedAndUnchanged) => {
|
|
7815
|
+
const lockedLocation = await classifySessionLocation(
|
|
7816
|
+
service,
|
|
7817
|
+
sessionId
|
|
7818
|
+
);
|
|
7819
|
+
if (lockedLocation === void 0) {
|
|
7820
|
+
return {
|
|
7821
|
+
value: "notFound",
|
|
7822
|
+
mutationApplied: false
|
|
7823
|
+
};
|
|
7824
|
+
}
|
|
7825
|
+
if (lockedLocation === "active") {
|
|
7826
|
+
return {
|
|
7827
|
+
value: "alreadyActive",
|
|
7828
|
+
mutationApplied: false
|
|
7829
|
+
};
|
|
7830
|
+
}
|
|
7831
|
+
if (lockedLocation === "conflict") {
|
|
7832
|
+
throw sessionLocationError(sessionId);
|
|
7833
|
+
}
|
|
7834
|
+
await assertOwnedAndUnchanged();
|
|
7835
|
+
const result = await service.unarchiveSessions([sessionId], {
|
|
7836
|
+
knownLocation: "archived"
|
|
7837
|
+
});
|
|
7838
|
+
if (result.errors[0]) throw result.errors[0].error;
|
|
7839
|
+
if (result.unarchived.length > 0) {
|
|
7840
|
+
return {
|
|
7841
|
+
value: "unarchived",
|
|
7842
|
+
mutationApplied: true
|
|
7843
|
+
};
|
|
7844
|
+
}
|
|
7845
|
+
return {
|
|
7846
|
+
value: result.alreadyActive.length > 0 ? "alreadyActive" : "notFound",
|
|
7847
|
+
mutationApplied: false
|
|
7848
|
+
};
|
|
7849
|
+
}, "mutate"),
|
|
7850
|
+
mutationAppliedAfterError: /* @__PURE__ */ __name(async () => await classifySessionLocation(service, sessionId) === "active", "mutationAppliedAfterError"),
|
|
7851
|
+
afterMutationApplied: /* @__PURE__ */ __name(() => updateScheduledTaskForMaintenance(
|
|
7852
|
+
service,
|
|
7853
|
+
sessionId,
|
|
7854
|
+
"unarchive"
|
|
7855
|
+
), "afterMutationApplied")
|
|
7168
7856
|
});
|
|
7169
|
-
|
|
7170
|
-
|
|
7171
|
-
|
|
7172
|
-
|
|
7173
|
-
|
|
7174
|
-
|
|
7175
|
-
errors.push({ sessionId, error: err });
|
|
7857
|
+
if (mutation.error !== void 0) {
|
|
7858
|
+
return {
|
|
7859
|
+
kind: "error",
|
|
7860
|
+
error: mutation.error,
|
|
7861
|
+
mutationApplied: mutation.mutationApplied
|
|
7862
|
+
};
|
|
7176
7863
|
}
|
|
7864
|
+
return {
|
|
7865
|
+
kind: mutation.value ?? "notFound",
|
|
7866
|
+
mutationApplied: mutation.mutationApplied,
|
|
7867
|
+
maintenanceError: mutation.maintenanceError
|
|
7868
|
+
};
|
|
7869
|
+
});
|
|
7870
|
+
} catch (error2) {
|
|
7871
|
+
if (error2 instanceof DaemonDrainingError) {
|
|
7872
|
+
throw error2;
|
|
7177
7873
|
}
|
|
7874
|
+
return {
|
|
7875
|
+
kind: "error",
|
|
7876
|
+
error: error2,
|
|
7877
|
+
mutationApplied: false,
|
|
7878
|
+
maintenanceError: void 0
|
|
7879
|
+
};
|
|
7178
7880
|
}
|
|
7179
|
-
})
|
|
7881
|
+
})
|
|
7882
|
+
);
|
|
7883
|
+
const unarchived = [];
|
|
7884
|
+
const alreadyActive = [];
|
|
7885
|
+
const notFound = [];
|
|
7886
|
+
const errors = [];
|
|
7887
|
+
for (let i = 0; i < results.length; i++) {
|
|
7888
|
+
const sessionId = uniqueSessionIds[i];
|
|
7889
|
+
const result = results[i];
|
|
7890
|
+
if (result.kind === "unarchived") unarchived.push(sessionId);
|
|
7891
|
+
else if (result.kind === "alreadyActive") alreadyActive.push(sessionId);
|
|
7892
|
+
else if (result.kind === "notFound") notFound.push(sessionId);
|
|
7893
|
+
else errors.push({ sessionId, error: result.error });
|
|
7894
|
+
if (result.maintenanceError !== void 0) {
|
|
7895
|
+
errors.push({ sessionId, error: result.maintenanceError });
|
|
7896
|
+
}
|
|
7180
7897
|
}
|
|
7181
7898
|
logSessionArchiveResult("unarchive", {
|
|
7182
7899
|
requested: uniqueSessionIds,
|
|
@@ -7185,17 +7902,6 @@ async function unarchiveDaemonSessions(params) {
|
|
|
7185
7902
|
notFound,
|
|
7186
7903
|
errors
|
|
7187
7904
|
});
|
|
7188
|
-
const resumeSessionIds = [.../* @__PURE__ */ new Set([...unarchived, ...alreadyActive])];
|
|
7189
|
-
try {
|
|
7190
|
-
await enableTasksForSessions(service.getProjectRoot(), resumeSessionIds);
|
|
7191
|
-
} catch (err) {
|
|
7192
|
-
logSessionArchiveWarning(
|
|
7193
|
-
`enableTasksForSessions failed for [${resumeSessionIds.join(", ")}]: ${err instanceof Error ? err.message : String(err)}`
|
|
7194
|
-
);
|
|
7195
|
-
for (const sessionId of resumeSessionIds) {
|
|
7196
|
-
errors.push({ sessionId, error: err });
|
|
7197
|
-
}
|
|
7198
|
-
}
|
|
7199
7905
|
return { unarchived, alreadyActive, notFound, errors };
|
|
7200
7906
|
}
|
|
7201
7907
|
__name(unarchiveDaemonSessions, "unarchiveDaemonSessions");
|
|
@@ -7596,6 +8302,13 @@ function pickSessionArtifactInput(params) {
|
|
|
7596
8302
|
}
|
|
7597
8303
|
__name(pickSessionArtifactInput, "pickSessionArtifactInput");
|
|
7598
8304
|
function toRpcError(err) {
|
|
8305
|
+
if (err instanceof DaemonDrainingError) {
|
|
8306
|
+
return {
|
|
8307
|
+
code: RPC.INTERNAL_ERROR,
|
|
8308
|
+
message: err.message,
|
|
8309
|
+
data: { errorKind: "daemon_draining" }
|
|
8310
|
+
};
|
|
8311
|
+
}
|
|
7599
8312
|
const writerError = sessionWriterRpcError(err);
|
|
7600
8313
|
if (writerError) return writerError;
|
|
7601
8314
|
if (err instanceof AcpParamError || err instanceof InvalidCursorError) {
|
|
@@ -7804,7 +8517,7 @@ function rpcErrorFrame(id, err) {
|
|
|
7804
8517
|
__name(rpcErrorFrame, "rpcErrorFrame");
|
|
7805
8518
|
var ACP_PROTOCOL_VERSION = 1;
|
|
7806
8519
|
var AcpDispatcher = class {
|
|
7807
|
-
constructor(bridge, boundWorkspace, getEnv, workspace, workspaceRememberLane, fsFactory, deviceFlowRegistry, sessionShellCommandEnabled = false, registry, archiveCoordinator = new SessionArchiveCoordinator(), isWorkspaceTrusted = () => true, captureGenerationAssertion = () => void 0) {
|
|
8520
|
+
constructor(bridge, boundWorkspace, getEnv, workspace, workspaceRememberLane, fsFactory, deviceFlowRegistry, sessionShellCommandEnabled = false, registry, archiveCoordinator = new SessionArchiveCoordinator(), isWorkspaceTrusted = () => true, captureGenerationAssertion = () => void 0, sessionRuntimeBaseDir = Storage.getRuntimeBaseDir()) {
|
|
7808
8521
|
this.bridge = bridge;
|
|
7809
8522
|
this.boundWorkspace = boundWorkspace;
|
|
7810
8523
|
this.getEnv = getEnv;
|
|
@@ -7817,6 +8530,7 @@ var AcpDispatcher = class {
|
|
|
7817
8530
|
this.archiveCoordinator = archiveCoordinator;
|
|
7818
8531
|
this.isWorkspaceTrusted = isWorkspaceTrusted;
|
|
7819
8532
|
this.captureGenerationAssertion = captureGenerationAssertion;
|
|
8533
|
+
this.sessionRuntimeBaseDir = sessionRuntimeBaseDir;
|
|
7820
8534
|
this.agentManager = createDaemonSubagentManager(boundWorkspace);
|
|
7821
8535
|
}
|
|
7822
8536
|
static {
|
|
@@ -7824,13 +8538,15 @@ var AcpDispatcher = class {
|
|
|
7824
8538
|
}
|
|
7825
8539
|
agentManager;
|
|
7826
8540
|
killOrphanSession(sessionId, removePersistedSession = false) {
|
|
7827
|
-
|
|
7828
|
-
|
|
7829
|
-
|
|
7830
|
-
|
|
7831
|
-
|
|
7832
|
-
|
|
7833
|
-
|
|
8541
|
+
const cleanup = removePersistedSession ? deleteDaemonSessionIfOrphan({
|
|
8542
|
+
sessionId,
|
|
8543
|
+
service: new SessionService(this.boundWorkspace, {
|
|
8544
|
+
runtimeBaseDir: this.sessionRuntimeBaseDir
|
|
8545
|
+
}),
|
|
8546
|
+
bridge: this.bridge,
|
|
8547
|
+
coordinator: this.archiveCoordinator
|
|
8548
|
+
}) : this.bridge.killSession(sessionId, { requireZeroAttaches: true });
|
|
8549
|
+
void cleanup.catch(
|
|
7834
8550
|
(err) => writeStderrLine(
|
|
7835
8551
|
`qwen serve: /acp orphan killSession(${logSafe(sessionId)}) failed: ${logSafe(errMsg(err))}`
|
|
7836
8552
|
)
|
|
@@ -8080,6 +8796,12 @@ var AcpDispatcher = class {
|
|
|
8080
8796
|
* (it mints the connection) and never reaches here.
|
|
8081
8797
|
*/
|
|
8082
8798
|
async handle(conn, msg, sessionHeader, reqLoopback) {
|
|
8799
|
+
return Storage.runWithResolvedRuntimeBaseDir(
|
|
8800
|
+
this.sessionRuntimeBaseDir,
|
|
8801
|
+
() => this.handleInRuntime(conn, msg, sessionHeader, reqLoopback)
|
|
8802
|
+
);
|
|
8803
|
+
}
|
|
8804
|
+
async handleInRuntime(conn, msg, sessionHeader, reqLoopback) {
|
|
8083
8805
|
const loopback = reqLoopback ?? conn.fromLoopback;
|
|
8084
8806
|
if (isResponse(msg)) {
|
|
8085
8807
|
try {
|
|
@@ -9926,8 +10648,26 @@ var AcpDispatcher = class {
|
|
|
9926
10648
|
);
|
|
9927
10649
|
return;
|
|
9928
10650
|
}
|
|
10651
|
+
const rawCursor = params["cursor"];
|
|
10652
|
+
if (rawCursor !== void 0 && (typeof rawCursor !== "string" || rawCursor.length === 0 || rawCursor.length > MAX_TEXT_CURSOR_CHARS)) {
|
|
10653
|
+
if (id !== void 0)
|
|
10654
|
+
conn.sendConn(
|
|
10655
|
+
error(
|
|
10656
|
+
id,
|
|
10657
|
+
RPC.INVALID_PARAMS,
|
|
10658
|
+
`\`cursor\` must be a non-empty string of at most ${MAX_TEXT_CURSOR_CHARS} characters`
|
|
10659
|
+
)
|
|
10660
|
+
);
|
|
10661
|
+
return;
|
|
10662
|
+
}
|
|
10663
|
+
const cursor = rawCursor;
|
|
9929
10664
|
const resolved = await fs6.resolve(p, "read");
|
|
9930
|
-
const out = await fs6.readText(resolved, {
|
|
10665
|
+
const out = await fs6.readText(resolved, {
|
|
10666
|
+
maxBytes,
|
|
10667
|
+
line,
|
|
10668
|
+
limit,
|
|
10669
|
+
cursor
|
|
10670
|
+
});
|
|
9931
10671
|
this.replyConn(conn, id, {
|
|
9932
10672
|
path: p,
|
|
9933
10673
|
content: out.content,
|
|
@@ -13061,7 +13801,8 @@ function mountAcpHttp(app, bridge, opts) {
|
|
|
13061
13801
|
() => {
|
|
13062
13802
|
const guard = opts.workspaceRegistry?.primaryEntry.current?.guard;
|
|
13063
13803
|
return guard ? () => guard.assertOpen() : void 0;
|
|
13064
|
-
}
|
|
13804
|
+
},
|
|
13805
|
+
opts.workspaceRegistry?.primary.sessionRuntimeBaseDir ?? Storage.getRuntimeBaseDir()
|
|
13065
13806
|
);
|
|
13066
13807
|
dispatcherRef.current = dispatcher;
|
|
13067
13808
|
const primaryMount = {
|
|
@@ -13368,7 +14109,8 @@ function mountAcpHttp(app, bridge, opts) {
|
|
|
13368
14109
|
() => {
|
|
13369
14110
|
const guard = rt.generationGuard;
|
|
13370
14111
|
return guard ? () => guard.assertOpen() : void 0;
|
|
13371
|
-
}
|
|
14112
|
+
},
|
|
14113
|
+
rt.sessionRuntimeBaseDir
|
|
13372
14114
|
);
|
|
13373
14115
|
secondaryDispatcherRef.current = secondaryDispatcher;
|
|
13374
14116
|
return {
|
|
@@ -16646,13 +17388,17 @@ function createExtensionsController(deps) {
|
|
|
16646
17388
|
const startedAt = Date.now();
|
|
16647
17389
|
try {
|
|
16648
17390
|
runtime.workspaceService.invalidateWorkspaceSkillsStatus();
|
|
16649
|
-
|
|
16650
|
-
|
|
16651
|
-
|
|
16652
|
-
|
|
16653
|
-
|
|
16654
|
-
|
|
16655
|
-
|
|
17391
|
+
try {
|
|
17392
|
+
return {
|
|
17393
|
+
status: "fulfilled",
|
|
17394
|
+
result: await runtime.bridge.refreshExtensionsForAllSessions(
|
|
17395
|
+
bridgeMutationEvent(event)
|
|
17396
|
+
),
|
|
17397
|
+
elapsedMs: Date.now() - startedAt
|
|
17398
|
+
};
|
|
17399
|
+
} finally {
|
|
17400
|
+
runtime.workspaceService.invalidateWorkspaceSkillsStatus();
|
|
17401
|
+
}
|
|
16656
17402
|
} catch (reason) {
|
|
16657
17403
|
return {
|
|
16658
17404
|
status: "rejected",
|
|
@@ -16727,10 +17473,14 @@ function createExtensionsController(deps) {
|
|
|
16727
17473
|
const { result, elapsedMs } = await runReconciliation(async () => {
|
|
16728
17474
|
workspace.invalidateWorkspaceSkillsStatus();
|
|
16729
17475
|
const startedAt = Date.now();
|
|
16730
|
-
|
|
16731
|
-
|
|
16732
|
-
|
|
16733
|
-
|
|
17476
|
+
try {
|
|
17477
|
+
const result2 = await bridge.refreshExtensionsForAllSessions(
|
|
17478
|
+
bridgeMutationEvent(event)
|
|
17479
|
+
);
|
|
17480
|
+
return { result: result2, elapsedMs: Date.now() - startedAt };
|
|
17481
|
+
} finally {
|
|
17482
|
+
workspace.invalidateWorkspaceSkillsStatus();
|
|
17483
|
+
}
|
|
16734
17484
|
});
|
|
16735
17485
|
const warnings = [...commitWarnings];
|
|
16736
17486
|
if (result.failed > 0) {
|
|
@@ -17249,11 +17999,15 @@ function registerWorkspaceExtensionRoutes(app, deps) {
|
|
|
17249
17999
|
async () => await Promise.allSettled(
|
|
17250
18000
|
runtimes.map(async (runtime) => {
|
|
17251
18001
|
runtime.workspaceService.invalidateWorkspaceSkillsStatus();
|
|
17252
|
-
|
|
17253
|
-
|
|
17254
|
-
|
|
17255
|
-
|
|
17256
|
-
|
|
18002
|
+
try {
|
|
18003
|
+
const result = await runtime.bridge.refreshExtensionsForAllSessions();
|
|
18004
|
+
if (result.failed > 0) {
|
|
18005
|
+
throw new Error(
|
|
18006
|
+
`${result.failed} extension session refresh(es) failed`
|
|
18007
|
+
);
|
|
18008
|
+
}
|
|
18009
|
+
} finally {
|
|
18010
|
+
runtime.workspaceService.invalidateWorkspaceSkillsStatus();
|
|
17257
18011
|
}
|
|
17258
18012
|
})
|
|
17259
18013
|
)
|
|
@@ -19071,6 +19825,12 @@ var legacySessionTelemetryRoutes = [
|
|
|
19071
19825
|
attribution: "handler_resolved",
|
|
19072
19826
|
route: "POST /session/:id/fork"
|
|
19073
19827
|
},
|
|
19828
|
+
{
|
|
19829
|
+
method: "POST",
|
|
19830
|
+
path: "/session/:id/side-task",
|
|
19831
|
+
attribution: "handler_resolved",
|
|
19832
|
+
route: "POST /session/:id/side-task"
|
|
19833
|
+
},
|
|
19074
19834
|
{
|
|
19075
19835
|
method: "POST",
|
|
19076
19836
|
path: "/session/:id/cd",
|
|
@@ -21045,10 +21805,8 @@ var VirtualSubagentSessions = class {
|
|
|
21045
21805
|
totalTokens: task.stats?.totalTokens
|
|
21046
21806
|
};
|
|
21047
21807
|
}
|
|
21048
|
-
const
|
|
21049
|
-
|
|
21050
|
-
runtimeDir,
|
|
21051
|
-
runtime.workspaceCwd,
|
|
21808
|
+
const projectDir = Storage.runWithResolvedRuntimeBaseDir(
|
|
21809
|
+
runtime.sessionRuntimeBaseDir,
|
|
21052
21810
|
() => new Storage(runtime.workspaceCwd).getProjectDir()
|
|
21053
21811
|
);
|
|
21054
21812
|
const sessionDir = getSubagentSessionDir(projectDir, parentSessionId);
|
|
@@ -21083,10 +21841,8 @@ var VirtualSubagentSessions = class {
|
|
|
21083
21841
|
return void 0;
|
|
21084
21842
|
}
|
|
21085
21843
|
async findLegacyTaskByToolCall(runtime, parentSessionId, toolCallId) {
|
|
21086
|
-
const
|
|
21087
|
-
|
|
21088
|
-
runtimeDir,
|
|
21089
|
-
runtime.workspaceCwd,
|
|
21844
|
+
const projectDir = Storage.runWithResolvedRuntimeBaseDir(
|
|
21845
|
+
runtime.sessionRuntimeBaseDir,
|
|
21090
21846
|
() => new Storage(runtime.workspaceCwd).getProjectDir()
|
|
21091
21847
|
);
|
|
21092
21848
|
const parentRecords = await read(
|
|
@@ -21159,10 +21915,8 @@ var VirtualSubagentSessions = class {
|
|
|
21159
21915
|
};
|
|
21160
21916
|
}
|
|
21161
21917
|
async readParentToolCallMetrics(runtime, parentSessionId, toolCallId) {
|
|
21162
|
-
const
|
|
21163
|
-
|
|
21164
|
-
runtimeDir,
|
|
21165
|
-
runtime.workspaceCwd,
|
|
21918
|
+
const projectDir = Storage.runWithResolvedRuntimeBaseDir(
|
|
21919
|
+
runtime.sessionRuntimeBaseDir,
|
|
21166
21920
|
() => new Storage(runtime.workspaceCwd).getProjectDir()
|
|
21167
21921
|
);
|
|
21168
21922
|
const records = await read(
|
|
@@ -21174,7 +21928,11 @@ var VirtualSubagentSessions = class {
|
|
|
21174
21928
|
let task = await this.findTask(
|
|
21175
21929
|
runtime,
|
|
21176
21930
|
parentSessionId,
|
|
21177
|
-
(candidate) =>
|
|
21931
|
+
(candidate) => (
|
|
21932
|
+
// /fork has no parent transcript tool call, so its task ID is the
|
|
21933
|
+
// stable reference used by Web Shell.
|
|
21934
|
+
candidate.id === toolCallId || candidate.toolUseId === toolCallId || candidate.id.endsWith(`-${toolCallId}`)
|
|
21935
|
+
)
|
|
21178
21936
|
);
|
|
21179
21937
|
const metrics = task && task.status !== "running" ? await this.readParentToolCallMetrics(
|
|
21180
21938
|
runtime,
|
|
@@ -21234,6 +21992,23 @@ var VirtualSubagentSessions = class {
|
|
|
21234
21992
|
}
|
|
21235
21993
|
};
|
|
21236
21994
|
|
|
21995
|
+
// packages/cli/src/serve/workspace-runtime-storage.ts
|
|
21996
|
+
init_esbuild_shims();
|
|
21997
|
+
function runWithWorkspaceRuntimeStorage(runtime, fn) {
|
|
21998
|
+
return Storage.runWithResolvedRuntimeBaseDir(
|
|
21999
|
+
runtime.sessionRuntimeBaseDir,
|
|
22000
|
+
fn
|
|
22001
|
+
);
|
|
22002
|
+
}
|
|
22003
|
+
__name(runWithWorkspaceRuntimeStorage, "runWithWorkspaceRuntimeStorage");
|
|
22004
|
+
function createWorkspaceRuntimeSessionService(runtime, options = {}) {
|
|
22005
|
+
return new SessionService(runtime.workspaceCwd, {
|
|
22006
|
+
...options,
|
|
22007
|
+
runtimeBaseDir: runtime.sessionRuntimeBaseDir
|
|
22008
|
+
});
|
|
22009
|
+
}
|
|
22010
|
+
__name(createWorkspaceRuntimeSessionService, "createWorkspaceRuntimeSessionService");
|
|
22011
|
+
|
|
21237
22012
|
// packages/cli/src/serve/routes/session.ts
|
|
21238
22013
|
var GIT_RESERVED_BRANCH = "HEAD";
|
|
21239
22014
|
var MAX_BRANCH_NAME_BYTES = 1e3;
|
|
@@ -21244,6 +22019,7 @@ var TRANSCRIPT_CURSOR_TOO_LARGE_REPLAY_ERROR = "Transcript pagination state exce
|
|
|
21244
22019
|
var CHANNEL_DELIVERY_AUTHORIZATION_GRACE_MS = 6e4;
|
|
21245
22020
|
var PRIMARY_ONLY_LIVE_SESSION_ROUTES = [
|
|
21246
22021
|
"POST /session/:id/branch",
|
|
22022
|
+
"POST /session/:id/side-task",
|
|
21247
22023
|
"POST /session/:id/fork",
|
|
21248
22024
|
"POST /session/:id/cd"
|
|
21249
22025
|
];
|
|
@@ -21258,7 +22034,8 @@ function isReadOnlyWorkspaceInspection(runtime) {
|
|
|
21258
22034
|
}
|
|
21259
22035
|
__name(isReadOnlyWorkspaceInspection, "isReadOnlyWorkspaceInspection");
|
|
21260
22036
|
function runWorkspaceInspectionWithLogPolicy(runtime, read2) {
|
|
21261
|
-
|
|
22037
|
+
const readInRuntime = /* @__PURE__ */ __name(() => runWithWorkspaceRuntimeStorage(runtime, read2), "readInRuntime");
|
|
22038
|
+
return isReadOnlyWorkspaceInspection(runtime) ? runWithoutDebugLogSession(readInRuntime) : readInRuntime();
|
|
21262
22039
|
}
|
|
21263
22040
|
__name(runWorkspaceInspectionWithLogPolicy, "runWorkspaceInspectionWithLogPolicy");
|
|
21264
22041
|
function requireSessionArtifactClientId(clientId, res) {
|
|
@@ -21595,9 +22372,30 @@ function registerSessionRoutes(app, deps) {
|
|
|
21595
22372
|
}
|
|
21596
22373
|
return runtime;
|
|
21597
22374
|
}, "resolveRuntimeForCatalogRoute");
|
|
21598
|
-
const
|
|
22375
|
+
const resolveLegacyPrimaryRuntimeFromParam = /* @__PURE__ */ __name((req, res) => {
|
|
22376
|
+
const entry = resolveWorkspaceEntryFromParam(
|
|
22377
|
+
workspaceRegistry,
|
|
22378
|
+
req,
|
|
22379
|
+
res,
|
|
22380
|
+
"id"
|
|
22381
|
+
);
|
|
22382
|
+
if (!entry) return null;
|
|
22383
|
+
if (!entry.primary) {
|
|
22384
|
+
sendWorkspaceMismatch2(res, entry.workspaceCwd);
|
|
22385
|
+
return null;
|
|
22386
|
+
}
|
|
22387
|
+
const runtime = entry.state === "active" ? entry.current?.runtime : void 0;
|
|
22388
|
+
if (!runtime) {
|
|
22389
|
+
sendWorkspaceRuntimeUnavailable(res, entry);
|
|
22390
|
+
return null;
|
|
22391
|
+
}
|
|
22392
|
+
return runtime;
|
|
22393
|
+
}, "resolveLegacyPrimaryRuntimeFromParam");
|
|
22394
|
+
const hasActivePersistedSessions = /* @__PURE__ */ __name(async (runtime) => {
|
|
21599
22395
|
try {
|
|
21600
|
-
const page = await
|
|
22396
|
+
const page = await createWorkspaceRuntimeSessionService(
|
|
22397
|
+
runtime
|
|
22398
|
+
).listSessions({
|
|
21601
22399
|
archiveState: "active",
|
|
21602
22400
|
size: 1
|
|
21603
22401
|
});
|
|
@@ -21647,20 +22445,28 @@ function registerSessionRoutes(app, deps) {
|
|
|
21647
22445
|
try {
|
|
21648
22446
|
const result = await archiveCoordinator.runSharedMany(
|
|
21649
22447
|
[sessionId],
|
|
21650
|
-
async () => {
|
|
22448
|
+
() => runWithWorkspaceRuntimeStorage(target.runtime, async () => {
|
|
21651
22449
|
if (target.archiveState === "archived") {
|
|
21652
|
-
await assertSessionArchived(
|
|
22450
|
+
await assertSessionArchived(
|
|
22451
|
+
target.runtime.workspaceCwd,
|
|
22452
|
+
sessionId,
|
|
22453
|
+
target.runtime.sessionRuntimeBaseDir
|
|
22454
|
+
);
|
|
21653
22455
|
} else {
|
|
21654
|
-
await assertSessionLoadable(
|
|
22456
|
+
await assertSessionLoadable(
|
|
22457
|
+
target.runtime.workspaceCwd,
|
|
22458
|
+
sessionId,
|
|
22459
|
+
target.runtime.sessionRuntimeBaseDir
|
|
22460
|
+
);
|
|
21655
22461
|
}
|
|
21656
22462
|
return exportSessionTranscript({
|
|
21657
|
-
workspaceCwd: target.workspaceCwd,
|
|
22463
|
+
workspaceCwd: target.runtime.workspaceCwd,
|
|
21658
22464
|
sessionId,
|
|
21659
22465
|
format,
|
|
21660
22466
|
archiveState: target.archiveState,
|
|
21661
22467
|
config: { getChannel: /* @__PURE__ */ __name(() => "daemon", "getChannel") }
|
|
21662
22468
|
});
|
|
21663
|
-
}
|
|
22469
|
+
})
|
|
21664
22470
|
);
|
|
21665
22471
|
const filename = result.filename.replace(/["\\\r\n]/g, "_");
|
|
21666
22472
|
res.status(200).set("Cache-Control", "no-store").set("X-Content-Type-Options", "nosniff").set("Content-Type", result.mimeType).set("Content-Disposition", `attachment; filename="${filename}"`).send(result.content);
|
|
@@ -21676,7 +22482,7 @@ function registerSessionRoutes(app, deps) {
|
|
|
21676
22482
|
sendBridgeError2(res, err, {
|
|
21677
22483
|
route: target.route,
|
|
21678
22484
|
sessionId,
|
|
21679
|
-
...target.workspaceQualified ? { workspaceCwd: target.workspaceCwd } : {}
|
|
22485
|
+
...target.workspaceQualified ? { workspaceCwd: target.runtime.workspaceCwd } : {}
|
|
21680
22486
|
});
|
|
21681
22487
|
}
|
|
21682
22488
|
}, "handleSessionExport");
|
|
@@ -21861,7 +22667,8 @@ function registerSessionRoutes(app, deps) {
|
|
|
21861
22667
|
const activeInRuntime = /* @__PURE__ */ __name(async (runtime) => {
|
|
21862
22668
|
const location = await assertSessionLoadable(
|
|
21863
22669
|
runtime.workspaceCwd,
|
|
21864
|
-
sessionId
|
|
22670
|
+
sessionId,
|
|
22671
|
+
runtime.sessionRuntimeBaseDir
|
|
21865
22672
|
);
|
|
21866
22673
|
return location === "active";
|
|
21867
22674
|
}, "activeInRuntime");
|
|
@@ -21964,19 +22771,6 @@ function registerSessionRoutes(app, deps) {
|
|
|
21964
22771
|
sessionId: e.sessionId,
|
|
21965
22772
|
error: e.error instanceof Error ? e.error.message : String(e.error)
|
|
21966
22773
|
})), "serializeSessionErrors");
|
|
21967
|
-
const resolveWorkspaceParam = /* @__PURE__ */ __name((req, res) => {
|
|
21968
|
-
const workspaceCwd = req.params["id"] ?? "";
|
|
21969
|
-
if (!path10.isAbsolute(workspaceCwd)) {
|
|
21970
|
-
res.status(400).json({ error: "`:id` must decode to an absolute workspace path" });
|
|
21971
|
-
return null;
|
|
21972
|
-
}
|
|
21973
|
-
const key = canonicalizeWorkspace(workspaceCwd);
|
|
21974
|
-
if (key !== boundWorkspace) {
|
|
21975
|
-
sendWorkspaceMismatch2(res, key);
|
|
21976
|
-
return null;
|
|
21977
|
-
}
|
|
21978
|
-
return key;
|
|
21979
|
-
}, "resolveWorkspaceParam");
|
|
21980
22774
|
const withPrimaryOnlyMutableSession = /* @__PURE__ */ __name((route, handler) => {
|
|
21981
22775
|
if (!isPrimaryOnlyLiveSessionRoute(route)) {
|
|
21982
22776
|
throw new Error(`Unregistered primary-only session route: ${route}`);
|
|
@@ -22250,13 +23044,16 @@ function registerSessionRoutes(app, deps) {
|
|
|
22250
23044
|
} catch (error2) {
|
|
22251
23045
|
if (!session.attached) {
|
|
22252
23046
|
try {
|
|
22253
|
-
const
|
|
22254
|
-
|
|
22255
|
-
|
|
22256
|
-
|
|
22257
|
-
|
|
22258
|
-
|
|
22259
|
-
|
|
23047
|
+
const removed = await runWithWorkspaceRuntimeStorage(
|
|
23048
|
+
runtime,
|
|
23049
|
+
() => deleteDaemonSessionIfOrphan({
|
|
23050
|
+
sessionId: session.sessionId,
|
|
23051
|
+
service: createWorkspaceRuntimeSessionService(runtime),
|
|
23052
|
+
bridge: runtime.bridge,
|
|
23053
|
+
coordinator: archiveCoordinator
|
|
23054
|
+
})
|
|
23055
|
+
);
|
|
23056
|
+
if (removed) {
|
|
22260
23057
|
if (worktreeMeta) {
|
|
22261
23058
|
await new GitWorktreeService(workspaceCwd).removeUserWorktree(worktreeMeta.slug, { deleteBranch: true }).catch(() => {
|
|
22262
23059
|
});
|
|
@@ -22288,13 +23085,16 @@ function registerSessionRoutes(app, deps) {
|
|
|
22288
23085
|
}
|
|
22289
23086
|
if (!session.attached) {
|
|
22290
23087
|
try {
|
|
22291
|
-
const
|
|
22292
|
-
|
|
22293
|
-
|
|
22294
|
-
|
|
22295
|
-
|
|
22296
|
-
|
|
22297
|
-
|
|
23088
|
+
const removed = await runWithWorkspaceRuntimeStorage(
|
|
23089
|
+
runtime,
|
|
23090
|
+
() => deleteDaemonSessionIfOrphan({
|
|
23091
|
+
sessionId: session.sessionId,
|
|
23092
|
+
service: createWorkspaceRuntimeSessionService(runtime),
|
|
23093
|
+
bridge: runtime.bridge,
|
|
23094
|
+
coordinator: archiveCoordinator
|
|
23095
|
+
})
|
|
23096
|
+
);
|
|
23097
|
+
if (removed) {
|
|
22298
23098
|
if (worktreeMeta) {
|
|
22299
23099
|
await new GitWorktreeService(workspaceCwd).removeUserWorktree(worktreeMeta.slug, { deleteBranch: true }).catch(() => {
|
|
22300
23100
|
});
|
|
@@ -22353,9 +23153,9 @@ function registerSessionRoutes(app, deps) {
|
|
|
22353
23153
|
).catch(() => {
|
|
22354
23154
|
});
|
|
22355
23155
|
await writeWorktreeSession(
|
|
22356
|
-
|
|
22357
|
-
|
|
22358
|
-
),
|
|
23156
|
+
createWorkspaceRuntimeSessionService(
|
|
23157
|
+
runtime
|
|
23158
|
+
).getWorktreeSessionPath(session.sessionId),
|
|
22359
23159
|
{
|
|
22360
23160
|
slug: worktreeMeta.slug,
|
|
22361
23161
|
worktreePath: worktreeMeta.path,
|
|
@@ -22373,11 +23173,15 @@ function registerSessionRoutes(app, deps) {
|
|
|
22373
23173
|
error: cdErr instanceof Error ? cdErr.message : String(cdErr)
|
|
22374
23174
|
});
|
|
22375
23175
|
}
|
|
22376
|
-
|
|
22377
|
-
|
|
22378
|
-
|
|
22379
|
-
|
|
22380
|
-
|
|
23176
|
+
await runWithWorkspaceRuntimeStorage(
|
|
23177
|
+
runtime,
|
|
23178
|
+
() => deleteDaemonSessionIfOrphan({
|
|
23179
|
+
sessionId: session.sessionId,
|
|
23180
|
+
service: createWorkspaceRuntimeSessionService(runtime),
|
|
23181
|
+
bridge: runtime.bridge,
|
|
23182
|
+
coordinator: archiveCoordinator
|
|
23183
|
+
})
|
|
23184
|
+
).catch(() => false);
|
|
22381
23185
|
await new GitWorktreeService(workspaceCwd).removeUserWorktree(worktreeMeta.slug, { deleteBranch: true }).catch(() => {
|
|
22382
23186
|
});
|
|
22383
23187
|
res.status(500).json({
|
|
@@ -22502,9 +23306,13 @@ function registerSessionRoutes(app, deps) {
|
|
|
22502
23306
|
const session = await archiveCoordinator.runSharedMany(
|
|
22503
23307
|
[sessionId],
|
|
22504
23308
|
async () => {
|
|
22505
|
-
await assertSessionLoadable(
|
|
22506
|
-
|
|
22507
|
-
|
|
23309
|
+
await assertSessionLoadable(
|
|
23310
|
+
workspaceCwd,
|
|
23311
|
+
sessionId,
|
|
23312
|
+
runtime.sessionRuntimeBaseDir
|
|
23313
|
+
);
|
|
23314
|
+
const metadata = await createWorkspaceRuntimeSessionService(
|
|
23315
|
+
runtime
|
|
22508
23316
|
).readCreationMetadata(sessionId);
|
|
22509
23317
|
runtime.generationGuard?.assertOpen();
|
|
22510
23318
|
return action === "load" ? await runtime.bridge.loadSession({
|
|
@@ -22554,7 +23362,9 @@ function registerSessionRoutes(app, deps) {
|
|
|
22554
23362
|
}
|
|
22555
23363
|
if (!session.worktree) {
|
|
22556
23364
|
const sidecar = await readWorktreeSession(
|
|
22557
|
-
|
|
23365
|
+
createWorkspaceRuntimeSessionService(
|
|
23366
|
+
runtime
|
|
23367
|
+
).getWorktreeSessionPath(sessionId)
|
|
22558
23368
|
).catch(() => null);
|
|
22559
23369
|
if (sidecar) {
|
|
22560
23370
|
let realTarget;
|
|
@@ -22757,13 +23567,72 @@ function registerSessionRoutes(app, deps) {
|
|
|
22757
23567
|
{ name },
|
|
22758
23568
|
{ clientId }
|
|
22759
23569
|
);
|
|
23570
|
+
try {
|
|
23571
|
+
runtime.generationGuard?.assertOpen();
|
|
23572
|
+
} catch (error2) {
|
|
23573
|
+
if (!result.attached) {
|
|
23574
|
+
await runWithWorkspaceRuntimeStorage(
|
|
23575
|
+
runtime,
|
|
23576
|
+
() => deleteDaemonSessionIfOrphan({
|
|
23577
|
+
sessionId: result.sessionId,
|
|
23578
|
+
service: createWorkspaceRuntimeSessionService(runtime),
|
|
23579
|
+
bridge: runtime.bridge,
|
|
23580
|
+
coordinator: archiveCoordinator
|
|
23581
|
+
})
|
|
23582
|
+
).catch(() => false);
|
|
23583
|
+
} else {
|
|
23584
|
+
await runtime.bridge.detachClient(result.sessionId, result.clientId).catch(() => {
|
|
23585
|
+
});
|
|
23586
|
+
}
|
|
23587
|
+
throw error2;
|
|
23588
|
+
}
|
|
23589
|
+
if (!res.writable) {
|
|
23590
|
+
if (!result.attached) {
|
|
23591
|
+
void runWithWorkspaceRuntimeStorage(
|
|
23592
|
+
runtime,
|
|
23593
|
+
() => deleteDaemonSessionIfOrphan({
|
|
23594
|
+
sessionId: result.sessionId,
|
|
23595
|
+
service: createWorkspaceRuntimeSessionService(runtime),
|
|
23596
|
+
bridge: runtime.bridge,
|
|
23597
|
+
coordinator: archiveCoordinator
|
|
23598
|
+
})
|
|
23599
|
+
).catch(() => {
|
|
23600
|
+
});
|
|
23601
|
+
} else {
|
|
23602
|
+
runtime.bridge.detachClient(result.sessionId, result.clientId).catch(() => {
|
|
23603
|
+
});
|
|
23604
|
+
}
|
|
23605
|
+
return;
|
|
23606
|
+
}
|
|
23607
|
+
res.status(201).json(result);
|
|
23608
|
+
}
|
|
23609
|
+
)
|
|
23610
|
+
);
|
|
23611
|
+
app.post(
|
|
23612
|
+
"/session/:id/side-task",
|
|
23613
|
+
mutate(),
|
|
23614
|
+
withPrimaryOnlyMutableSession(
|
|
23615
|
+
"POST /session/:id/side-task",
|
|
23616
|
+
async (req, res, sessionId, runtime) => {
|
|
23617
|
+
const body = safeBody(req);
|
|
23618
|
+
let name = typeof body?.["name"] === "string" ? body["name"] : void 0;
|
|
23619
|
+
if (name) {
|
|
23620
|
+
name = Array.from(name.replace(/[\x00-\x1F\x7F-\x9F]/g, "")).slice(0, 200).join("");
|
|
23621
|
+
}
|
|
23622
|
+
const clientId = parseClientIdHeader(req, res);
|
|
23623
|
+
if (clientId === null) return;
|
|
23624
|
+
const result = await runtime.bridge.createSideTaskSession(
|
|
23625
|
+
sessionId,
|
|
23626
|
+
{ name },
|
|
23627
|
+
{ clientId }
|
|
23628
|
+
);
|
|
22760
23629
|
try {
|
|
22761
23630
|
runtime.generationGuard?.assertOpen();
|
|
22762
23631
|
} catch (error2) {
|
|
22763
23632
|
if (!result.attached) {
|
|
22764
23633
|
const killed = await runtime.bridge.killSession(result.sessionId, { requireZeroAttaches: true }).catch(() => false);
|
|
22765
23634
|
if (killed) {
|
|
22766
|
-
await
|
|
23635
|
+
await createWorkspaceRuntimeSessionService(runtime).removeSession(result.sessionId).catch(() => {
|
|
22767
23636
|
});
|
|
22768
23637
|
}
|
|
22769
23638
|
} else {
|
|
@@ -22774,7 +23643,12 @@ function registerSessionRoutes(app, deps) {
|
|
|
22774
23643
|
}
|
|
22775
23644
|
if (!res.writable) {
|
|
22776
23645
|
if (!result.attached) {
|
|
22777
|
-
runtime.bridge.killSession(result.sessionId, { requireZeroAttaches: true }).
|
|
23646
|
+
runtime.bridge.killSession(result.sessionId, { requireZeroAttaches: true }).then((killed) => {
|
|
23647
|
+
if (!killed) return void 0;
|
|
23648
|
+
return createWorkspaceRuntimeSessionService(
|
|
23649
|
+
runtime
|
|
23650
|
+
).removeSession(result.sessionId);
|
|
23651
|
+
}).catch(() => {
|
|
22778
23652
|
});
|
|
22779
23653
|
} else {
|
|
22780
23654
|
runtime.bridge.detachClient(result.sessionId, result.clientId).catch(() => {
|
|
@@ -22870,7 +23744,7 @@ function registerSessionRoutes(app, deps) {
|
|
|
22870
23744
|
app.get("/session/:id/export", async (req, res) => {
|
|
22871
23745
|
await handleSessionExport(req, res, {
|
|
22872
23746
|
route: "GET /session/:id/export",
|
|
22873
|
-
|
|
23747
|
+
runtime: workspaceRegistry.primary
|
|
22874
23748
|
});
|
|
22875
23749
|
});
|
|
22876
23750
|
app.get("/workspaces/:workspace/session/:id/export", async (req, res) => {
|
|
@@ -22879,7 +23753,7 @@ function registerSessionRoutes(app, deps) {
|
|
|
22879
23753
|
if (!runtime) return;
|
|
22880
23754
|
await handleSessionExport(req, res, {
|
|
22881
23755
|
route,
|
|
22882
|
-
|
|
23756
|
+
runtime,
|
|
22883
23757
|
workspaceQualified: true
|
|
22884
23758
|
});
|
|
22885
23759
|
});
|
|
@@ -22891,7 +23765,7 @@ function registerSessionRoutes(app, deps) {
|
|
|
22891
23765
|
if (!runtime) return;
|
|
22892
23766
|
await handleSessionExport(req, res, {
|
|
22893
23767
|
route,
|
|
22894
|
-
|
|
23768
|
+
runtime,
|
|
22895
23769
|
workspaceQualified: true,
|
|
22896
23770
|
archiveState: "archived"
|
|
22897
23771
|
});
|
|
@@ -22988,67 +23862,74 @@ function registerSessionRoutes(app, deps) {
|
|
|
22988
23862
|
}
|
|
22989
23863
|
try {
|
|
22990
23864
|
const result = await runWithoutDebugLogSession(
|
|
22991
|
-
() => archiveCoordinator.runSharedMany(
|
|
22992
|
-
|
|
22993
|
-
|
|
22994
|
-
|
|
22995
|
-
|
|
22996
|
-
|
|
22997
|
-
|
|
22998
|
-
|
|
22999
|
-
|
|
23000
|
-
|
|
23001
|
-
let page;
|
|
23002
|
-
try {
|
|
23003
|
-
page = await reader.readPage(sessionId, {
|
|
23004
|
-
...limit !== void 0 ? { limit } : {},
|
|
23005
|
-
...cursor !== void 0 ? { cursor } : {},
|
|
23006
|
-
...beforeRecordId !== void 0 ? { beforeRecordId } : {},
|
|
23007
|
-
maxBytes: SESSION_TRANSCRIPT_MAX_PAGE_BYTES
|
|
23008
|
-
});
|
|
23009
|
-
} catch (error2) {
|
|
23010
|
-
if (error2.code !== "ENOENT") {
|
|
23011
|
-
throw error2;
|
|
23012
|
-
}
|
|
23013
|
-
if (cursor !== void 0) {
|
|
23014
|
-
throw new SessionTranscriptSnapshotUnavailableError(sessionId);
|
|
23865
|
+
() => archiveCoordinator.runSharedMany(
|
|
23866
|
+
[sessionId],
|
|
23867
|
+
() => runWithWorkspaceRuntimeStorage(runtime, async () => {
|
|
23868
|
+
const service = createWorkspaceRuntimeSessionService(runtime);
|
|
23869
|
+
if (cursor === void 0) {
|
|
23870
|
+
await assertSessionLoadable(
|
|
23871
|
+
runtime.workspaceCwd,
|
|
23872
|
+
sessionId,
|
|
23873
|
+
runtime.sessionRuntimeBaseDir
|
|
23874
|
+
);
|
|
23015
23875
|
}
|
|
23016
|
-
const
|
|
23017
|
-
|
|
23018
|
-
|
|
23876
|
+
const codec = getTranscriptCursorCodec(runtime);
|
|
23877
|
+
const reader = new SessionTranscriptReader(
|
|
23878
|
+
runtime.workspaceCwd,
|
|
23879
|
+
codec
|
|
23880
|
+
);
|
|
23881
|
+
let page;
|
|
23882
|
+
try {
|
|
23883
|
+
page = await reader.readPage(sessionId, {
|
|
23884
|
+
...limit !== void 0 ? { limit } : {},
|
|
23885
|
+
...cursor !== void 0 ? { cursor } : {},
|
|
23886
|
+
...beforeRecordId !== void 0 ? { beforeRecordId } : {},
|
|
23887
|
+
maxBytes: SESSION_TRANSCRIPT_MAX_PAGE_BYTES
|
|
23888
|
+
});
|
|
23889
|
+
} catch (error2) {
|
|
23890
|
+
if (error2.code !== "ENOENT") {
|
|
23891
|
+
throw error2;
|
|
23892
|
+
}
|
|
23893
|
+
if (cursor !== void 0) {
|
|
23894
|
+
throw new SessionTranscriptSnapshotUnavailableError(sessionId);
|
|
23895
|
+
}
|
|
23896
|
+
const location = await service.getSessionLocation(sessionId);
|
|
23897
|
+
if (location === "archived") {
|
|
23898
|
+
throw new SessionArchivedError(sessionId);
|
|
23899
|
+
}
|
|
23900
|
+
if (location === "conflict") {
|
|
23901
|
+
throw new SessionConflictError(sessionId);
|
|
23902
|
+
}
|
|
23903
|
+
throw new SessionNotFoundError(sessionId);
|
|
23019
23904
|
}
|
|
23020
|
-
if (
|
|
23021
|
-
throw new
|
|
23905
|
+
if (page.records.some((record) => record.sessionId !== sessionId)) {
|
|
23906
|
+
throw new SessionTranscriptSnapshotUnavailableError(sessionId);
|
|
23022
23907
|
}
|
|
23023
|
-
|
|
23024
|
-
|
|
23025
|
-
|
|
23026
|
-
|
|
23027
|
-
|
|
23028
|
-
|
|
23029
|
-
|
|
23030
|
-
page,
|
|
23031
|
-
encodeCursor: /* @__PURE__ */ __name((state) => codec.encode(state), "encodeCursor")
|
|
23032
|
-
});
|
|
23033
|
-
const cursorTooLarge = replay.nextCursor !== void 0 && Buffer.byteLength(replay.nextCursor) > WORKSPACE_TRANSCRIPT_CURSOR_MAX_BYTES;
|
|
23034
|
-
return {
|
|
23035
|
-
v: 1,
|
|
23036
|
-
sessionId,
|
|
23037
|
-
events: replay.updates.map((update) => ({
|
|
23908
|
+
const replay = await replayTranscriptRecordPage({
|
|
23909
|
+
sessionId,
|
|
23910
|
+
page,
|
|
23911
|
+
encodeCursor: /* @__PURE__ */ __name((state) => codec.encode(state), "encodeCursor")
|
|
23912
|
+
});
|
|
23913
|
+
const cursorTooLarge = replay.nextCursor !== void 0 && Buffer.byteLength(replay.nextCursor) > WORKSPACE_TRANSCRIPT_CURSOR_MAX_BYTES;
|
|
23914
|
+
return {
|
|
23038
23915
|
v: 1,
|
|
23039
|
-
|
|
23040
|
-
|
|
23041
|
-
|
|
23042
|
-
|
|
23043
|
-
|
|
23044
|
-
|
|
23045
|
-
|
|
23046
|
-
|
|
23047
|
-
|
|
23048
|
-
|
|
23049
|
-
|
|
23050
|
-
|
|
23051
|
-
|
|
23916
|
+
sessionId,
|
|
23917
|
+
events: replay.updates.map((update) => ({
|
|
23918
|
+
v: 1,
|
|
23919
|
+
type: "session_update",
|
|
23920
|
+
data: update
|
|
23921
|
+
})),
|
|
23922
|
+
...replay.nextCursor && !cursorTooLarge ? { nextCursor: replay.nextCursor } : {},
|
|
23923
|
+
hasMore: cursorTooLarge ? false : replay.hasMore,
|
|
23924
|
+
startTime: replay.startTime,
|
|
23925
|
+
lastUpdated: replay.lastUpdated,
|
|
23926
|
+
...replay.partial || cursorTooLarge ? {
|
|
23927
|
+
partial: true,
|
|
23928
|
+
replayError: cursorTooLarge ? TRANSCRIPT_CURSOR_TOO_LARGE_REPLAY_ERROR : replay.replayError
|
|
23929
|
+
} : {}
|
|
23930
|
+
};
|
|
23931
|
+
})
|
|
23932
|
+
)
|
|
23052
23933
|
);
|
|
23053
23934
|
const serialized = serializeWorkspaceTranscriptResponse(
|
|
23054
23935
|
result,
|
|
@@ -23701,18 +24582,22 @@ function registerSessionRoutes(app, deps) {
|
|
|
23701
24582
|
const uniqueIds = parseSessionIdsBody(req, res);
|
|
23702
24583
|
if (uniqueIds === void 0) return;
|
|
23703
24584
|
try {
|
|
23704
|
-
const
|
|
23705
|
-
const
|
|
23706
|
-
|
|
23707
|
-
|
|
23708
|
-
|
|
23709
|
-
|
|
23710
|
-
|
|
23711
|
-
|
|
23712
|
-
|
|
23713
|
-
)
|
|
23714
|
-
|
|
23715
|
-
|
|
24585
|
+
const runtime = workspaceRegistry.primary;
|
|
24586
|
+
const service = createWorkspaceRuntimeSessionService(runtime);
|
|
24587
|
+
const result = await runWithWorkspaceRuntimeStorage(
|
|
24588
|
+
runtime,
|
|
24589
|
+
() => deleteDaemonSessions({
|
|
24590
|
+
sessionIds: uniqueIds,
|
|
24591
|
+
service,
|
|
24592
|
+
bridge,
|
|
24593
|
+
coordinator: archiveCoordinator,
|
|
24594
|
+
onError: /* @__PURE__ */ __name(({ phase, sessionId, error: error2 }) => {
|
|
24595
|
+
writeStderrLine(
|
|
24596
|
+
`qwen serve: ${phase}Session failed for ${safeLogValue(sessionId)}: ${safeLogValue(error2)}`
|
|
24597
|
+
);
|
|
24598
|
+
}, "onError")
|
|
24599
|
+
})
|
|
24600
|
+
);
|
|
23716
24601
|
for (const removedId of result.removed) {
|
|
23717
24602
|
clearBranchSessionEntry(removedId);
|
|
23718
24603
|
}
|
|
@@ -23724,16 +24609,20 @@ function registerSessionRoutes(app, deps) {
|
|
|
23724
24609
|
app.post("/sessions/archive", mutate(), async (req, res) => {
|
|
23725
24610
|
const uniqueIds = parseSessionIdsBody(req, res);
|
|
23726
24611
|
if (uniqueIds === void 0) return;
|
|
23727
|
-
const
|
|
24612
|
+
const runtime = workspaceRegistry.primary;
|
|
24613
|
+
const service = createWorkspaceRuntimeSessionService(runtime, {
|
|
23728
24614
|
onWarning: logSessionArchiveWarning
|
|
23729
24615
|
});
|
|
23730
24616
|
try {
|
|
23731
|
-
const result = await
|
|
23732
|
-
|
|
23733
|
-
|
|
23734
|
-
|
|
23735
|
-
|
|
23736
|
-
|
|
24617
|
+
const result = await runWithWorkspaceRuntimeStorage(
|
|
24618
|
+
runtime,
|
|
24619
|
+
() => archiveDaemonSessions({
|
|
24620
|
+
sessionIds: uniqueIds,
|
|
24621
|
+
service,
|
|
24622
|
+
bridge,
|
|
24623
|
+
coordinator: archiveCoordinator
|
|
24624
|
+
})
|
|
24625
|
+
);
|
|
23737
24626
|
res.status(200).json({
|
|
23738
24627
|
archived: result.archived,
|
|
23739
24628
|
alreadyArchived: result.alreadyArchived,
|
|
@@ -23747,15 +24636,19 @@ function registerSessionRoutes(app, deps) {
|
|
|
23747
24636
|
app.post("/sessions/unarchive", mutate(), async (req, res) => {
|
|
23748
24637
|
const uniqueIds = parseSessionIdsBody(req, res);
|
|
23749
24638
|
if (uniqueIds === void 0) return;
|
|
23750
|
-
const
|
|
24639
|
+
const runtime = workspaceRegistry.primary;
|
|
24640
|
+
const service = createWorkspaceRuntimeSessionService(runtime, {
|
|
23751
24641
|
onWarning: logSessionArchiveWarning
|
|
23752
24642
|
});
|
|
23753
24643
|
try {
|
|
23754
|
-
const result = await
|
|
23755
|
-
|
|
23756
|
-
|
|
23757
|
-
|
|
23758
|
-
|
|
24644
|
+
const result = await runWithWorkspaceRuntimeStorage(
|
|
24645
|
+
runtime,
|
|
24646
|
+
() => unarchiveDaemonSessions({
|
|
24647
|
+
sessionIds: uniqueIds,
|
|
24648
|
+
service,
|
|
24649
|
+
coordinator: archiveCoordinator
|
|
24650
|
+
})
|
|
24651
|
+
);
|
|
23759
24652
|
res.status(200).json({
|
|
23760
24653
|
unarchived: result.unarchived,
|
|
23761
24654
|
alreadyActive: result.alreadyActive,
|
|
@@ -23778,18 +24671,21 @@ function registerSessionRoutes(app, deps) {
|
|
|
23778
24671
|
const uniqueIds = parseSessionIdsBody(req, res);
|
|
23779
24672
|
if (uniqueIds === void 0) return;
|
|
23780
24673
|
try {
|
|
23781
|
-
const service =
|
|
23782
|
-
const result = await
|
|
23783
|
-
|
|
23784
|
-
|
|
23785
|
-
|
|
23786
|
-
|
|
23787
|
-
|
|
23788
|
-
|
|
23789
|
-
|
|
23790
|
-
|
|
23791
|
-
|
|
23792
|
-
|
|
24674
|
+
const service = createWorkspaceRuntimeSessionService(runtime);
|
|
24675
|
+
const result = await runWithWorkspaceRuntimeStorage(
|
|
24676
|
+
runtime,
|
|
24677
|
+
() => deleteDaemonSessions({
|
|
24678
|
+
sessionIds: uniqueIds,
|
|
24679
|
+
service,
|
|
24680
|
+
bridge: runtime.bridge,
|
|
24681
|
+
coordinator: archiveCoordinator,
|
|
24682
|
+
onError: /* @__PURE__ */ __name(({ phase, sessionId, error: error2 }) => {
|
|
24683
|
+
writeStderrLine(
|
|
24684
|
+
`qwen serve: ${phase}Session failed for ${safeLogValue(sessionId)}: ${safeLogValue(error2)}`
|
|
24685
|
+
);
|
|
24686
|
+
}, "onError")
|
|
24687
|
+
})
|
|
24688
|
+
);
|
|
23793
24689
|
for (const removedId of result.removed) {
|
|
23794
24690
|
clearBranchSessionEntry(removedId);
|
|
23795
24691
|
}
|
|
@@ -23808,16 +24704,19 @@ function registerSessionRoutes(app, deps) {
|
|
|
23808
24704
|
if (!runtime) return;
|
|
23809
24705
|
const uniqueIds = parseSessionIdsBody(req, res);
|
|
23810
24706
|
if (uniqueIds === void 0) return;
|
|
23811
|
-
const service =
|
|
24707
|
+
const service = createWorkspaceRuntimeSessionService(runtime, {
|
|
23812
24708
|
onWarning: logSessionArchiveWarning
|
|
23813
24709
|
});
|
|
23814
24710
|
try {
|
|
23815
|
-
const result = await
|
|
23816
|
-
|
|
23817
|
-
|
|
23818
|
-
|
|
23819
|
-
|
|
23820
|
-
|
|
24711
|
+
const result = await runWithWorkspaceRuntimeStorage(
|
|
24712
|
+
runtime,
|
|
24713
|
+
() => archiveDaemonSessions({
|
|
24714
|
+
sessionIds: uniqueIds,
|
|
24715
|
+
service,
|
|
24716
|
+
bridge: runtime.bridge,
|
|
24717
|
+
coordinator: archiveCoordinator
|
|
24718
|
+
})
|
|
24719
|
+
);
|
|
23821
24720
|
res.status(200).json({
|
|
23822
24721
|
archived: result.archived,
|
|
23823
24722
|
alreadyArchived: result.alreadyArchived,
|
|
@@ -23838,15 +24737,18 @@ function registerSessionRoutes(app, deps) {
|
|
|
23838
24737
|
if (!runtime) return;
|
|
23839
24738
|
const uniqueIds = parseSessionIdsBody(req, res);
|
|
23840
24739
|
if (uniqueIds === void 0) return;
|
|
23841
|
-
const service =
|
|
24740
|
+
const service = createWorkspaceRuntimeSessionService(runtime, {
|
|
23842
24741
|
onWarning: logSessionArchiveWarning
|
|
23843
24742
|
});
|
|
23844
24743
|
try {
|
|
23845
|
-
const result = await
|
|
23846
|
-
|
|
23847
|
-
|
|
23848
|
-
|
|
23849
|
-
|
|
24744
|
+
const result = await runWithWorkspaceRuntimeStorage(
|
|
24745
|
+
runtime,
|
|
24746
|
+
() => unarchiveDaemonSessions({
|
|
24747
|
+
sessionIds: uniqueIds,
|
|
24748
|
+
service,
|
|
24749
|
+
coordinator: archiveCoordinator
|
|
24750
|
+
})
|
|
24751
|
+
);
|
|
23850
24752
|
res.status(200).json({
|
|
23851
24753
|
unarchived: result.unarchived,
|
|
23852
24754
|
alreadyActive: result.alreadyActive,
|
|
@@ -23890,74 +24792,80 @@ function registerSessionRoutes(app, deps) {
|
|
|
23890
24792
|
const sessionId = requireSessionId(req, res);
|
|
23891
24793
|
if (sessionId === null) return;
|
|
23892
24794
|
try {
|
|
23893
|
-
await archiveCoordinator.runSharedMany(
|
|
23894
|
-
|
|
23895
|
-
|
|
23896
|
-
|
|
23897
|
-
|
|
23898
|
-
|
|
23899
|
-
|
|
23900
|
-
|
|
23901
|
-
|
|
24795
|
+
await archiveCoordinator.runSharedMany(
|
|
24796
|
+
[sessionId],
|
|
24797
|
+
() => runWithWorkspaceRuntimeStorage(target.runtime, async () => {
|
|
24798
|
+
const sessionService = createWorkspaceRuntimeSessionService(
|
|
24799
|
+
target.runtime
|
|
24800
|
+
);
|
|
24801
|
+
let exists = await sessionService.sessionExistsInAnyState(sessionId);
|
|
24802
|
+
if (!exists) {
|
|
24803
|
+
try {
|
|
24804
|
+
const summary = target.runtime.bridge.getSessionSummary(sessionId);
|
|
24805
|
+
exists = summary.workspaceCwd === target.runtime.workspaceCwd;
|
|
24806
|
+
} catch {
|
|
24807
|
+
exists = false;
|
|
24808
|
+
}
|
|
23902
24809
|
}
|
|
23903
|
-
|
|
23904
|
-
|
|
23905
|
-
|
|
23906
|
-
|
|
23907
|
-
|
|
23908
|
-
|
|
23909
|
-
|
|
23910
|
-
|
|
23911
|
-
|
|
23912
|
-
|
|
23913
|
-
|
|
23914
|
-
|
|
23915
|
-
|
|
23916
|
-
|
|
23917
|
-
|
|
23918
|
-
|
|
23919
|
-
|
|
23920
|
-
|
|
23921
|
-
|
|
23922
|
-
|
|
23923
|
-
|
|
23924
|
-
|
|
23925
|
-
|
|
23926
|
-
|
|
23927
|
-
|
|
23928
|
-
|
|
23929
|
-
|
|
23930
|
-
|
|
23931
|
-
|
|
23932
|
-
|
|
23933
|
-
|
|
23934
|
-
|
|
23935
|
-
|
|
24810
|
+
if (!exists) {
|
|
24811
|
+
res.status(404).json({
|
|
24812
|
+
error: `No session with id "${sessionId}"`,
|
|
24813
|
+
sessionId
|
|
24814
|
+
});
|
|
24815
|
+
return;
|
|
24816
|
+
}
|
|
24817
|
+
const body = safeBody(req);
|
|
24818
|
+
const rawIsPinned = body["isPinned"];
|
|
24819
|
+
if (rawIsPinned !== void 0 && typeof rawIsPinned !== "boolean") {
|
|
24820
|
+
res.status(400).json({
|
|
24821
|
+
error: "`isPinned` must be a boolean",
|
|
24822
|
+
code: "invalid_session_organization",
|
|
24823
|
+
field: "isPinned"
|
|
24824
|
+
});
|
|
24825
|
+
return;
|
|
24826
|
+
}
|
|
24827
|
+
const rawGroupId = body["groupId"];
|
|
24828
|
+
if (rawGroupId !== void 0 && rawGroupId !== null && typeof rawGroupId !== "string") {
|
|
24829
|
+
res.status(400).json({
|
|
24830
|
+
error: "`groupId` must be a string or null",
|
|
24831
|
+
code: "invalid_session_organization",
|
|
24832
|
+
field: "groupId"
|
|
24833
|
+
});
|
|
24834
|
+
return;
|
|
24835
|
+
}
|
|
24836
|
+
const rawColor = body["color"];
|
|
24837
|
+
if (rawColor !== void 0 && rawColor !== null && (typeof rawColor !== "string" || !GROUP_COLOR_OPTIONS.includes(
|
|
24838
|
+
rawColor
|
|
24839
|
+
))) {
|
|
24840
|
+
res.status(400).json({
|
|
24841
|
+
error: "`color` must be a supported color or null",
|
|
24842
|
+
code: "invalid_session_organization",
|
|
24843
|
+
field: "color"
|
|
24844
|
+
});
|
|
24845
|
+
return;
|
|
24846
|
+
}
|
|
24847
|
+
const organization = await createSessionOrganizationService(
|
|
24848
|
+
target.runtime.workspaceCwd
|
|
24849
|
+
).updateSessionOrganization(sessionId, {
|
|
24850
|
+
...rawIsPinned !== void 0 ? { isPinned: rawIsPinned } : {},
|
|
24851
|
+
...rawGroupId !== void 0 ? { groupId: rawGroupId } : {},
|
|
24852
|
+
...rawColor !== void 0 ? { color: rawColor } : {}
|
|
23936
24853
|
});
|
|
23937
|
-
|
|
23938
|
-
}
|
|
23939
|
-
|
|
23940
|
-
target.workspaceCwd
|
|
23941
|
-
).updateSessionOrganization(sessionId, {
|
|
23942
|
-
...rawIsPinned !== void 0 ? { isPinned: rawIsPinned } : {},
|
|
23943
|
-
...rawGroupId !== void 0 ? { groupId: rawGroupId } : {},
|
|
23944
|
-
...rawColor !== void 0 ? { color: rawColor } : {}
|
|
23945
|
-
});
|
|
23946
|
-
res.status(200).json({ sessionId, ...organization });
|
|
23947
|
-
});
|
|
24854
|
+
res.status(200).json({ sessionId, ...organization });
|
|
24855
|
+
})
|
|
24856
|
+
);
|
|
23948
24857
|
} catch (err) {
|
|
23949
24858
|
if (sendSessionOrganizationError(res, err)) return;
|
|
23950
24859
|
sendBridgeError2(res, err, {
|
|
23951
24860
|
route: target.route,
|
|
23952
24861
|
sessionId,
|
|
23953
|
-
workspaceCwd: target.workspaceCwd
|
|
24862
|
+
workspaceCwd: target.runtime.workspaceCwd
|
|
23954
24863
|
});
|
|
23955
24864
|
}
|
|
23956
24865
|
}, "handleSessionOrganizationUpdate");
|
|
23957
24866
|
app.patch("/session/:id/organization", mutate(), async (req, res) => {
|
|
23958
24867
|
await handleSessionOrganizationUpdate(req, res, {
|
|
23959
|
-
|
|
23960
|
-
bridge,
|
|
24868
|
+
runtime: workspaceRegistry.primary,
|
|
23961
24869
|
route: "PATCH /session/:id/organization"
|
|
23962
24870
|
});
|
|
23963
24871
|
});
|
|
@@ -23969,8 +24877,7 @@ function registerSessionRoutes(app, deps) {
|
|
|
23969
24877
|
const runtime = requireTrustedRuntimeForWorkspaceRoute(req, res, route);
|
|
23970
24878
|
if (!runtime) return;
|
|
23971
24879
|
await handleSessionOrganizationUpdate(req, res, {
|
|
23972
|
-
|
|
23973
|
-
bridge: runtime.bridge,
|
|
24880
|
+
runtime,
|
|
23974
24881
|
route
|
|
23975
24882
|
});
|
|
23976
24883
|
}
|
|
@@ -23992,14 +24899,17 @@ function registerSessionRoutes(app, deps) {
|
|
|
23992
24899
|
}
|
|
23993
24900
|
});
|
|
23994
24901
|
app.post("/workspace/:id/session-groups", mutate(), async (req, res) => {
|
|
23995
|
-
const
|
|
23996
|
-
if (
|
|
24902
|
+
const runtime = resolveLegacyPrimaryRuntimeFromParam(req, res);
|
|
24903
|
+
if (runtime === null) return;
|
|
23997
24904
|
const body = safeBody(req);
|
|
23998
24905
|
try {
|
|
23999
|
-
const group = await
|
|
24000
|
-
|
|
24001
|
-
|
|
24002
|
-
|
|
24906
|
+
const group = await runWithWorkspaceRuntimeStorage(
|
|
24907
|
+
runtime,
|
|
24908
|
+
() => createSessionOrganizationService(runtime.workspaceCwd).createGroup({
|
|
24909
|
+
name: body["name"],
|
|
24910
|
+
color: body["color"]
|
|
24911
|
+
})
|
|
24912
|
+
);
|
|
24003
24913
|
res.status(201).json({ group });
|
|
24004
24914
|
} catch (err) {
|
|
24005
24915
|
if (sendSessionOrganizationError(res, err)) return;
|
|
@@ -24012,17 +24922,20 @@ function registerSessionRoutes(app, deps) {
|
|
|
24012
24922
|
"/workspace/:id/session-groups/:groupId",
|
|
24013
24923
|
mutate(),
|
|
24014
24924
|
async (req, res) => {
|
|
24015
|
-
const
|
|
24016
|
-
if (
|
|
24925
|
+
const runtime = resolveLegacyPrimaryRuntimeFromParam(req, res);
|
|
24926
|
+
if (runtime === null) return;
|
|
24017
24927
|
const body = safeBody(req);
|
|
24018
24928
|
try {
|
|
24019
|
-
const group = await
|
|
24020
|
-
|
|
24021
|
-
|
|
24022
|
-
|
|
24023
|
-
|
|
24024
|
-
|
|
24025
|
-
|
|
24929
|
+
const group = await runWithWorkspaceRuntimeStorage(
|
|
24930
|
+
runtime,
|
|
24931
|
+
() => createSessionOrganizationService(runtime.workspaceCwd).updateGroup(
|
|
24932
|
+
req.params["groupId"] ?? "",
|
|
24933
|
+
{
|
|
24934
|
+
...Object.prototype.hasOwnProperty.call(body, "name") ? { name: body["name"] } : {},
|
|
24935
|
+
...Object.prototype.hasOwnProperty.call(body, "color") ? { color: body["color"] } : {},
|
|
24936
|
+
...Object.prototype.hasOwnProperty.call(body, "order") ? { order: body["order"] } : {}
|
|
24937
|
+
}
|
|
24938
|
+
)
|
|
24026
24939
|
);
|
|
24027
24940
|
res.status(200).json({ group });
|
|
24028
24941
|
} catch (err) {
|
|
@@ -24037,11 +24950,14 @@ function registerSessionRoutes(app, deps) {
|
|
|
24037
24950
|
"/workspace/:id/session-groups/:groupId",
|
|
24038
24951
|
mutate(),
|
|
24039
24952
|
async (req, res) => {
|
|
24040
|
-
const
|
|
24041
|
-
if (
|
|
24953
|
+
const runtime = resolveLegacyPrimaryRuntimeFromParam(req, res);
|
|
24954
|
+
if (runtime === null) return;
|
|
24042
24955
|
try {
|
|
24043
|
-
const deleted = await
|
|
24044
|
-
|
|
24956
|
+
const deleted = await runWithWorkspaceRuntimeStorage(
|
|
24957
|
+
runtime,
|
|
24958
|
+
() => createSessionOrganizationService(runtime.workspaceCwd).deleteGroup(
|
|
24959
|
+
req.params["groupId"] ?? ""
|
|
24960
|
+
)
|
|
24045
24961
|
);
|
|
24046
24962
|
res.status(200).json({ deleted });
|
|
24047
24963
|
} catch (err) {
|
|
@@ -24076,12 +24992,13 @@ function registerSessionRoutes(app, deps) {
|
|
|
24076
24992
|
if (!runtime) return;
|
|
24077
24993
|
const body = safeBody(req);
|
|
24078
24994
|
try {
|
|
24079
|
-
const group = await
|
|
24080
|
-
runtime
|
|
24081
|
-
|
|
24082
|
-
|
|
24083
|
-
|
|
24084
|
-
|
|
24995
|
+
const group = await runWithWorkspaceRuntimeStorage(
|
|
24996
|
+
runtime,
|
|
24997
|
+
() => createSessionOrganizationService(runtime.workspaceCwd).createGroup({
|
|
24998
|
+
name: body["name"],
|
|
24999
|
+
color: body["color"]
|
|
25000
|
+
})
|
|
25001
|
+
);
|
|
24085
25002
|
res.status(201).json({ group });
|
|
24086
25003
|
} catch (err) {
|
|
24087
25004
|
if (sendSessionOrganizationError(res, err)) return;
|
|
@@ -24098,13 +25015,17 @@ function registerSessionRoutes(app, deps) {
|
|
|
24098
25015
|
if (!runtime) return;
|
|
24099
25016
|
const body = safeBody(req);
|
|
24100
25017
|
try {
|
|
24101
|
-
const group = await
|
|
24102
|
-
runtime
|
|
24103
|
-
|
|
24104
|
-
|
|
24105
|
-
|
|
24106
|
-
|
|
24107
|
-
|
|
25018
|
+
const group = await runWithWorkspaceRuntimeStorage(
|
|
25019
|
+
runtime,
|
|
25020
|
+
() => createSessionOrganizationService(runtime.workspaceCwd).updateGroup(
|
|
25021
|
+
req.params["groupId"] ?? "",
|
|
25022
|
+
{
|
|
25023
|
+
...Object.prototype.hasOwnProperty.call(body, "name") ? { name: body["name"] } : {},
|
|
25024
|
+
...Object.prototype.hasOwnProperty.call(body, "color") ? { color: body["color"] } : {},
|
|
25025
|
+
...Object.prototype.hasOwnProperty.call(body, "order") ? { order: body["order"] } : {}
|
|
25026
|
+
}
|
|
25027
|
+
)
|
|
25028
|
+
);
|
|
24108
25029
|
res.status(200).json({ group });
|
|
24109
25030
|
} catch (err) {
|
|
24110
25031
|
if (sendSessionOrganizationError(res, err)) return;
|
|
@@ -24120,9 +25041,12 @@ function registerSessionRoutes(app, deps) {
|
|
|
24120
25041
|
const runtime = requireTrustedRuntimeForWorkspaceRoute(req, res, route);
|
|
24121
25042
|
if (!runtime) return;
|
|
24122
25043
|
try {
|
|
24123
|
-
const deleted = await
|
|
24124
|
-
runtime
|
|
24125
|
-
|
|
25044
|
+
const deleted = await runWithWorkspaceRuntimeStorage(
|
|
25045
|
+
runtime,
|
|
25046
|
+
() => createSessionOrganizationService(runtime.workspaceCwd).deleteGroup(
|
|
25047
|
+
req.params["groupId"] ?? ""
|
|
25048
|
+
)
|
|
25049
|
+
);
|
|
24126
25050
|
res.status(200).json({ deleted });
|
|
24127
25051
|
} catch (err) {
|
|
24128
25052
|
if (sendSessionOrganizationError(res, err)) return;
|
|
@@ -24210,7 +25134,7 @@ function registerSessionRoutes(app, deps) {
|
|
|
24210
25134
|
...parentSessionId !== void 0 ? { parentSessionId } : {},
|
|
24211
25135
|
...parsedSource
|
|
24212
25136
|
};
|
|
24213
|
-
const usePersisted = readOnlySecondary || runtime.primary || view === "organized" || archiveState === "archived" || parentSessionId !== void 0 || parsedSource.sourceType !== void 0 || (cursor !== void 0 && cursor !== "" ? isNumericSessionCursor(cursor) : await hasActivePersistedSessions(
|
|
25137
|
+
const usePersisted = readOnlySecondary || runtime.primary || view === "organized" || archiveState === "archived" || parentSessionId !== void 0 || parsedSource.sourceType !== void 0 || (cursor !== void 0 && cursor !== "" ? isNumericSessionCursor(cursor) : await hasActivePersistedSessions(runtime));
|
|
24214
25138
|
if (!usePersisted && (view !== void 0 || archiveState === "archived" || parentSessionId !== void 0 || parsedSource.sourceType !== void 0)) {
|
|
24215
25139
|
throw new Error(
|
|
24216
25140
|
"session list live path received persisted-only options"
|
|
@@ -24707,11 +25631,14 @@ function requireOpenGeneration2(target, res) {
|
|
|
24707
25631
|
}
|
|
24708
25632
|
}
|
|
24709
25633
|
__name(requireOpenGeneration2, "requireOpenGeneration");
|
|
24710
|
-
async function rollbackCronMutation(
|
|
25634
|
+
async function rollbackCronMutation(target, before, after, route) {
|
|
24711
25635
|
if (!before || !after) return;
|
|
24712
|
-
await
|
|
24713
|
-
|
|
24714
|
-
(
|
|
25636
|
+
await runWithScheduledTaskTarget(
|
|
25637
|
+
target,
|
|
25638
|
+
() => updateCronTasks(
|
|
25639
|
+
target.workspaceCwd,
|
|
25640
|
+
(tasks) => isDeepStrictEqual2(tasks, after) ? before : tasks
|
|
25641
|
+
)
|
|
24715
25642
|
).catch((error2) => {
|
|
24716
25643
|
writeStderrLine(
|
|
24717
25644
|
`qwen serve: ${route} failed to roll back a stale task mutation: ${error2 instanceof Error ? error2.message : String(error2)}`
|
|
@@ -24719,6 +25646,27 @@ async function rollbackCronMutation(workspaceCwd, before, after, route) {
|
|
|
24719
25646
|
});
|
|
24720
25647
|
}
|
|
24721
25648
|
__name(rollbackCronMutation, "rollbackCronMutation");
|
|
25649
|
+
async function teardownBoundSession(target, sessionId) {
|
|
25650
|
+
if (target.cleanupSession) {
|
|
25651
|
+
await target.cleanupSession(sessionId).catch(() => {
|
|
25652
|
+
});
|
|
25653
|
+
} else if (target.bridge) {
|
|
25654
|
+
await target.bridge.closeSession(sessionId).catch(() => {
|
|
25655
|
+
});
|
|
25656
|
+
await new SessionService(target.workspaceCwd, {
|
|
25657
|
+
runtimeBaseDir: target.runtimeBaseDir
|
|
25658
|
+
}).removeSession(sessionId).catch(() => {
|
|
25659
|
+
});
|
|
25660
|
+
}
|
|
25661
|
+
}
|
|
25662
|
+
__name(teardownBoundSession, "teardownBoundSession");
|
|
25663
|
+
function runWithScheduledTaskTarget(target, fn) {
|
|
25664
|
+
if (target.runtimeBaseDir === void 0) {
|
|
25665
|
+
return fn();
|
|
25666
|
+
}
|
|
25667
|
+
return Storage.runWithResolvedRuntimeBaseDir(target.runtimeBaseDir, fn);
|
|
25668
|
+
}
|
|
25669
|
+
__name(runWithScheduledTaskTarget, "runWithScheduledTaskTarget");
|
|
24722
25670
|
function computeNextRunAt(task) {
|
|
24723
25671
|
if (task.enabled === false) return null;
|
|
24724
25672
|
return nextDurableFireMs(task);
|
|
@@ -24793,7 +25741,10 @@ function registerScheduledTaskCrudRoutes(app, deps) {
|
|
|
24793
25741
|
if (!target) return;
|
|
24794
25742
|
if (!requireOpenGeneration2(target, res)) return;
|
|
24795
25743
|
try {
|
|
24796
|
-
const tasks = await
|
|
25744
|
+
const tasks = await runWithScheduledTaskTarget(
|
|
25745
|
+
target,
|
|
25746
|
+
() => readCronTasks(target.workspaceCwd)
|
|
25747
|
+
);
|
|
24797
25748
|
if (!requireOpenGeneration2(target, res)) return;
|
|
24798
25749
|
res.status(200).json({ v: 1, tasks: tasks.map(toView) });
|
|
24799
25750
|
} catch (err) {
|
|
@@ -24887,7 +25838,10 @@ function registerScheduledTaskCrudRoutes(app, deps) {
|
|
|
24887
25838
|
let boundSessionId;
|
|
24888
25839
|
if (bridge) {
|
|
24889
25840
|
try {
|
|
24890
|
-
if ((await
|
|
25841
|
+
if ((await runWithScheduledTaskTarget(
|
|
25842
|
+
target,
|
|
25843
|
+
() => readCronTasks(workspaceCwd)
|
|
25844
|
+
)).length >= MAX_SCHEDULED_TASKS) {
|
|
24891
25845
|
res.status(409).json({
|
|
24892
25846
|
error: `Maximum number of scheduled tasks (${MAX_SCHEDULED_TASKS}) reached`,
|
|
24893
25847
|
code: "max_tasks_reached"
|
|
@@ -24906,10 +25860,7 @@ function registerScheduledTaskCrudRoutes(app, deps) {
|
|
|
24906
25860
|
});
|
|
24907
25861
|
boundSessionId = session.sessionId;
|
|
24908
25862
|
if (!requireOpenGeneration2(target, res)) {
|
|
24909
|
-
await
|
|
24910
|
-
});
|
|
24911
|
-
await new SessionService(workspaceCwd).removeSession(boundSessionId).catch(() => {
|
|
24912
|
-
});
|
|
25863
|
+
await teardownBoundSession(target, boundSessionId);
|
|
24913
25864
|
return;
|
|
24914
25865
|
}
|
|
24915
25866
|
try {
|
|
@@ -24946,29 +25897,29 @@ function registerScheduledTaskCrudRoutes(app, deps) {
|
|
|
24946
25897
|
...nameResult.value !== void 0 ? { name: nameResult.value } : {}
|
|
24947
25898
|
};
|
|
24948
25899
|
const rollbackSession = /* @__PURE__ */ __name(async () => {
|
|
24949
|
-
if (boundSessionId !== void 0
|
|
24950
|
-
await
|
|
24951
|
-
});
|
|
24952
|
-
await new SessionService(workspaceCwd).removeSession(boundSessionId).catch(() => {
|
|
24953
|
-
});
|
|
25900
|
+
if (boundSessionId !== void 0) {
|
|
25901
|
+
await teardownBoundSession(target, boundSessionId);
|
|
24954
25902
|
}
|
|
24955
25903
|
}, "rollbackSession");
|
|
24956
25904
|
let overCap = false;
|
|
24957
25905
|
let rollbackBefore;
|
|
24958
25906
|
let rollbackAfter;
|
|
24959
25907
|
try {
|
|
24960
|
-
await
|
|
24961
|
-
|
|
24962
|
-
(
|
|
24963
|
-
|
|
24964
|
-
|
|
24965
|
-
|
|
24966
|
-
|
|
24967
|
-
|
|
24968
|
-
|
|
24969
|
-
|
|
24970
|
-
|
|
24971
|
-
|
|
25908
|
+
await runWithScheduledTaskTarget(
|
|
25909
|
+
target,
|
|
25910
|
+
() => updateCronTasks(
|
|
25911
|
+
workspaceCwd,
|
|
25912
|
+
(tasks) => {
|
|
25913
|
+
if (tasks.length >= MAX_SCHEDULED_TASKS) {
|
|
25914
|
+
overCap = true;
|
|
25915
|
+
return tasks;
|
|
25916
|
+
}
|
|
25917
|
+
rollbackBefore = tasks;
|
|
25918
|
+
rollbackAfter = [...tasks, task];
|
|
25919
|
+
return rollbackAfter;
|
|
25920
|
+
},
|
|
25921
|
+
{ assertCanCommit: target.assertGenerationOpen }
|
|
25922
|
+
)
|
|
24972
25923
|
);
|
|
24973
25924
|
} catch (err) {
|
|
24974
25925
|
await rollbackSession();
|
|
@@ -24987,7 +25938,7 @@ function registerScheduledTaskCrudRoutes(app, deps) {
|
|
|
24987
25938
|
target.assertGenerationOpen?.();
|
|
24988
25939
|
} catch (error2) {
|
|
24989
25940
|
await rollbackCronMutation(
|
|
24990
|
-
|
|
25941
|
+
target,
|
|
24991
25942
|
rollbackBefore,
|
|
24992
25943
|
rollbackAfter,
|
|
24993
25944
|
`POST ${base}`
|
|
@@ -25121,44 +26072,47 @@ function registerScheduledTaskCrudRoutes(app, deps) {
|
|
|
25121
26072
|
let rollbackBefore;
|
|
25122
26073
|
let rollbackAfter;
|
|
25123
26074
|
try {
|
|
25124
|
-
await
|
|
25125
|
-
|
|
25126
|
-
(
|
|
25127
|
-
|
|
25128
|
-
|
|
25129
|
-
|
|
25130
|
-
|
|
25131
|
-
|
|
25132
|
-
|
|
25133
|
-
|
|
25134
|
-
|
|
25135
|
-
|
|
25136
|
-
blockedByArchive = true;
|
|
25137
|
-
return tasks;
|
|
25138
|
-
}
|
|
25139
|
-
const next = { ...current, ...patch };
|
|
25140
|
-
if (clearName) delete next.name;
|
|
25141
|
-
if (clearDelivery) delete next.delivery;
|
|
25142
|
-
const justReEnabled = current.enabled === false && patch.enabled === true;
|
|
25143
|
-
const cronChanged = patch.cron !== void 0 && canonicalCron(patch.cron) !== canonicalCron(current.cron);
|
|
25144
|
-
const becameRecurring = patch.recurring === true && current.recurring !== true;
|
|
25145
|
-
const becameOneShot = patch.recurring === false && current.recurring !== false;
|
|
25146
|
-
{
|
|
25147
|
-
const now = Date.now();
|
|
25148
|
-
const minute = now - now % 6e4;
|
|
25149
|
-
if (next.recurring && (justReEnabled || cronChanged || becameRecurring)) {
|
|
25150
|
-
next.lastFiredAt = minute;
|
|
25151
|
-
} else if (!next.recurring && (justReEnabled || cronChanged || becameOneShot)) {
|
|
25152
|
-
next.createdAt = now;
|
|
25153
|
-
next.lastFiredAt = minute;
|
|
26075
|
+
await runWithScheduledTaskTarget(
|
|
26076
|
+
target,
|
|
26077
|
+
() => updateCronTasks(
|
|
26078
|
+
workspaceCwd,
|
|
26079
|
+
(tasks) => {
|
|
26080
|
+
const idx = tasks.findIndex((t) => t.id === id);
|
|
26081
|
+
if (idx === -1) return tasks;
|
|
26082
|
+
found = true;
|
|
26083
|
+
const current = tasks[idx];
|
|
26084
|
+
if (patch.enabled === true && taskHasLegacyCondition(current)) {
|
|
26085
|
+
blockedLegacy = true;
|
|
26086
|
+
return tasks;
|
|
25154
26087
|
}
|
|
25155
|
-
|
|
25156
|
-
|
|
25157
|
-
|
|
25158
|
-
|
|
25159
|
-
|
|
25160
|
-
|
|
25161
|
-
|
|
26088
|
+
if (patch.enabled === true && current.disabledByArchive === true) {
|
|
26089
|
+
blockedByArchive = true;
|
|
26090
|
+
return tasks;
|
|
26091
|
+
}
|
|
26092
|
+
const next = { ...current, ...patch };
|
|
26093
|
+
if (clearName) delete next.name;
|
|
26094
|
+
if (clearDelivery) delete next.delivery;
|
|
26095
|
+
const justReEnabled = current.enabled === false && patch.enabled === true;
|
|
26096
|
+
const cronChanged = patch.cron !== void 0 && canonicalCron(patch.cron) !== canonicalCron(current.cron);
|
|
26097
|
+
const becameRecurring = patch.recurring === true && current.recurring !== true;
|
|
26098
|
+
const becameOneShot = patch.recurring === false && current.recurring !== false;
|
|
26099
|
+
{
|
|
26100
|
+
const now = Date.now();
|
|
26101
|
+
const minute = now - now % 6e4;
|
|
26102
|
+
if (next.recurring && (justReEnabled || cronChanged || becameRecurring)) {
|
|
26103
|
+
next.lastFiredAt = minute;
|
|
26104
|
+
} else if (!next.recurring && (justReEnabled || cronChanged || becameOneShot)) {
|
|
26105
|
+
next.createdAt = now;
|
|
26106
|
+
next.lastFiredAt = minute;
|
|
26107
|
+
}
|
|
26108
|
+
}
|
|
26109
|
+
updated = next;
|
|
26110
|
+
rollbackBefore = tasks;
|
|
26111
|
+
rollbackAfter = tasks.map((t, i) => i === idx ? next : t);
|
|
26112
|
+
return rollbackAfter;
|
|
26113
|
+
},
|
|
26114
|
+
{ assertCanCommit: target.assertGenerationOpen }
|
|
26115
|
+
)
|
|
25162
26116
|
);
|
|
25163
26117
|
} catch (err) {
|
|
25164
26118
|
if (sendGenerationClosedError(res, err)) return;
|
|
@@ -25176,7 +26130,7 @@ function registerScheduledTaskCrudRoutes(app, deps) {
|
|
|
25176
26130
|
target.assertGenerationOpen?.();
|
|
25177
26131
|
} catch (error2) {
|
|
25178
26132
|
await rollbackCronMutation(
|
|
25179
|
-
|
|
26133
|
+
target,
|
|
25180
26134
|
rollbackBefore,
|
|
25181
26135
|
rollbackAfter,
|
|
25182
26136
|
`PATCH ${base}/${id}`
|
|
@@ -25245,21 +26199,24 @@ function registerScheduledTaskCrudRoutes(app, deps) {
|
|
|
25245
26199
|
let rollbackBefore;
|
|
25246
26200
|
let rollbackAfter;
|
|
25247
26201
|
try {
|
|
25248
|
-
await
|
|
25249
|
-
|
|
25250
|
-
(
|
|
25251
|
-
|
|
25252
|
-
|
|
25253
|
-
|
|
25254
|
-
|
|
25255
|
-
|
|
25256
|
-
|
|
25257
|
-
|
|
25258
|
-
|
|
25259
|
-
|
|
25260
|
-
|
|
25261
|
-
|
|
25262
|
-
|
|
26202
|
+
await runWithScheduledTaskTarget(
|
|
26203
|
+
target,
|
|
26204
|
+
() => updateCronTasks(
|
|
26205
|
+
workspaceCwd,
|
|
26206
|
+
(tasks) => {
|
|
26207
|
+
const idx = tasks.findIndex((t) => t.id === id);
|
|
26208
|
+
if (idx === -1) return tasks;
|
|
26209
|
+
const match = tasks[idx].sessionId;
|
|
26210
|
+
if (typeof match === "string" && match.length > 0) {
|
|
26211
|
+
boundSessionId = match;
|
|
26212
|
+
}
|
|
26213
|
+
removed = true;
|
|
26214
|
+
rollbackBefore = tasks;
|
|
26215
|
+
rollbackAfter = tasks.filter((_, i) => i !== idx);
|
|
26216
|
+
return rollbackAfter;
|
|
26217
|
+
},
|
|
26218
|
+
{ assertCanCommit: target.assertGenerationOpen }
|
|
26219
|
+
)
|
|
25263
26220
|
);
|
|
25264
26221
|
} catch (err) {
|
|
25265
26222
|
if (sendGenerationClosedError(res, err)) return;
|
|
@@ -25277,7 +26234,7 @@ function registerScheduledTaskCrudRoutes(app, deps) {
|
|
|
25277
26234
|
target.assertGenerationOpen?.();
|
|
25278
26235
|
} catch (error2) {
|
|
25279
26236
|
await rollbackCronMutation(
|
|
25280
|
-
|
|
26237
|
+
target,
|
|
25281
26238
|
rollbackBefore,
|
|
25282
26239
|
rollbackAfter,
|
|
25283
26240
|
`DELETE ${base}/${id}`
|
|
@@ -25321,37 +26278,40 @@ function registerScheduledTaskCrudRoutes(app, deps) {
|
|
|
25321
26278
|
let rollbackBefore;
|
|
25322
26279
|
let rollbackAfter;
|
|
25323
26280
|
try {
|
|
25324
|
-
await
|
|
25325
|
-
|
|
25326
|
-
(
|
|
25327
|
-
|
|
25328
|
-
|
|
25329
|
-
|
|
25330
|
-
|
|
25331
|
-
|
|
25332
|
-
|
|
25333
|
-
|
|
25334
|
-
|
|
25335
|
-
|
|
25336
|
-
|
|
25337
|
-
|
|
25338
|
-
|
|
25339
|
-
|
|
25340
|
-
|
|
25341
|
-
|
|
25342
|
-
|
|
25343
|
-
|
|
25344
|
-
|
|
25345
|
-
|
|
25346
|
-
|
|
25347
|
-
|
|
25348
|
-
|
|
25349
|
-
|
|
25350
|
-
|
|
25351
|
-
|
|
25352
|
-
|
|
25353
|
-
|
|
25354
|
-
|
|
26281
|
+
await runWithScheduledTaskTarget(
|
|
26282
|
+
target,
|
|
26283
|
+
() => updateCronTasks(
|
|
26284
|
+
workspaceCwd,
|
|
26285
|
+
(tasks) => {
|
|
26286
|
+
const idx = tasks.findIndex((t) => t.id === id);
|
|
26287
|
+
if (idx === -1) return tasks;
|
|
26288
|
+
found = true;
|
|
26289
|
+
const current = tasks[idx];
|
|
26290
|
+
if (taskHasLegacyCondition(current)) {
|
|
26291
|
+
blockedLegacy = true;
|
|
26292
|
+
return tasks;
|
|
26293
|
+
}
|
|
26294
|
+
if (current.enabled === false) {
|
|
26295
|
+
blockedDisabled = true;
|
|
26296
|
+
return tasks;
|
|
26297
|
+
}
|
|
26298
|
+
const next = {
|
|
26299
|
+
...current,
|
|
26300
|
+
lastFiredAt: now,
|
|
26301
|
+
runs: appendCronRun(current.runs, {
|
|
26302
|
+
at: now,
|
|
26303
|
+
kind: "manual",
|
|
26304
|
+
...current.sessionId ? { sessionId: current.sessionId } : {}
|
|
26305
|
+
})
|
|
26306
|
+
};
|
|
26307
|
+
updated = next;
|
|
26308
|
+
rollbackBefore = tasks;
|
|
26309
|
+
const nextTasks = !current.recurring ? tasks.filter((_, i) => i !== idx) : tasks.map((t, i) => i === idx ? next : t);
|
|
26310
|
+
rollbackAfter = nextTasks;
|
|
26311
|
+
return nextTasks;
|
|
26312
|
+
},
|
|
26313
|
+
{ assertCanCommit: target.assertGenerationOpen }
|
|
26314
|
+
)
|
|
25355
26315
|
);
|
|
25356
26316
|
} catch (err) {
|
|
25357
26317
|
if (sendGenerationClosedError(res, err)) return;
|
|
@@ -25369,7 +26329,7 @@ function registerScheduledTaskCrudRoutes(app, deps) {
|
|
|
25369
26329
|
target.assertGenerationOpen?.();
|
|
25370
26330
|
} catch (error2) {
|
|
25371
26331
|
await rollbackCronMutation(
|
|
25372
|
-
|
|
26332
|
+
target,
|
|
25373
26333
|
rollbackBefore,
|
|
25374
26334
|
rollbackAfter,
|
|
25375
26335
|
`POST ${base}/${id}/run`
|
|
@@ -25425,6 +26385,12 @@ function registerScheduledTasksRoutes(app, deps) {
|
|
|
25425
26385
|
if (runtime && !requireTrustedWorkspaceRuntime(runtime, res)) return null;
|
|
25426
26386
|
return {
|
|
25427
26387
|
workspaceCwd: boundWorkspace,
|
|
26388
|
+
...runtime ? {
|
|
26389
|
+
runtimeBaseDir: runtime.sessionRuntimeBaseDir,
|
|
26390
|
+
...deps.cleanupSession ? {
|
|
26391
|
+
cleanupSession: /* @__PURE__ */ __name((sessionId) => deps.cleanupSession(runtime, sessionId), "cleanupSession")
|
|
26392
|
+
} : {}
|
|
26393
|
+
} : {},
|
|
25428
26394
|
bridge: runtime?.bridge ?? bridge,
|
|
25429
26395
|
...runtime?.generationGuard ? {
|
|
25430
26396
|
assertGenerationOpen: /* @__PURE__ */ __name(() => runtime.generationGuard?.assertOpen(), "assertGenerationOpen")
|
|
@@ -25443,7 +26409,8 @@ function registerWorkspaceQualifiedScheduledTasksRoutes(app, deps) {
|
|
|
25443
26409
|
mutate,
|
|
25444
26410
|
safeBody: safeBody2,
|
|
25445
26411
|
manageScheduledTaskSessions,
|
|
25446
|
-
channelDeliveryAuthorizations
|
|
26412
|
+
channelDeliveryAuthorizations,
|
|
26413
|
+
cleanupSession
|
|
25447
26414
|
} = deps;
|
|
25448
26415
|
registerScheduledTaskCrudRoutes(app, {
|
|
25449
26416
|
prefix: "/workspaces/:workspace",
|
|
@@ -25457,6 +26424,10 @@ function registerWorkspaceQualifiedScheduledTasksRoutes(app, deps) {
|
|
|
25457
26424
|
if (!requireTrustedWorkspaceRuntime(runtime, res)) return null;
|
|
25458
26425
|
return {
|
|
25459
26426
|
workspaceCwd: runtime.workspaceCwd,
|
|
26427
|
+
runtimeBaseDir: runtime.sessionRuntimeBaseDir,
|
|
26428
|
+
...cleanupSession ? {
|
|
26429
|
+
cleanupSession: /* @__PURE__ */ __name((sessionId) => cleanupSession(runtime, sessionId), "cleanupSession")
|
|
26430
|
+
} : {},
|
|
25460
26431
|
// Mirror the primary surface: only bind a session when management is on,
|
|
25461
26432
|
// so a bound task always has something to keep it resident + rehydrate it.
|
|
25462
26433
|
bridge: manageScheduledTaskSessions ? runtime.bridge : void 0,
|
|
@@ -25735,7 +26706,7 @@ __name(collectBoundSessionIds, "collectBoundSessionIds");
|
|
|
25735
26706
|
var KEEPALIVE_REVIVE_TIMEOUT_MS = 3e4;
|
|
25736
26707
|
var KEEPALIVE_SPAWN_TIMEOUT_MS = 3e4;
|
|
25737
26708
|
var MAX_REVIVE_BACKOFF_MS = 30 * 6e4;
|
|
25738
|
-
async function bindAndNameSessions(bridge, boundWorkspace, tasks, renamed, spawnTimeoutMs, binding) {
|
|
26709
|
+
async function bindAndNameSessions(bridge, boundWorkspace, tasks, renamed, spawnTimeoutMs, binding, cleanupSession) {
|
|
25739
26710
|
const unbound = tasks.filter(
|
|
25740
26711
|
(t) => !t.sessionId && t.enabled !== false && !taskHasLegacyCondition(t) && !binding.has(t.id)
|
|
25741
26712
|
);
|
|
@@ -25753,16 +26724,14 @@ async function bindAndNameSessions(bridge, boundWorkspace, tasks, renamed, spawn
|
|
|
25753
26724
|
sourceId: task.id
|
|
25754
26725
|
});
|
|
25755
26726
|
let timedOut = false;
|
|
25756
|
-
rawSpawn.then(({ sessionId: sessionId2 }) => {
|
|
26727
|
+
rawSpawn.then(async ({ sessionId: sessionId2 }) => {
|
|
25757
26728
|
if (timedOut) {
|
|
25758
26729
|
log.debug(
|
|
25759
26730
|
"keepalive: late spawn resolved, cleaning up",
|
|
25760
26731
|
task.id,
|
|
25761
26732
|
sessionId2
|
|
25762
26733
|
);
|
|
25763
|
-
|
|
25764
|
-
});
|
|
25765
|
-
new SessionService(boundWorkspace).removeSession(sessionId2).catch(() => {
|
|
26734
|
+
await cleanupSession(sessionId2).catch(() => {
|
|
25766
26735
|
});
|
|
25767
26736
|
}
|
|
25768
26737
|
}).catch(() => {
|
|
@@ -25810,9 +26779,7 @@ async function bindAndNameSessions(bridge, boundWorkspace, tasks, renamed, spawn
|
|
|
25810
26779
|
} catch (err) {
|
|
25811
26780
|
log.debug("keepalive: failed to bind task", task.id, err);
|
|
25812
26781
|
if (spawnedSessionId !== void 0) {
|
|
25813
|
-
await
|
|
25814
|
-
});
|
|
25815
|
-
await new SessionService(boundWorkspace).removeSession(spawnedSessionId).catch(() => {
|
|
26782
|
+
await cleanupSession(spawnedSessionId).catch(() => {
|
|
25816
26783
|
});
|
|
25817
26784
|
}
|
|
25818
26785
|
}
|
|
@@ -25834,11 +26801,17 @@ function startScheduledTaskKeepalive(opts) {
|
|
|
25834
26801
|
const { bridge, boundWorkspace, intervalMs } = opts;
|
|
25835
26802
|
const reviveTimeoutMs = opts.reviveTimeoutMs ?? KEEPALIVE_REVIVE_TIMEOUT_MS;
|
|
25836
26803
|
const spawnTimeoutMs = opts.spawnTimeoutMs ?? KEEPALIVE_SPAWN_TIMEOUT_MS;
|
|
26804
|
+
const cleanupSession = opts.cleanupSession ?? (async (sessionId) => {
|
|
26805
|
+
await bridge.closeSession(sessionId);
|
|
26806
|
+
await new SessionService(boundWorkspace, {
|
|
26807
|
+
runtimeBaseDir: opts.runtimeBaseDir
|
|
26808
|
+
}).removeSession(sessionId);
|
|
26809
|
+
});
|
|
25837
26810
|
const reviveState = /* @__PURE__ */ new Map();
|
|
25838
26811
|
const reviving = /* @__PURE__ */ new Set();
|
|
25839
26812
|
const binding = /* @__PURE__ */ new Set();
|
|
25840
26813
|
const renamed = /* @__PURE__ */ new Set();
|
|
25841
|
-
const
|
|
26814
|
+
const tickInRuntime = /* @__PURE__ */ __name(async () => {
|
|
25842
26815
|
let tasks;
|
|
25843
26816
|
try {
|
|
25844
26817
|
tasks = await readCronTasks(boundWorkspace);
|
|
@@ -25916,9 +26889,14 @@ function startScheduledTaskKeepalive(opts) {
|
|
|
25916
26889
|
tasks,
|
|
25917
26890
|
renamed,
|
|
25918
26891
|
spawnTimeoutMs,
|
|
25919
|
-
binding
|
|
26892
|
+
binding,
|
|
26893
|
+
cleanupSession
|
|
25920
26894
|
);
|
|
25921
|
-
}, "
|
|
26895
|
+
}, "tickInRuntime");
|
|
26896
|
+
const tick = /* @__PURE__ */ __name(() => opts.runtimeBaseDir === void 0 ? tickInRuntime() : Storage.runWithResolvedRuntimeBaseDir(
|
|
26897
|
+
opts.runtimeBaseDir,
|
|
26898
|
+
tickInRuntime
|
|
26899
|
+
), "tick");
|
|
25922
26900
|
let running = false;
|
|
25923
26901
|
const timer = setInterval(() => {
|
|
25924
26902
|
if (running) return;
|
|
@@ -25929,7 +26907,10 @@ function startScheduledTaskKeepalive(opts) {
|
|
|
25929
26907
|
}, intervalMs);
|
|
25930
26908
|
timer.unref?.();
|
|
25931
26909
|
let bindDebounce;
|
|
25932
|
-
const cronFilePath = getCronFilePath(boundWorkspace)
|
|
26910
|
+
const cronFilePath = opts.runtimeBaseDir === void 0 ? getCronFilePath(boundWorkspace) : Storage.runWithResolvedRuntimeBaseDir(
|
|
26911
|
+
opts.runtimeBaseDir,
|
|
26912
|
+
() => getCronFilePath(boundWorkspace)
|
|
26913
|
+
);
|
|
25933
26914
|
const cronDir = path11.dirname(cronFilePath);
|
|
25934
26915
|
const cronFileName = path11.basename(cronFilePath);
|
|
25935
26916
|
let fileWatcher;
|
|
@@ -27424,6 +28405,14 @@ function sendPermissionVoteError(res, err, ctx, daemonLog) {
|
|
|
27424
28405
|
}
|
|
27425
28406
|
__name(sendPermissionVoteError, "sendPermissionVoteError");
|
|
27426
28407
|
function sendBridgeError(res, err, ctx, daemonLog) {
|
|
28408
|
+
if (err instanceof DaemonDrainingError) {
|
|
28409
|
+
res.status(503).json({
|
|
28410
|
+
error: err.message,
|
|
28411
|
+
code: err.code,
|
|
28412
|
+
errorKind: err.code
|
|
28413
|
+
});
|
|
28414
|
+
return;
|
|
28415
|
+
}
|
|
27427
28416
|
if (sendGenerationClosedError(res, err)) return;
|
|
27428
28417
|
if (err instanceof SessionWriterError) {
|
|
27429
28418
|
res.status(err.httpStatus).json({
|
|
@@ -32730,6 +33719,18 @@ function parsePairingCode(body, res) {
|
|
|
32730
33719
|
return code.trim().toUpperCase();
|
|
32731
33720
|
}
|
|
32732
33721
|
__name(parsePairingCode, "parsePairingCode");
|
|
33722
|
+
function parsePairingSenderId(body, res) {
|
|
33723
|
+
const senderId = body["senderId"];
|
|
33724
|
+
if (typeof senderId !== "string" || senderId.length === 0) {
|
|
33725
|
+
res.status(400).json({
|
|
33726
|
+
error: "`senderId` must be a non-empty string.",
|
|
33727
|
+
code: "invalid_channel_pairing_sender_id"
|
|
33728
|
+
});
|
|
33729
|
+
return void 0;
|
|
33730
|
+
}
|
|
33731
|
+
return senderId;
|
|
33732
|
+
}
|
|
33733
|
+
__name(parsePairingSenderId, "parsePairingSenderId");
|
|
32733
33734
|
function errorCode2(error2) {
|
|
32734
33735
|
if (!error2 || typeof error2 !== "object") return void 0;
|
|
32735
33736
|
try {
|
|
@@ -32751,6 +33752,7 @@ var ERROR_STATUS = /* @__PURE__ */ new Map([
|
|
|
32751
33752
|
["untrusted_workspace", 403],
|
|
32752
33753
|
["channel_instance_not_found", 404],
|
|
32753
33754
|
["channel_pairing_request_not_found", 404],
|
|
33755
|
+
["channel_pairing_approval_not_found", 404],
|
|
32754
33756
|
["channel_pairing_not_enabled", 409],
|
|
32755
33757
|
["channel_settings_conflict", 409],
|
|
32756
33758
|
["channel_runtime_owner_mismatch", 409],
|
|
@@ -32807,6 +33809,8 @@ function registerWorkspaceChannelManagementRoutes(app, deps) {
|
|
|
32807
33809
|
const register = /* @__PURE__ */ __name((prefix, resolveRuntime) => {
|
|
32808
33810
|
const pairingRead = deps.mutate({ strict: true });
|
|
32809
33811
|
const pairingApprove = deps.mutate({ strict: true });
|
|
33812
|
+
const pairingApprovalsRead = deps.mutate({ strict: true });
|
|
33813
|
+
const pairingRevoke = deps.mutate({ strict: true });
|
|
32810
33814
|
const upsert = deps.mutate({ strict: true });
|
|
32811
33815
|
const remove = deps.mutate({ strict: true });
|
|
32812
33816
|
const startup = deps.mutate({ strict: true });
|
|
@@ -32869,6 +33873,40 @@ function registerWorkspaceChannelManagementRoutes(app, deps) {
|
|
|
32869
33873
|
}
|
|
32870
33874
|
}
|
|
32871
33875
|
);
|
|
33876
|
+
app.get(
|
|
33877
|
+
`${prefix}/channels/:name/pairing-approvals`,
|
|
33878
|
+
pairingApprovalsRead,
|
|
33879
|
+
async (req, res) => {
|
|
33880
|
+
const resolved = await target(req, res);
|
|
33881
|
+
if (!resolved || !validateClient(req, res, resolved.runtime)) return;
|
|
33882
|
+
const name = parseInstanceName(req, res);
|
|
33883
|
+
if (!name) return;
|
|
33884
|
+
try {
|
|
33885
|
+
noStore(res);
|
|
33886
|
+
res.status(200).json(await resolved.service.pairingApprovals(name));
|
|
33887
|
+
} catch (error2) {
|
|
33888
|
+
sendManagementError(res, error2);
|
|
33889
|
+
}
|
|
33890
|
+
}
|
|
33891
|
+
);
|
|
33892
|
+
app.delete(
|
|
33893
|
+
`${prefix}/channels/:name/pairing-approvals`,
|
|
33894
|
+
pairingRevoke,
|
|
33895
|
+
async (req, res) => {
|
|
33896
|
+
const resolved = await target(req, res);
|
|
33897
|
+
if (!resolved || !validateClient(req, res, resolved.runtime)) return;
|
|
33898
|
+
const name = parseInstanceName(req, res);
|
|
33899
|
+
if (!name) return;
|
|
33900
|
+
const senderId = parsePairingSenderId(deps.safeBody(req), res);
|
|
33901
|
+
if (!senderId) return;
|
|
33902
|
+
try {
|
|
33903
|
+
noStore(res);
|
|
33904
|
+
res.status(200).json(await resolved.service.revokePairingApproval(name, senderId));
|
|
33905
|
+
} catch (error2) {
|
|
33906
|
+
sendManagementError(res, error2);
|
|
33907
|
+
}
|
|
33908
|
+
}
|
|
33909
|
+
);
|
|
32872
33910
|
app.put(`${prefix}/channels/:name`, upsert, async (req, res) => {
|
|
32873
33911
|
const resolved = await target(req, res);
|
|
32874
33912
|
if (!resolved || !validateClient(req, res, resolved.runtime)) return;
|
|
@@ -33993,6 +35031,16 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
33993
35031
|
defaultBridgeForAdmission = bridge;
|
|
33994
35032
|
}
|
|
33995
35033
|
const archiveCoordinator = new SessionArchiveCoordinator();
|
|
35034
|
+
app.locals.sessionArchiveCoordinator = archiveCoordinator;
|
|
35035
|
+
const cleanupSession = /* @__PURE__ */ __name((runtime, sessionId) => runWithWorkspaceRuntimeStorage(
|
|
35036
|
+
runtime,
|
|
35037
|
+
() => deleteDaemonSessionIfOrphan({
|
|
35038
|
+
sessionId,
|
|
35039
|
+
service: createWorkspaceRuntimeSessionService(runtime),
|
|
35040
|
+
bridge: runtime.bridge,
|
|
35041
|
+
coordinator: archiveCoordinator
|
|
35042
|
+
})
|
|
35043
|
+
), "cleanupSession");
|
|
33996
35044
|
installSelfOriginStripMiddleware(app, getPort);
|
|
33997
35045
|
app.locals.fsFactory = fsFactory;
|
|
33998
35046
|
app.locals.boundWorkspace = boundWorkspace;
|
|
@@ -34057,6 +35105,7 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
34057
35105
|
{
|
|
34058
35106
|
workspaceId: hashDaemonWorkspace(boundWorkspace),
|
|
34059
35107
|
workspaceCwd: boundWorkspace,
|
|
35108
|
+
sessionRuntimeBaseDir: Storage.getRuntimeBaseDir(),
|
|
34060
35109
|
primary: true,
|
|
34061
35110
|
trusted: deps.primaryWorkspaceTrusted ?? false,
|
|
34062
35111
|
env: primaryRuntimeEnvMetadata ?? {
|
|
@@ -34681,6 +35730,7 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
34681
35730
|
safeBody,
|
|
34682
35731
|
bridge: deps.manageScheduledTaskSessions ? primaryBridge : void 0,
|
|
34683
35732
|
getRuntime: /* @__PURE__ */ __name(() => workspaceRegistry.primaryEntry.state === "active" ? workspaceRegistry.primaryEntry.current?.runtime : void 0, "getRuntime"),
|
|
35733
|
+
cleanupSession,
|
|
34684
35734
|
channelDeliveryAuthorizations: deps.channelDeliveryAuthorizations
|
|
34685
35735
|
});
|
|
34686
35736
|
registerGoalsRoutes(app, {
|
|
@@ -34694,7 +35744,8 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
34694
35744
|
mutate,
|
|
34695
35745
|
safeBody,
|
|
34696
35746
|
manageScheduledTaskSessions: deps.manageScheduledTaskSessions === true,
|
|
34697
|
-
channelDeliveryAuthorizations: deps.channelDeliveryAuthorizations
|
|
35747
|
+
channelDeliveryAuthorizations: deps.channelDeliveryAuthorizations,
|
|
35748
|
+
cleanupSession
|
|
34698
35749
|
});
|
|
34699
35750
|
registerUsageStatsRoutes(app);
|
|
34700
35751
|
if (deps.manageScheduledTaskSessions) {
|
|
@@ -34714,23 +35765,26 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
34714
35765
|
}, "registerScheduledTaskAuthorizations");
|
|
34715
35766
|
const idleTimeoutMs = opts.sessionIdleTimeoutMs ?? DEFAULT_SESSION_IDLE_TIMEOUT_MS;
|
|
34716
35767
|
const keepaliveIntervalMs = computeKeepaliveIntervalMs(idleTimeoutMs);
|
|
34717
|
-
const rehydrateWorkspace = /* @__PURE__ */ __name((
|
|
34718
|
-
void
|
|
34719
|
-
|
|
34720
|
-
|
|
34721
|
-
|
|
34722
|
-
|
|
34723
|
-
|
|
34724
|
-
|
|
35768
|
+
const rehydrateWorkspace = /* @__PURE__ */ __name((runtime) => {
|
|
35769
|
+
void runWithWorkspaceRuntimeStorage(
|
|
35770
|
+
runtime,
|
|
35771
|
+
() => rehydrateScheduledTaskSessions({
|
|
35772
|
+
bridge: runtime.bridge,
|
|
35773
|
+
boundWorkspace: runtime.workspaceCwd,
|
|
35774
|
+
onTasksRead: /* @__PURE__ */ __name((tasks) => registerScheduledTaskAuthorizations(runtime.workspaceCwd, tasks), "onTasksRead"),
|
|
35775
|
+
onError: /* @__PURE__ */ __name((sessionId, err) => {
|
|
35776
|
+
process.stderr.write(
|
|
35777
|
+
`qwen serve: failed to rehydrate scheduled-task session ${sessionId}: ${err instanceof Error ? err.message : String(err)}
|
|
34725
35778
|
`
|
|
34726
|
-
|
|
34727
|
-
|
|
34728
|
-
|
|
34729
|
-
|
|
34730
|
-
|
|
34731
|
-
|
|
34732
|
-
|
|
34733
|
-
|
|
35779
|
+
);
|
|
35780
|
+
}, "onError")
|
|
35781
|
+
// Outer catch is defense-in-depth: rehydrateScheduledTaskSessions already
|
|
35782
|
+
// catches readCronTasks failures and per-session load errors internally
|
|
35783
|
+
// (returning { loaded, failed }), so this only guards an unexpected throw
|
|
35784
|
+
// from the function entry itself. Log rather than swallow it — a silent
|
|
35785
|
+
// failure here leaves every bound task dormant with no diagnostic.
|
|
35786
|
+
})
|
|
35787
|
+
).catch((err) => {
|
|
34734
35788
|
process.stderr.write(
|
|
34735
35789
|
`qwen serve: unexpected scheduled-task rehydration failure: ${err instanceof Error ? err.message : String(err)}
|
|
34736
35790
|
`
|
|
@@ -34746,9 +35800,11 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
34746
35800
|
bridge: runtime.bridge,
|
|
34747
35801
|
boundWorkspace: runtime.workspaceCwd,
|
|
34748
35802
|
intervalMs: keepaliveIntervalMs,
|
|
35803
|
+
runtimeBaseDir: runtime.sessionRuntimeBaseDir,
|
|
35804
|
+
cleanupSession: /* @__PURE__ */ __name((sessionId) => cleanupSession(runtime, sessionId), "cleanupSession"),
|
|
34749
35805
|
onTasksRead: /* @__PURE__ */ __name((tasks) => registerScheduledTaskAuthorizations(runtime.workspaceCwd, tasks), "onTasksRead")
|
|
34750
35806
|
});
|
|
34751
|
-
rehydrateWorkspace(runtime
|
|
35807
|
+
rehydrateWorkspace(runtime);
|
|
34752
35808
|
keepaliveStops.set(runtime.workspaceCwd, keepalive.stop);
|
|
34753
35809
|
}, "startKeepaliveForWorkspace");
|
|
34754
35810
|
for (const runtime of workspaceRegistry.list()) {
|