@qwen-code/qwen-code 0.20.1-preview.7215 → 0.20.2-gdpval-vl-agent.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundled/qc-helper/docs/configuration/settings.md +1 -1
- package/bundled/qc-helper/docs/features/auto-mode.md +19 -16
- package/bundled/qc-helper/docs/features/commands.md +54 -0
- package/bundled/qc-helper/docs/features/sub-agents.md +16 -7
- package/bundled/qc-helper/docs/integration-github-action.md +1 -1
- package/bundled/qc-helper/docs/qwen-serve.md +2 -1
- package/bundled/review/DESIGN.md +2 -2
- package/bundled/review/SKILL.md +4 -4
- package/chunks/{MaxSizedBox-EH6G5AEH.js → MaxSizedBox-KYNG7EN7.js} +38 -35
- package/chunks/{StandaloneSessionPicker-264A3TEA.js → StandaloneSessionPicker-7XN4WVVG.js} +55 -52
- package/chunks/{acpAgent-6RBIJFDI.js → acpAgent-FTFFYP5G.js} +1536 -512
- package/chunks/{agent-QURXGAA3.js → agent-Y76LTTOT.js} +34 -31
- package/chunks/{agent-headless-CRGX4ICQ.js → agent-headless-IVAEQPK6.js} +34 -31
- package/chunks/{anthropicContentGenerator-BWBAZGTW.js → anthropicContentGenerator-HGWAHO24.js} +11 -13
- package/chunks/{artifact-tool-IUJ7QWCX.js → artifact-tool-56T5IMBP.js} +3 -3
- package/chunks/{askUserQuestion-IUMUUTDQ.js → askUserQuestion-E25OBIC2.js} +3 -3
- package/chunks/{bridge-MNFVKPMI.js → bridge-4M77KUEV.js} +39 -36
- package/chunks/{build-SSCNEHZZ.js → build-GHIZ4MSZ.js} +1 -1
- package/chunks/{ca-2SL2BXTK.js → ca-N6VVUFVB.js} +611 -201
- package/chunks/{channel-worker-group-53CMOPFT.js → channel-worker-group-QZV2SP5U.js} +4 -4
- package/chunks/{channel-worker-manager-UTXILKC2.js → channel-worker-manager-3GMAU45H.js} +4 -4
- package/chunks/{channel-worker-supervisor-ZGO2W2MD.js → channel-worker-supervisor-QCXSXCRY.js} +3 -3
- package/chunks/{chunk-UQES76OO.js → chunk-2HGTVAOW.js} +6 -6
- package/chunks/{chunk-2HOVDT7W.js → chunk-2LI23QA6.js} +1 -1
- package/chunks/{chunk-ANHT55MR.js → chunk-2P6CNEHB.js} +1 -1
- package/chunks/chunk-2RFKHEXL.js +74 -0
- package/chunks/{chunk-BF32GYSY.js → chunk-3IABAQR6.js} +1 -1
- package/chunks/chunk-3Z43GZUQ.js +32 -0
- package/chunks/chunk-43T5WDQ7.js +127 -0
- package/chunks/{chunk-DA7OOKVN.js → chunk-4CTP6VR6.js} +29 -2
- package/chunks/{chunk-JD3MKVKL.js → chunk-4K56OJFJ.js} +1 -1
- package/chunks/{chunk-KTUQMDEP.js → chunk-4K7VDKAD.js} +1 -1
- package/chunks/{chunk-QKYTTBYW.js → chunk-4LVZNIDO.js} +1 -1
- package/chunks/{chunk-ZEOZL37W.js → chunk-57FIIFJN.js} +1 -1
- package/chunks/{chunk-7YBZGNEC.js → chunk-5G3ZVADU.js} +308 -199
- package/chunks/{chunk-X4CGDBKA.js → chunk-6GEJX3LE.js} +3 -3
- package/chunks/{chunk-6GUTHAN7.js → chunk-6HOCJNO5.js} +1 -1
- package/chunks/{chunk-GMGDLUC7.js → chunk-6IL7KRLE.js} +1 -1
- package/chunks/chunk-6PVPNMXU.js +29 -0
- package/chunks/{chunk-BDBMYST4.js → chunk-6X4GWOPW.js} +1 -1
- package/chunks/{chunk-4ODB7WIB.js → chunk-6ZBPS62S.js} +1 -1
- package/chunks/{chunk-AYCDXHZB.js → chunk-7Z6JQEL6.js} +1 -1
- package/chunks/{chunk-WAX3ITOA.js → chunk-A3TAEAHX.js} +1 -1
- package/chunks/{chunk-OLMETXLX.js → chunk-ACW3VNUE.js} +2 -2
- package/chunks/{chunk-IB35C3IL.js → chunk-AVQ6EX4J.js} +1 -1
- package/chunks/{chunk-TTSKHF43.js → chunk-BK6UOUJ2.js} +2 -2
- package/chunks/{chunk-6OH6A5EX.js → chunk-BLAEKN6K.js} +20603 -17709
- package/chunks/chunk-BULDBTYC.js +153 -0
- package/chunks/{chunk-XNP57UDV.js → chunk-C3EXYVFX.js} +2 -2
- package/chunks/{chunk-FVS747N7.js → chunk-C54UTDOC.js} +23 -19
- package/chunks/{chunk-MAQQGNQ5.js → chunk-CBOQ3HY7.js} +466 -10
- package/chunks/{chunk-VFAE4AGH.js → chunk-CGZ5SV23.js} +72 -67
- package/chunks/{chunk-WKRXIHD6.js → chunk-COAARUPK.js} +8 -8
- package/chunks/{chunk-GA7VRJVN.js → chunk-E2ZK5M4P.js} +5 -5
- package/chunks/{chunk-5SCI6E3E.js → chunk-E4IMU4Y5.js} +1 -1
- package/chunks/{chunk-E5GIFWE3.js → chunk-EEFRJ5CT.js} +54 -33
- package/chunks/{chunk-WXAXH7IJ.js → chunk-ESQHGKPJ.js} +1 -1
- package/chunks/{chunk-NEEB7UEN.js → chunk-FFFM6NJV.js} +1 -2
- package/chunks/{chunk-Z5R4JMOL.js → chunk-FJ2IUWNQ.js} +4 -4
- package/chunks/{chunk-JVTCARQ6.js → chunk-FQI7LT7T.js} +4 -4
- package/chunks/{chunk-BRXIO5WY.js → chunk-FTNI3D7D.js} +7 -7
- package/chunks/{chunk-OMH3276Y.js → chunk-GHRSKGHF.js} +7 -7
- package/chunks/{chunk-OONJNQ42.js → chunk-GPSKDNEE.js} +3 -3
- package/chunks/{chunk-KPZNOZPC.js → chunk-GWM4PDYK.js} +19 -19
- package/chunks/{chunk-NBMIC7DR.js → chunk-H24SOJIQ.js} +2 -2
- package/chunks/{chunk-FNGK2Z5B.js → chunk-H4AR2JQF.js} +3 -3
- package/chunks/{chunk-WOT64EP2.js → chunk-HCJQORKC.js} +2 -2
- package/chunks/{chunk-7KDI2IB2.js → chunk-HDATOR4J.js} +4 -4
- package/chunks/{chunk-IE4JSQ5L.js → chunk-HIYP7IR4.js} +39 -37
- package/chunks/{chunk-N6YTEVLV.js → chunk-HL6AKUGD.js} +10 -4
- package/chunks/{chunk-BAIEQKR5.js → chunk-HPQFGWOD.js} +5 -5
- package/chunks/chunk-HTR4WV6U.js +327 -0
- package/chunks/{chunk-SDXIH6OA.js → chunk-IFUNDCQ6.js} +137 -5
- package/chunks/{chunk-Z6UEAQTP.js → chunk-IFVECEIK.js} +178 -61
- package/chunks/{chunk-QOK6RMIP.js → chunk-IKP54WUL.js} +4 -4
- package/chunks/{chunk-IUSNI6IX.js → chunk-ISMD2AB3.js} +1 -1
- package/chunks/{chunk-G45X5TRN.js → chunk-JCW2R7WC.js} +1 -72
- package/chunks/{chunk-LZYWWWCZ.js → chunk-KF6CTNTJ.js} +8 -9
- package/chunks/{chunk-EIAK6Q2B.js → chunk-KHOVYUHX.js} +2 -2
- package/chunks/chunk-KWK7UE6L.js +6194 -0
- package/chunks/{chunk-WBTZGWQ6.js → chunk-L5F3T6TQ.js} +1 -1
- package/chunks/{chunk-RELYEO3R.js → chunk-L7ASZD66.js} +244 -1607
- package/chunks/{chunk-UJEZQ562.js → chunk-LESHKUWF.js} +3 -5
- package/chunks/{chunk-OOCI5VVU.js → chunk-LIZRAKPB.js} +1 -1
- package/chunks/{chunk-Q3ZBFXK4.js → chunk-LKB5YL5T.js} +143 -36
- package/chunks/{chunk-MKLKHZAK.js → chunk-LU3RXCM7.js} +1 -1
- package/chunks/{chunk-B453NMZJ.js → chunk-M3EQ3GZC.js} +3 -3
- package/chunks/{chunk-TCKTNY66.js → chunk-M4VFMLQK.js} +6 -6
- package/chunks/{chunk-26LLB6FM.js → chunk-MDZTPSXO.js} +2 -2
- package/chunks/{chunk-4SLLEAQP.js → chunk-MJPBB2GK.js} +591 -316
- package/chunks/chunk-NABLFI57.js +82 -0
- package/chunks/{chunk-T7DDD7CZ.js → chunk-NAXEEGJU.js} +4 -4
- package/chunks/{chunk-467G3SV5.js → chunk-NPQDJGKU.js} +1 -1
- package/chunks/{chunk-FLTN6NRU.js → chunk-O4OT3DM3.js} +5 -1
- package/chunks/{chunk-3EUZWNWA.js → chunk-OPDZT2VG.js} +1 -1
- package/chunks/chunk-OQ5SYCPE.js +10017 -0
- package/chunks/{chunk-C27BYUX6.js → chunk-OQB4EXO4.js} +14 -11
- package/chunks/{chunk-V25Z5UUB.js → chunk-P6PBZL3N.js} +7 -6
- package/chunks/{chunk-5NWV4NFB.js → chunk-PRAUGUNM.js} +3 -3
- package/chunks/{chunk-MC2DOZS7.js → chunk-PVT6E3ZI.js} +3 -3
- package/chunks/{chunk-KXEGCGUG.js → chunk-Q22WWVR6.js} +31 -6
- package/chunks/{chunk-JDI67JFB.js → chunk-Q2YKNMLS.js} +3 -3
- package/chunks/{chunk-PBATSWUQ.js → chunk-QBUDF33N.js} +1 -1
- package/chunks/{chunk-Y2ENGUD6.js → chunk-QKTHJXCS.js} +1 -1
- package/chunks/{chunk-BVLROR2T.js → chunk-QLJUC7TG.js} +1 -1
- package/chunks/{chunk-UEY4AYUL.js → chunk-QNLNLENL.js} +2 -2
- package/chunks/{chunk-OKWRU4NO.js → chunk-RC7A7SSL.js} +3 -3
- package/chunks/chunk-RCUEYZDE.js +2290 -0
- package/chunks/{chunk-EVSTCA7S.js → chunk-RMY5SX7S.js} +368 -113
- package/chunks/{chunk-4WUAQ2DO.js → chunk-RTQSXHS7.js} +2 -2
- package/chunks/{chunk-RFIAR4YL.js → chunk-RV4C2ZFG.js} +1 -1
- package/chunks/{chunk-NIJEXGV6.js → chunk-RVLZCXEE.js} +79 -10
- package/chunks/{chunk-Q4RBU7WX.js → chunk-S333CBIA.js} +6 -6
- package/chunks/{chunk-JNWZQ27S.js → chunk-SP5WRGVG.js} +3 -3
- package/chunks/{chunk-FSL5W5TI.js → chunk-T2L47JJK.js} +3 -3
- package/chunks/{chunk-PWVTCGBP.js → chunk-TA4S377U.js} +30 -20
- package/chunks/{chunk-TB6UDU4T.js → chunk-THJNPLI4.js} +16 -16
- package/chunks/chunk-U6TQGUNB.js +20687 -0
- package/chunks/chunk-U7ZFW55U.js +2098 -0
- package/chunks/{chunk-W7H223ZZ.js → chunk-UGYMA4EI.js} +1 -1
- package/chunks/{chunk-X6YQWCIJ.js → chunk-UH3WSE5L.js} +13 -1
- package/chunks/{chunk-P2YAOGJD.js → chunk-UKU3NGW6.js} +3 -3
- package/chunks/{chunk-NOWTNYC7.js → chunk-UVFCANV5.js} +8 -8
- package/chunks/{chunk-CVDW42JT.js → chunk-V4AKJQ26.js} +1 -1
- package/chunks/{chunk-Z5Q65RVH.js → chunk-VJPRLNLR.js} +1 -1
- package/chunks/{chunk-Y4CRUWFZ.js → chunk-VTXX72XS.js} +60 -35
- package/chunks/{chunk-R3VWUU2E.js → chunk-VYPFXUCB.js} +1 -1
- package/chunks/chunk-WHGVTP7Q.js +1049 -0
- package/chunks/{chunk-IKP5DXZY.js → chunk-WOWQQGGN.js} +5 -5
- package/chunks/{chunk-D2VIDMVM.js → chunk-X6N25LXS.js} +2 -2
- package/chunks/chunk-XHATNRQA.js +1500 -0
- package/chunks/{chunk-2DXOIVUI.js → chunk-YLSB23Y2.js} +11 -11
- package/chunks/{chunk-S35ZDXOS.js → chunk-YM3SZTH4.js} +2 -1
- package/chunks/{chunk-OF2BBLYQ.js → chunk-YNWJAOPL.js} +2 -2
- package/chunks/{chunk-GKY2OJ7R.js → chunk-ZHERRXZJ.js} +1 -1
- package/chunks/{chunk-AR27OPIU.js → chunk-ZKFJKN23.js} +2 -2
- package/chunks/{computer-use-R7KA6UJ6.js → computer-use-UKQBH7UM.js} +39 -36
- package/chunks/{config-utils-6FXFJUYB.js → config-utils-FYTBZLCJ.js} +3 -3
- package/chunks/{contextCommand-KAQQPHZ4.js → contextCommand-ESHGAVWX.js} +36 -33
- package/chunks/{create-sub-session-TDPDBU4K.js → create-sub-session-574EPZUU.js} +34 -31
- package/chunks/{create-sub-session-X5RVIHCK.js → create-sub-session-AZ77LBL3.js} +3 -3
- package/chunks/{cron-create-AC5FFLN7.js → cron-create-KTWJM7QT.js} +5 -5
- package/chunks/{cron-delete-JEB3FAHA.js → cron-delete-2P3I5ULL.js} +5 -5
- package/chunks/{cron-list-NBYPCNIB.js → cron-list-PXDPGEDQ.js} +5 -5
- package/chunks/{daemon-RG2MAI6T.js → daemon-GJRFILYS.js} +323 -99
- package/chunks/daemon-status-provider-GZXZP3NU.js +80 -0
- package/chunks/{de-I7ZIYXZC.js → de-4IBXM7CN.js} +5 -1
- package/chunks/{dist-AU7NQQRP.js → dist-OAV7LJGJ.js} +1 -1
- package/chunks/{dist-FUTEXY6A.js → dist-OMW6WDEO.js} +1 -1
- package/chunks/{dist-2MIU4UUH.js → dist-PJLG2XYX.js} +1 -1
- package/chunks/{dist-53PZYC5B.js → dist-UIFWIFRO.js} +2 -2
- package/chunks/{dist-2BHAYBKP.js → dist-XBJVSWS2.js} +1 -1
- package/chunks/{dist-WGTQO7F2.js → dist-XRYV6TJP.js} +65 -25
- package/chunks/{earlyInputCapture-WC7RI5HV.js → earlyInputCapture-GI3HGQIT.js} +35 -32
- package/chunks/{edit-6MHKCJCM.js → edit-EBJK74B3.js} +42 -41
- package/chunks/{en-XE34GKAA.js → en-USMCCJAJ.js} +5 -1
- package/chunks/{enter-worktree-O7VJ2E7A.js → enter-worktree-2ETY5CSV.js} +39 -36
- package/chunks/{enterPlanMode-5XYAALIO.js → enterPlanMode-NY4U2727.js} +45 -37
- package/chunks/{environment-LSKFNLBU.js → environment-33IR3NOU.js} +36 -33
- package/chunks/{errors-ZFVCY6HG.js → errors-2OCY23IC.js} +36 -33
- package/chunks/{exit-worktree-MYIK66T7.js → exit-worktree-Y4ULJ45U.js} +39 -36
- package/chunks/{exitPlanMode-7MBNU76O.js → exitPlanMode-SECI2EQ6.js} +39 -36
- package/chunks/{fast-path-RNLIB64C.js → fast-path-6Z7RW5J5.js} +3 -2
- package/chunks/{fr-X7KDVZIY.js → fr-WVHEBDDB.js} +5 -1
- package/chunks/{gemini-WK5ISEAQ.js → gemini-XLGLUGSU.js} +93 -89
- package/chunks/{geminiContentGenerator-NUJQBZBW.js → geminiContentGenerator-NNZZDH24.js} +5 -5
- package/chunks/{getMachineId-bsd-EXV7SWPA.js → getMachineId-bsd-QFVLPUPT.js} +1 -1
- package/chunks/{getMachineId-darwin-IUOMFXU3.js → getMachineId-darwin-DGMQQE2E.js} +1 -1
- package/chunks/{getMachineId-linux-K7XJYFHL.js → getMachineId-linux-R4Z6CSWC.js} +1 -1
- package/chunks/{getMachineId-unsupported-EA5FDRJ6.js → getMachineId-unsupported-Z3SBVBUV.js} +1 -1
- package/chunks/{getMachineId-win-KBA6RAI5.js → getMachineId-win-SCK5UFDT.js} +1 -1
- package/chunks/{glob-7P6RYY4L.js → glob-KZA64SSV.js} +41 -38
- package/chunks/{grep-V3QHNP2J.js → grep-ONHQMY3V.js} +41 -38
- package/chunks/handleAutoUpdate-PRTJISXQ.js +73 -0
- package/chunks/{i18n-B7IO7WQT.js → i18n-ZTKKG5R5.js} +35 -32
- package/chunks/{initializer-E5TIC3CW.js → initializer-FPPZGBYN.js} +40 -37
- package/chunks/{installationInfo-XLPNAISK.js → installationInfo-DV2C27HT.js} +37 -32
- package/chunks/{ja-2ICT3KXF.js → ja-KY4ROZTE.js} +5 -1
- package/chunks/{keychain-token-storage-DWRJMNH3.js → keychain-token-storage-6ACJDYIB.js} +3 -3
- package/chunks/{list-3CZR5I42.js → list-KEHCNUAK.js} +42 -39
- package/chunks/{loadedSettingsAdapter-X5BSC6CE.js → loadedSettingsAdapter-7RZ6M3WH.js} +39 -36
- package/chunks/{loop-wakeup-HMHCT5GU.js → loop-wakeup-RNMRVA66.js} +6 -6
- package/chunks/{ls-IW5HYDG4.js → ls-J2ZI5XYK.js} +5 -5
- package/chunks/{lsp-4RL52YIZ.js → lsp-UMS3NUB5.js} +3 -3
- package/chunks/managed-npm-update-EBKNOG37.js +332 -0
- package/chunks/{mcp-4C4HWXAR.js → mcp-NHXKZRRP.js} +39 -36
- package/chunks/{monitor-3CJDNZB2.js → monitor-FMUAIFFH.js} +39 -36
- package/chunks/nonInteractiveCli-I2GPZNTP.js +132 -0
- package/chunks/{notebook-edit-MX366HCT.js → notebook-edit-V7RNXKVL.js} +43 -42
- package/chunks/{openaiContentGenerator-KRPNNJGZ.js → openaiContentGenerator-IBVUUZDH.js} +19 -18
- package/chunks/{pidfile-K7T2JLUJ.js → pidfile-AMTGL2H2.js} +35 -32
- package/chunks/{processUtils-YXL3VIBR.js → processUtils-3ZT2JF6D.js} +2 -2
- package/chunks/{pt-JJ4XPIBP.js → pt-OK455PLH.js} +5 -1
- package/chunks/{qwenContentGenerator-GJVXFZ3U.js → qwenContentGenerator-E72VVWS3.js} +41 -38
- package/chunks/{qwenOAuth2-UZTIBQLY.js → qwenOAuth2-YCC3HP24.js} +17 -16
- package/chunks/{read-file-S5XQSYOW.js → read-file-5EWNGUXN.js} +13 -11
- package/chunks/{read-mcp-resource-OIBCNIX7.js → read-mcp-resource-F6HYMDUY.js} +3 -3
- package/chunks/{record-artifact-HDMK4LHG.js → record-artifact-7GCFLDD7.js} +3 -3
- package/chunks/{resumeHistoryUtils-IKR6XD2S.js → resumeHistoryUtils-IH4RNB76.js} +41 -38
- package/chunks/{ripGrep-H65GRSQX.js → ripGrep-B6A6N7GI.js} +34 -31
- package/chunks/{ru-STR4KTW7.js → ru-7SPDGMGD.js} +5 -1
- package/chunks/{run-qwen-serve-7SKAQOAA.js → run-qwen-serve-6PKSMF6Z.js} +115 -74
- package/chunks/{runtime-I2STBGPR.js → runtime-ASRANXO6.js} +45 -40
- package/chunks/{scheduler-6F7HETNO.js → scheduler-IABM76UZ.js} +34 -31
- package/chunks/sdk-exporters-grpc-ETLH47EP.js +23214 -0
- package/chunks/sdk-exporters-http-6MCQH335.js +563 -0
- package/chunks/sdk-impl-HOLWAXC6.js +9193 -0
- package/chunks/{send-message-WXVVK4DB.js → send-message-KBO6X4ZS.js} +7 -5
- package/chunks/{serve-4ATEWSEA.js → serve-A4DT5D32.js} +39 -36
- package/chunks/{server-YPUPFV2O.js → server-DZ5ZSVRE.js} +2317 -472
- package/chunks/{session-AZFIERIY.js → session-G2R3CYU6.js} +87 -172
- package/chunks/{settings-EFQHLTM3.js → settings-7TNSXUTO.js} +43 -40
- package/chunks/{shell-FWXWBJ4Q.js → shell-5BRFGEMK.js} +34 -31
- package/chunks/{skill-A634MNCD.js → skill-3SWYEK7M.js} +24 -20
- package/chunks/{spawnChannel-KKBGGR47.js → spawnChannel-GGN2WVWW.js} +36 -33
- package/chunks/{src-BVROLD6N.js → src-5BPBNQ5S.js} +314 -236
- package/chunks/{standalone-update-ERLA3BDC.js → standalone-update-AHOZ56LS.js} +37 -34
- package/chunks/{startInteractiveUI-3VZ23WAY.js → startInteractiveUI-TLGOQVV7.js} +1105 -906
- package/chunks/{syntheticOutput-HCUFXSIA.js → syntheticOutput-H7RTI5KL.js} +4 -4
- package/chunks/{task-create-RIY5JTFC.js → task-create-7474AJJD.js} +10 -8
- package/chunks/{task-list-XBUCV3CO.js → task-list-633HGOIB.js} +6 -6
- package/chunks/{task-stop-QDFCCYR5.js → task-stop-MNUGHPIA.js} +3 -3
- package/chunks/{task-update-7PXKJQOI.js → task-update-66GQB5LI.js} +10 -8
- package/chunks/{team-create-ZZO7QFQ7.js → team-create-XHDF7UKM.js} +42 -39
- package/chunks/{team-delete-TNSSE2S5.js → team-delete-BB3CG3QF.js} +6 -6
- package/chunks/{team-plan-approval-3BZBJ46K.js → team-plan-approval-XKSBXWMH.js} +39 -36
- package/chunks/{theme-manager-FSFWNXFJ.js → theme-manager-6ZKLBFAN.js} +35 -32
- package/chunks/{todoWrite-OMAIGB6V.js → todoWrite-KRAUN54W.js} +5 -5
- package/chunks/{tool-search-VYXAAIDW.js → tool-search-UDNJCXYS.js} +21 -17
- package/chunks/{total-session-admission-PSMLQICS.js → total-session-admission-VWRCCDYM.js} +40 -37
- package/chunks/{tree-sitter-4D7QS7F6.js → tree-sitter-L5BFT64K.js} +1 -1
- package/chunks/{tree-sitter-bash-VEJGF5XF.js → tree-sitter-bash-ZKDNQGID.js} +1 -1
- package/chunks/{trustedFolders-QA3RK2NV.js → trustedFolders-TJI6OLAN.js} +35 -32
- package/chunks/{chunk-6EFTQYW7.js → undici-3FJYTMOF.js} +24 -399
- package/chunks/{chunk-L573Z2QZ.js → undici-PYHBDDPN.js} +1 -5
- package/chunks/{update-relaunch-LNLZFX3J.js → update-relaunch-RS5GB74A.js} +17 -17
- package/chunks/updateCheck-T4EEA5YR.js +88 -0
- package/chunks/{useAutoAcceptIndicator-DIWN27LT.js → useAutoAcceptIndicator-LLWMXC7F.js} +44 -41
- package/chunks/{validateNonInterActiveAuth-LOEOFCAF.js → validateNonInterActiveAuth-OJ3KYXAR.js} +74 -71
- package/chunks/{version-HBF2VBLE.js → version-ZCEUV5DO.js} +1 -1
- package/chunks/{web-fetch-BWGSD2BD.js → web-fetch-KQF4YFCI.js} +99 -42
- package/chunks/{web-search-OOHTCVR3.js → web-search-QDDGFGKI.js} +113 -61
- package/chunks/{workflow-LJAJBOR4.js → workflow-GIRKCX4P.js} +47 -43
- package/chunks/{workspace-providers-status-FYV7TTHA.js → workspace-providers-status-UTMAVTNE.js} +42 -39
- package/chunks/{workspace-registration-store-4EHGQW4Y.js → workspace-registration-store-EYJMJFZU.js} +8 -2
- package/chunks/{workspace-registry-BKD7VC4Y.js → workspace-registry-4W4UW6MY.js} +40 -37
- package/chunks/{workspace-service-75RHX6KR.js → workspace-service-DJCPY6ZN.js} +46 -43
- package/chunks/{workspace-skills-status-WBZBZI6A.js → workspace-skills-status-VQ2LKXXX.js} +40 -37
- package/chunks/write-file-PLK6RQ7M.js +65 -0
- package/chunks/{zh-TW-4RR3YHNN.js → zh-TW-BM47YBFH.js} +5 -1
- package/chunks/{zh-6ANG2HTL.js → zh-WY5DWYZD.js} +5 -1
- package/cli-entry.js +164 -12
- package/cli.js +18 -11
- package/locales/ca.js +772 -203
- package/locales/de.js +8 -2
- package/locales/en.js +8 -2
- package/locales/fr.js +8 -2
- package/locales/ja.js +8 -2
- package/locales/pt.js +8 -2
- package/locales/ru.js +8 -2
- package/locales/zh-TW.js +8 -2
- package/locales/zh.js +8 -2
- package/package.json +3 -3
- package/web-shell/assets/{arc-Buk1besA.js → arc-DIQrcXXh.js} +1 -1
- package/web-shell/assets/{architectureDiagram-3BPJPVTR-B1aUKYDC.js → architectureDiagram-3BPJPVTR-CbPd-DSw.js} +1 -1
- package/web-shell/assets/{blockDiagram-GPEHLZMM-CRTdg3Zx.js → blockDiagram-GPEHLZMM-yzBIVhMX.js} +1 -1
- package/web-shell/assets/{c4Diagram-AAUBKEIU-DFdRMp5g.js → c4Diagram-AAUBKEIU-B88Swcsu.js} +1 -1
- package/web-shell/assets/channel-BaTMUesZ.js +1 -0
- package/web-shell/assets/{chunk-2J33WTMH-4rYQdkEI.js → chunk-2J33WTMH-BbOLo6NX.js} +1 -1
- package/web-shell/assets/{chunk-4BX2VUAB-Coi-pQJy.js → chunk-4BX2VUAB-Bg6in0r0.js} +1 -1
- package/web-shell/assets/{chunk-55IACEB6-BtBjz02t.js → chunk-55IACEB6-Bv9QRyLI.js} +1 -1
- package/web-shell/assets/{chunk-727SXJPM-CGYOWorl.js → chunk-727SXJPM-CFokiv61.js} +1 -1
- package/web-shell/assets/{chunk-AQP2D5EJ-CH5AKhqx.js → chunk-AQP2D5EJ-DS2Oxf6L.js} +1 -1
- package/web-shell/assets/{chunk-FMBD7UC4-Cd50-w85.js → chunk-FMBD7UC4-D2NkHD3B.js} +1 -1
- package/web-shell/assets/{chunk-ND2GUHAM-C2wF3KCK.js → chunk-ND2GUHAM-BsT_UC5B.js} +1 -1
- package/web-shell/assets/{chunk-QZHKN3VN-pCeRTaWi.js → chunk-QZHKN3VN-tnJo3zln.js} +1 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-CyBPzWud.js +1 -0
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-CyBPzWud.js +1 -0
- package/web-shell/assets/{cose-bilkent-S5V4N54A-B-_fAB6D.js → cose-bilkent-S5V4N54A-BTMa6DAZ.js} +1 -1
- package/web-shell/assets/{dagre-BM42HDAG-ChSPNHpL.js → dagre-BM42HDAG-ujGX7Owg.js} +1 -1
- package/web-shell/assets/{diagram-2AECGRRQ-BX7cFOF3.js → diagram-2AECGRRQ-fU4-dbPa.js} +1 -1
- package/web-shell/assets/{diagram-5GNKFQAL-BQUTW92n.js → diagram-5GNKFQAL-Bdm-TYSA.js} +1 -1
- package/web-shell/assets/{diagram-KO2AKTUF-BkYPh3e4.js → diagram-KO2AKTUF-Bkhz85Z9.js} +1 -1
- package/web-shell/assets/{diagram-LMA3HP47-Cl6jsNyx.js → diagram-LMA3HP47-Bzu3q26p.js} +1 -1
- package/web-shell/assets/{diagram-OG6HWLK6-DRWoHz8n.js → diagram-OG6HWLK6-CZrXbG5Q.js} +1 -1
- package/web-shell/assets/{erDiagram-TEJ5UH35-CGvFcZco.js → erDiagram-TEJ5UH35-BjozEAYu.js} +1 -1
- package/web-shell/assets/{flowDiagram-I6XJVG4X-vms6oVdv.js → flowDiagram-I6XJVG4X-B3a2I8c-.js} +1 -1
- package/web-shell/assets/{ganttDiagram-6RSMTGT7-ukT_sfmi.js → ganttDiagram-6RSMTGT7-CIMn9fNm.js} +1 -1
- package/web-shell/assets/{gitGraphDiagram-PVQCEYII-Bn2ZE2Ut.js → gitGraphDiagram-PVQCEYII-DlFy9KRx.js} +1 -1
- package/web-shell/assets/{index-wFXp7W68.js → index-BODUAzQA.js} +1 -1
- package/web-shell/assets/index-C54DNMF7.js +1209 -0
- package/web-shell/assets/index-lWqBfc78.css +5 -0
- package/web-shell/assets/{infoDiagram-5YYISTIA-DHJdSi7x.js → infoDiagram-5YYISTIA-BmKjQgCy.js} +1 -1
- package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-DOvd2Wph.js → ishikawaDiagram-YF4QCWOH-BrQEMZz2.js} +1 -1
- package/web-shell/assets/{journeyDiagram-JHISSGLW-CH_urMCT.js → journeyDiagram-JHISSGLW-D-2r7Xrt.js} +1 -1
- package/web-shell/assets/{kanban-definition-UN3LZRKU-FKiBdgbH.js → kanban-definition-UN3LZRKU-CndsFHCX.js} +1 -1
- package/web-shell/assets/{linear-0ZVQFVKf.js → linear-D-IwNnKx.js} +1 -1
- package/web-shell/assets/{mermaid.core-DJ05ZZIK.js → mermaid.core-4ll09sri.js} +5 -5
- package/web-shell/assets/{mindmap-definition-RKZ34NQL-BPuUhkUm.js → mindmap-definition-RKZ34NQL-maMRIxjo.js} +1 -1
- package/web-shell/assets/{pieDiagram-4H26LBE5-yLFKcXyG.js → pieDiagram-4H26LBE5-aunUDhrJ.js} +1 -1
- package/web-shell/assets/{quadrantDiagram-W4KKPZXB-irWqc1pE.js → quadrantDiagram-W4KKPZXB-D3K0P1NZ.js} +1 -1
- package/web-shell/assets/{requirementDiagram-4Y6WPE33-B_4uMoIV.js → requirementDiagram-4Y6WPE33-CX2X9HRc.js} +1 -1
- package/web-shell/assets/{sankeyDiagram-5OEKKPKP-ciA4GPwk.js → sankeyDiagram-5OEKKPKP-CDroWk7l.js} +1 -1
- package/web-shell/assets/{sequenceDiagram-3UESZ5HK-CRdZvy0U.js → sequenceDiagram-3UESZ5HK-DTk-2b16.js} +1 -1
- package/web-shell/assets/{stateDiagram-AJRCARHV-DaYIkCCn.js → stateDiagram-AJRCARHV-Cud64hQr.js} +1 -1
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-g-uUpecT.js +1 -0
- package/web-shell/assets/{timeline-definition-PNZ67QCA-oBUKv6iH.js → timeline-definition-PNZ67QCA-DfD5okf_.js} +1 -1
- package/web-shell/assets/{vennDiagram-CIIHVFJN-CGW9Sdmb.js → vennDiagram-CIIHVFJN-BYl8ay25.js} +1 -1
- package/web-shell/assets/{wardley-L42UT6IY-CvwKJOCm.js → wardley-L42UT6IY-BZFAt10J.js} +1 -1
- package/web-shell/assets/{wardleyDiagram-YWT4CUSO-Ipc260sN.js → wardleyDiagram-YWT4CUSO-BIWn0GA7.js} +1 -1
- package/web-shell/assets/{xychartDiagram-2RQKCTM6-D6-CM7pK.js → xychartDiagram-2RQKCTM6-1_H4xblT.js} +1 -1
- package/web-shell/index.html +2 -2
- package/chunks/chunk-ETD6K42I.js +0 -358
- package/chunks/chunk-I5NLVPZJ.js +0 -45
- package/chunks/chunk-ONWW74X6.js +0 -74639
- package/chunks/chunk-W7FJ3N32.js +0 -49
- package/chunks/daemon-status-provider-LVTVJGAD.js +0 -77
- package/chunks/handleAutoUpdate-AAQ6PL3E.js +0 -70
- package/chunks/nonInteractiveCli-QTEHDDFH.js +0 -129
- package/chunks/updateCheck-JJEUQ54U.js +0 -73
- package/chunks/write-file-M2DTFILF.js +0 -599
- package/web-shell/assets/channel-04R0vLbG.js +0 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-Bw9SOwAV.js +0 -1
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-Bw9SOwAV.js +0 -1
- package/web-shell/assets/index-DgkKrjw3.js +0 -1187
- package/web-shell/assets/index-Rv6mOAN9.css +0 -5
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-DWBoO4UY.js +0 -1
|
@@ -14,15 +14,16 @@ import {
|
|
|
14
14
|
shouldSuppressRememberErrorDetails,
|
|
15
15
|
workspaceMemoryFailureCode,
|
|
16
16
|
workspaceMemoryFailureDiagnostics
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-BK6UOUJ2.js";
|
|
18
18
|
import {
|
|
19
19
|
openQwenAsrRealtimeStream,
|
|
20
20
|
openVoiceStream,
|
|
21
21
|
openVoiceStreamWithRetry
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-ZHERRXZJ.js";
|
|
23
23
|
import {
|
|
24
24
|
SetupGithubError,
|
|
25
25
|
collectSessionData,
|
|
26
|
+
createTranscriptMessageUpdate,
|
|
26
27
|
generateExportFilename,
|
|
27
28
|
normalizeSessionData,
|
|
28
29
|
setupGithub,
|
|
@@ -30,25 +31,21 @@ import {
|
|
|
30
31
|
toJson,
|
|
31
32
|
toJsonl,
|
|
32
33
|
toMarkdown
|
|
33
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-C54UTDOC.js";
|
|
34
35
|
import {
|
|
35
36
|
OBSERVED_CONTACT_MAX_FRESH_WITHIN_SECONDS,
|
|
36
37
|
ObservedChannelContactStore
|
|
37
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-4K7VDKAD.js";
|
|
39
|
+
import "./chunk-V4AKJQ26.js";
|
|
38
40
|
import "./chunk-RS7MT2QG.js";
|
|
39
|
-
import "./chunk-CVDW42JT.js";
|
|
40
41
|
import "./chunk-H2XVO6NE.js";
|
|
41
|
-
import "./chunk-QTERJVPZ.js";
|
|
42
42
|
import "./chunk-QHTIBUWB.js";
|
|
43
|
-
import "./chunk-
|
|
44
|
-
import
|
|
45
|
-
createTotalSessionAdmissionController
|
|
46
|
-
} from "./chunk-R3VWUU2E.js";
|
|
43
|
+
import "./chunk-QTERJVPZ.js";
|
|
44
|
+
import "./chunk-3Z43GZUQ.js";
|
|
47
45
|
import {
|
|
48
46
|
createSingleWorkspaceRegistry,
|
|
49
47
|
createWorkspaceSessionOwnerIndex
|
|
50
|
-
} from "./chunk-
|
|
51
|
-
import "./chunk-GRC5HGPI.js";
|
|
48
|
+
} from "./chunk-UGYMA4EI.js";
|
|
52
49
|
import {
|
|
53
50
|
CAPABILITIES_SCHEMA_VERSION,
|
|
54
51
|
CLIENT_ID_HEADER,
|
|
@@ -73,6 +70,7 @@ import {
|
|
|
73
70
|
createBridgeFileSystemAdapter,
|
|
74
71
|
createBuildWorkspaceCtx,
|
|
75
72
|
createClientMcpServerProvider,
|
|
73
|
+
createManagedScratchDirectory,
|
|
76
74
|
createMutationGate,
|
|
77
75
|
createRateLimiter,
|
|
78
76
|
denyBrowserOriginCors,
|
|
@@ -84,6 +82,7 @@ import {
|
|
|
84
82
|
installAccessLogMiddleware,
|
|
85
83
|
isBrowserAutomationMcpAvailable,
|
|
86
84
|
isDeepHealthQuery,
|
|
85
|
+
isScratchRootCompatible,
|
|
87
86
|
parseAllowOriginPatterns,
|
|
88
87
|
parseAndValidateWorkspaceClientId,
|
|
89
88
|
parseClientIdHeader,
|
|
@@ -104,42 +103,29 @@ import {
|
|
|
104
103
|
setRateLimiter,
|
|
105
104
|
unsafeRevealSecret,
|
|
106
105
|
validateMcpRuntimeServerName
|
|
107
|
-
} from "./chunk-
|
|
106
|
+
} from "./chunk-5G3ZVADU.js";
|
|
108
107
|
import {
|
|
109
108
|
isLoopbackBind
|
|
110
109
|
} from "./chunk-RXFQM6FQ.js";
|
|
111
110
|
import {
|
|
112
111
|
createDaemonStatusProvider
|
|
113
|
-
} from "./chunk-
|
|
112
|
+
} from "./chunk-NAXEEGJU.js";
|
|
114
113
|
import "./chunk-LXXMOYPL.js";
|
|
115
|
-
import "./chunk-
|
|
114
|
+
import "./chunk-HDATOR4J.js";
|
|
116
115
|
import "./chunk-E5Z2AVNV.js";
|
|
117
|
-
import {
|
|
118
|
-
SessionArtifactAuthorizationError,
|
|
119
|
-
SessionArtifactValidationError,
|
|
120
|
-
createAcpSessionBridge,
|
|
121
|
-
parseSessionSource
|
|
122
|
-
} from "./chunk-EVSTCA7S.js";
|
|
123
|
-
import {
|
|
124
|
-
EVENT_SCHEMA_VERSION,
|
|
125
|
-
SubscriberLimitExceededError
|
|
126
|
-
} from "./chunk-6RLROE6G.js";
|
|
127
|
-
import "./chunk-COH43MRJ.js";
|
|
128
|
-
import "./chunk-QR6U5QPP.js";
|
|
129
|
-
import "./chunk-6GUTHAN7.js";
|
|
130
116
|
import {
|
|
131
117
|
createWorkspaceProvidersStatusProvider
|
|
132
|
-
} from "./chunk-
|
|
118
|
+
} from "./chunk-COAARUPK.js";
|
|
133
119
|
import {
|
|
134
120
|
getAuthTypeFromEnv,
|
|
135
121
|
resolveCliGenerationConfig
|
|
136
|
-
} from "./chunk-
|
|
122
|
+
} from "./chunk-M4VFMLQK.js";
|
|
137
123
|
import {
|
|
138
124
|
snapshotProcessEnv
|
|
139
|
-
} from "./chunk-
|
|
125
|
+
} from "./chunk-ZKFJKN23.js";
|
|
140
126
|
import {
|
|
141
127
|
createWorkspaceSkillsStatusProvider
|
|
142
|
-
} from "./chunk-
|
|
128
|
+
} from "./chunk-PRAUGUNM.js";
|
|
143
129
|
import "./chunk-2W3OOD4W.js";
|
|
144
130
|
import {
|
|
145
131
|
EMPTY_WORKSPACE_VOICE_UPDATE_ERROR,
|
|
@@ -154,14 +140,14 @@ import {
|
|
|
154
140
|
validateWorkspaceSkillName,
|
|
155
141
|
validateWorkspaceVoiceState,
|
|
156
142
|
voiceSettingsScopeToWire
|
|
157
|
-
} from "./chunk-
|
|
143
|
+
} from "./chunk-VTXX72XS.js";
|
|
158
144
|
import {
|
|
159
145
|
PermissionRulesValidationError,
|
|
160
146
|
buildPermissionSettings,
|
|
161
147
|
isPermissionRuleType,
|
|
162
148
|
normalizePermissionRules,
|
|
163
149
|
readPermissionRuleSet
|
|
164
|
-
} from "./chunk-
|
|
150
|
+
} from "./chunk-A3TAEAHX.js";
|
|
165
151
|
import {
|
|
166
152
|
assertVoiceBaseUrlNetworkAllowed,
|
|
167
153
|
isStreamingVoiceModel,
|
|
@@ -169,13 +155,36 @@ import {
|
|
|
169
155
|
resolveVoiceTranscriptionConfig,
|
|
170
156
|
sanitizeVoiceErrorMessage,
|
|
171
157
|
transcribeVoiceAudio
|
|
172
|
-
} from "./chunk-
|
|
158
|
+
} from "./chunk-M3EQ3GZC.js";
|
|
173
159
|
import {
|
|
174
160
|
isVoiceEnabled,
|
|
175
161
|
isVoiceMode,
|
|
176
162
|
readVoiceModel
|
|
177
|
-
} from "./chunk-
|
|
178
|
-
import "./chunk-
|
|
163
|
+
} from "./chunk-AVQ6EX4J.js";
|
|
164
|
+
import "./chunk-QLJUC7TG.js";
|
|
165
|
+
import {
|
|
166
|
+
WorkspacePermissionRulesSessionRequiredError,
|
|
167
|
+
WorkspaceSettingsPartialPersistError,
|
|
168
|
+
WorkspaceSkillNotFoundError,
|
|
169
|
+
WorkspaceSkillNotToggleableError
|
|
170
|
+
} from "./chunk-OA4JVLSA.js";
|
|
171
|
+
import {
|
|
172
|
+
createTotalSessionAdmissionController
|
|
173
|
+
} from "./chunk-VYPFXUCB.js";
|
|
174
|
+
import "./chunk-GRC5HGPI.js";
|
|
175
|
+
import {
|
|
176
|
+
SessionArtifactAuthorizationError,
|
|
177
|
+
SessionArtifactValidationError,
|
|
178
|
+
createAcpSessionBridge,
|
|
179
|
+
parseSessionSource
|
|
180
|
+
} from "./chunk-RMY5SX7S.js";
|
|
181
|
+
import {
|
|
182
|
+
EVENT_SCHEMA_VERSION,
|
|
183
|
+
EventBus,
|
|
184
|
+
SubscriberLimitExceededError
|
|
185
|
+
} from "./chunk-6RLROE6G.js";
|
|
186
|
+
import "./chunk-COH43MRJ.js";
|
|
187
|
+
import "./chunk-QR6U5QPP.js";
|
|
179
188
|
import {
|
|
180
189
|
BranchWhilePromptActiveError,
|
|
181
190
|
CancelSentinelCollisionError,
|
|
@@ -189,6 +198,7 @@ import {
|
|
|
189
198
|
McpServerRestartFailedError,
|
|
190
199
|
PermissionForbiddenError,
|
|
191
200
|
PermissionPolicyNotImplementedError,
|
|
201
|
+
PromptDeadlineExceededError,
|
|
192
202
|
PromptQueueFullError,
|
|
193
203
|
RestoreInProgressError,
|
|
194
204
|
SessionArchivedError,
|
|
@@ -207,42 +217,39 @@ import {
|
|
|
207
217
|
WorkspaceInitRaceError,
|
|
208
218
|
WorkspaceInitSymlinkError,
|
|
209
219
|
WorkspaceMismatchError
|
|
210
|
-
} from "./chunk-
|
|
211
|
-
import {
|
|
212
|
-
STATUS_SCHEMA_VERSION,
|
|
213
|
-
createIdleWorkspaceMemoryStatus,
|
|
214
|
-
mapDomainErrorToErrorKind
|
|
215
|
-
} from "./chunk-WXAXH7IJ.js";
|
|
216
|
-
import {
|
|
217
|
-
WorkspacePermissionRulesSessionRequiredError,
|
|
218
|
-
WorkspaceSettingsPartialPersistError,
|
|
219
|
-
WorkspaceSkillNotFoundError,
|
|
220
|
-
WorkspaceSkillNotToggleableError
|
|
221
|
-
} from "./chunk-OA4JVLSA.js";
|
|
220
|
+
} from "./chunk-UH3WSE5L.js";
|
|
222
221
|
import "./chunk-WBL3FJEU.js";
|
|
223
|
-
import "./chunk-T2NCM2ET.js";
|
|
224
222
|
import {
|
|
225
223
|
daemonObservedContactsPath,
|
|
226
224
|
loadChannelsConfig
|
|
227
|
-
} from "./chunk-
|
|
228
|
-
import "./chunk-
|
|
225
|
+
} from "./chunk-Q22WWVR6.js";
|
|
226
|
+
import "./chunk-FQI7LT7T.js";
|
|
229
227
|
import "./chunk-57OAHC2Y.js";
|
|
230
228
|
import {
|
|
231
229
|
parseChannelWebhookConfigLenient
|
|
232
|
-
} from "./chunk-
|
|
233
|
-
import "./chunk-
|
|
230
|
+
} from "./chunk-GHRSKGHF.js";
|
|
231
|
+
import "./chunk-6ZBPS62S.js";
|
|
234
232
|
import "./chunk-V6WHFGST.js";
|
|
233
|
+
import "./chunk-6HOCJNO5.js";
|
|
234
|
+
import {
|
|
235
|
+
STATUS_SCHEMA_VERSION,
|
|
236
|
+
createIdleWorkspaceMemoryStatus,
|
|
237
|
+
mapDomainErrorToErrorKind
|
|
238
|
+
} from "./chunk-ESQHGKPJ.js";
|
|
235
239
|
import {
|
|
236
240
|
MAX_REGISTERED_WORKSPACES,
|
|
241
|
+
WorkspaceDisplayNameValidationError,
|
|
237
242
|
WorkspaceRegistrationStoreCommittedError,
|
|
238
243
|
WorkspaceRegistrationStoreLimitError,
|
|
244
|
+
normalizeWorkspaceDisplayName,
|
|
239
245
|
workspaceRegistrationId
|
|
240
|
-
} from "./chunk-
|
|
246
|
+
} from "./chunk-IFUNDCQ6.js";
|
|
241
247
|
import {
|
|
242
248
|
MAX_WORKSPACE_PATH_LENGTH,
|
|
243
249
|
canonicalizeWorkspace,
|
|
244
|
-
canonicalizeWorkspaces
|
|
245
|
-
|
|
250
|
+
canonicalizeWorkspaces,
|
|
251
|
+
translateAndCheckAbsoluteWorkspacePath
|
|
252
|
+
} from "./chunk-2RFKHEXL.js";
|
|
246
253
|
import {
|
|
247
254
|
MAX_CHANNEL_STARTUP_FAILURES,
|
|
248
255
|
MAX_CHANNEL_STARTUP_FAILURE_CHANNEL_LENGTH,
|
|
@@ -251,7 +258,7 @@ import {
|
|
|
251
258
|
QWEN_SERVER_TOKEN_ENV,
|
|
252
259
|
isChannelWebhookEnqueueError,
|
|
253
260
|
normalizeWorkerDiagnostic
|
|
254
|
-
} from "./chunk-
|
|
261
|
+
} from "./chunk-QKTHJXCS.js";
|
|
255
262
|
import {
|
|
256
263
|
normalizeServeChannelSelection
|
|
257
264
|
} from "./chunk-TJTKSVIV.js";
|
|
@@ -259,9 +266,10 @@ import {
|
|
|
259
266
|
redactLogCredentials
|
|
260
267
|
} from "./chunk-M5GB774H.js";
|
|
261
268
|
import "./chunk-5HBA2Z7V.js";
|
|
269
|
+
import "./chunk-T2NCM2ET.js";
|
|
262
270
|
import {
|
|
263
271
|
sanitizeLogText
|
|
264
|
-
} from "./chunk-
|
|
272
|
+
} from "./chunk-RVLZCXEE.js";
|
|
265
273
|
import "./chunk-UDXSXLER.js";
|
|
266
274
|
import {
|
|
267
275
|
getDialogSettingKeys,
|
|
@@ -272,20 +280,23 @@ import {
|
|
|
272
280
|
getWritableScopes,
|
|
273
281
|
loadSettings,
|
|
274
282
|
validateSettingValue
|
|
275
|
-
} from "./chunk-
|
|
283
|
+
} from "./chunk-GWM4PDYK.js";
|
|
276
284
|
import "./chunk-RKUWKYED.js";
|
|
285
|
+
import {
|
|
286
|
+
SUPPORTED_LANGUAGES,
|
|
287
|
+
detectSystemLanguage,
|
|
288
|
+
resolveLanguageSetting,
|
|
289
|
+
resolveSupportedLanguage
|
|
290
|
+
} from "./chunk-YLSB23Y2.js";
|
|
291
|
+
import "./chunk-YNWJAOPL.js";
|
|
277
292
|
import "./chunk-GOXKNSDZ.js";
|
|
278
293
|
import "./chunk-IDS7MSUP.js";
|
|
279
|
-
import {
|
|
280
|
-
SUPPORTED_LANGUAGES
|
|
281
|
-
} from "./chunk-2DXOIVUI.js";
|
|
282
|
-
import "./chunk-OF2BBLYQ.js";
|
|
283
294
|
import "./chunk-QRUIS3DN.js";
|
|
284
|
-
import "./chunk-
|
|
295
|
+
import "./chunk-ISMD2AB3.js";
|
|
285
296
|
import "./chunk-VJNBRRZG.js";
|
|
286
297
|
import {
|
|
287
298
|
getWorkspaceTrustStatus
|
|
288
|
-
} from "./chunk-
|
|
299
|
+
} from "./chunk-PVT6E3ZI.js";
|
|
289
300
|
import "./chunk-ALGGS7UH.js";
|
|
290
301
|
import {
|
|
291
302
|
isWithinRoot as isWithinRoot2
|
|
@@ -299,15 +310,19 @@ import {
|
|
|
299
310
|
BuiltinAgentRegistry,
|
|
300
311
|
Client,
|
|
301
312
|
ClientMcpRegistrar,
|
|
313
|
+
DEFAULT_LOG_LIMIT,
|
|
302
314
|
ExtensionManager,
|
|
303
315
|
GROUP_COLOR_OPTIONS,
|
|
316
|
+
GitWorktreeService,
|
|
304
317
|
IMAGE_CAPABILITY,
|
|
305
318
|
InvalidSessionTranscriptCursorError,
|
|
319
|
+
MAX_LOG_LIMIT,
|
|
306
320
|
ModelsConfig,
|
|
307
321
|
RUNTIME_MCP_IF_ABSENT_CONFIG_FLAG,
|
|
308
322
|
SESSION_TRANSCRIPT_MAX_INDEX_BYTES,
|
|
309
323
|
SESSION_TRANSCRIPT_MAX_LIMIT,
|
|
310
324
|
SESSION_TRANSCRIPT_MAX_PAGE_BYTES,
|
|
325
|
+
SESSION_WRITER_RPC_CODES,
|
|
311
326
|
SessionOrganizationError,
|
|
312
327
|
SessionOrganizationService,
|
|
313
328
|
SessionService,
|
|
@@ -316,6 +331,7 @@ import {
|
|
|
316
331
|
SessionTranscriptReader,
|
|
317
332
|
SessionTranscriptSnapshotUnavailableError,
|
|
318
333
|
SessionTranscriptTooLargeError,
|
|
334
|
+
SessionWriterError,
|
|
319
335
|
StandardFileSystemService,
|
|
320
336
|
StdioClientTransport,
|
|
321
337
|
StreamableHTTPClientTransport,
|
|
@@ -326,13 +342,18 @@ import {
|
|
|
326
342
|
buildUsageDashboard,
|
|
327
343
|
detectLineEnding,
|
|
328
344
|
encodeTextFileContent,
|
|
345
|
+
fetchGitCommitDetail,
|
|
329
346
|
fetchGitDiff,
|
|
330
347
|
fetchGitDiffHunksForFile,
|
|
348
|
+
fetchGitLog,
|
|
331
349
|
getGitWorkingTreeStatus,
|
|
350
|
+
getSubagentSessionDir,
|
|
332
351
|
glob,
|
|
333
352
|
loadIgnoreRules,
|
|
334
353
|
loadUsageHistoryWithLive,
|
|
335
354
|
parseInstallSource,
|
|
355
|
+
readAgentMeta,
|
|
356
|
+
readWorktreeSession,
|
|
336
357
|
redactUrlCredentials,
|
|
337
358
|
resolveBranchName,
|
|
338
359
|
resolveProviderProtocol,
|
|
@@ -340,16 +361,22 @@ import {
|
|
|
340
361
|
stripAnsiAndControl,
|
|
341
362
|
stripTerminalControlSequences,
|
|
342
363
|
watchRepoBranch,
|
|
343
|
-
writeWorkspaceContextFile
|
|
344
|
-
|
|
345
|
-
|
|
364
|
+
writeWorkspaceContextFile,
|
|
365
|
+
writeWorktreeSession,
|
|
366
|
+
writeWorktreeSessionMarker
|
|
367
|
+
} from "./chunk-BLAEKN6K.js";
|
|
346
368
|
import "./chunk-T4TZQJ7W.js";
|
|
347
369
|
import "./chunk-H6XPXXMH.js";
|
|
348
|
-
import "./chunk-
|
|
370
|
+
import "./chunk-5M6IDOMF.js";
|
|
371
|
+
import "./chunk-T2L47JJK.js";
|
|
372
|
+
import "./chunk-GPSKDNEE.js";
|
|
373
|
+
import "./chunk-X6N25LXS.js";
|
|
374
|
+
import "./chunk-E2UVIFI2.js";
|
|
375
|
+
import "./chunk-L5F3T6TQ.js";
|
|
349
376
|
import {
|
|
350
377
|
MAX_JOBS,
|
|
351
378
|
nextDurableFireMs
|
|
352
|
-
} from "./chunk-
|
|
379
|
+
} from "./chunk-Q2YKNMLS.js";
|
|
353
380
|
import {
|
|
354
381
|
nextFireTime,
|
|
355
382
|
parseCron
|
|
@@ -362,24 +389,22 @@ import {
|
|
|
362
389
|
readCronTasks,
|
|
363
390
|
taskHasLegacyCondition,
|
|
364
391
|
updateCronTasks
|
|
365
|
-
} from "./chunk-
|
|
366
|
-
import "./chunk-FSL5W5TI.js";
|
|
367
|
-
import "./chunk-D2VIDMVM.js";
|
|
368
|
-
import "./chunk-E2UVIFI2.js";
|
|
369
|
-
import "./chunk-WBTZGWQ6.js";
|
|
392
|
+
} from "./chunk-KHOVYUHX.js";
|
|
370
393
|
import "./chunk-SZRN75WQ.js";
|
|
371
|
-
import "./chunk-
|
|
394
|
+
import "./chunk-6PVPNMXU.js";
|
|
372
395
|
import "./chunk-CPBF7KYF.js";
|
|
396
|
+
import "./chunk-NABLFI57.js";
|
|
397
|
+
import "./chunk-QBUDF33N.js";
|
|
398
|
+
import "./chunk-LIZRAKPB.js";
|
|
373
399
|
import {
|
|
374
400
|
APPROVAL_MODES,
|
|
375
401
|
SubagentError,
|
|
376
402
|
SubagentErrorCode
|
|
377
|
-
} from "./chunk-
|
|
403
|
+
} from "./chunk-WHGVTP7Q.js";
|
|
378
404
|
import "./chunk-6AM5D4ME.js";
|
|
379
|
-
import "./chunk-
|
|
380
|
-
import "./chunk-
|
|
381
|
-
import "./chunk-
|
|
382
|
-
import "./chunk-OOCI5VVU.js";
|
|
405
|
+
import "./chunk-JCW2R7WC.js";
|
|
406
|
+
import "./chunk-57FIIFJN.js";
|
|
407
|
+
import "./chunk-HTO4JFDZ.js";
|
|
383
408
|
import {
|
|
384
409
|
QwenOAuth2Client,
|
|
385
410
|
QwenOAuthPollError,
|
|
@@ -388,10 +413,15 @@ import {
|
|
|
388
413
|
isDeviceAuthorizationSuccess,
|
|
389
414
|
isDeviceTokenPending,
|
|
390
415
|
isDeviceTokenSuccess
|
|
391
|
-
} from "./chunk-
|
|
392
|
-
import "./chunk-OKWRU4NO.js";
|
|
393
|
-
import "./chunk-XNP57UDV.js";
|
|
416
|
+
} from "./chunk-2HGTVAOW.js";
|
|
394
417
|
import "./chunk-JESCGQM3.js";
|
|
418
|
+
import "./chunk-RC7A7SSL.js";
|
|
419
|
+
import "./chunk-C3EXYVFX.js";
|
|
420
|
+
import "./chunk-XVNQMZ2I.js";
|
|
421
|
+
import "./chunk-CR3C7WXL.js";
|
|
422
|
+
import "./chunk-FODK6UMO.js";
|
|
423
|
+
import "./chunk-GLNBDYUX.js";
|
|
424
|
+
import "./chunk-DJ2GSRLV.js";
|
|
395
425
|
import {
|
|
396
426
|
addDaemonRequestAttribute,
|
|
397
427
|
decodeBufferWithEncodingInfo,
|
|
@@ -400,43 +430,42 @@ import {
|
|
|
400
430
|
hashDaemonWorkspace,
|
|
401
431
|
isBinaryFile,
|
|
402
432
|
isWithinRoot,
|
|
433
|
+
parseLineTolerant,
|
|
434
|
+
read,
|
|
403
435
|
recordDaemonBridgeError,
|
|
404
436
|
recordDaemonError,
|
|
405
437
|
recordDaemonHttpRequest,
|
|
406
438
|
recordDaemonHttpResponse,
|
|
407
439
|
withDaemonRequestSpan
|
|
408
|
-
} from "./chunk-
|
|
409
|
-
import "./chunk-4WKAA4KS.js";
|
|
410
|
-
import "./chunk-CR3C7WXL.js";
|
|
440
|
+
} from "./chunk-U6TQGUNB.js";
|
|
411
441
|
import "./chunk-VGC4I5JJ.js";
|
|
412
|
-
import "./chunk-
|
|
413
|
-
import "./chunk-
|
|
414
|
-
import "./chunk-BDBMYST4.js";
|
|
415
|
-
import "./chunk-467G3SV5.js";
|
|
416
|
-
import "./chunk-S35ZDXOS.js";
|
|
417
|
-
import "./chunk-XVNQMZ2I.js";
|
|
418
|
-
import "./chunk-FODK6UMO.js";
|
|
419
|
-
import "./chunk-GLNBDYUX.js";
|
|
420
|
-
import "./chunk-DJ2GSRLV.js";
|
|
421
|
-
import "./chunk-6EFTQYW7.js";
|
|
422
|
-
import "./chunk-MAQQGNQ5.js";
|
|
442
|
+
import "./chunk-4K56OJFJ.js";
|
|
443
|
+
import "./chunk-CBOQ3HY7.js";
|
|
423
444
|
import "./chunk-A4UCTEB5.js";
|
|
424
445
|
import "./chunk-XWRJCPHC.js";
|
|
446
|
+
import "./chunk-QNLNLENL.js";
|
|
447
|
+
import "./chunk-6X4GWOPW.js";
|
|
425
448
|
import "./chunk-TYQMGACW.js";
|
|
426
449
|
import {
|
|
427
450
|
import_websocket_server
|
|
428
451
|
} from "./chunk-TYAMGABM.js";
|
|
429
452
|
import "./chunk-FCMNKVXT.js";
|
|
453
|
+
import "./chunk-RCUEYZDE.js";
|
|
454
|
+
import "./chunk-HTR4WV6U.js";
|
|
455
|
+
import "./chunk-BULDBTYC.js";
|
|
456
|
+
import "./chunk-U7ZFW55U.js";
|
|
457
|
+
import "./chunk-NPQDJGKU.js";
|
|
458
|
+
import "./chunk-YM3SZTH4.js";
|
|
430
459
|
import {
|
|
431
460
|
FatalConfigError,
|
|
432
461
|
Storage,
|
|
433
462
|
createDebugLogger,
|
|
434
463
|
runWithoutDebugLogSession
|
|
435
|
-
} from "./chunk-
|
|
464
|
+
} from "./chunk-OQB4EXO4.js";
|
|
436
465
|
import "./chunk-75DOP5OR.js";
|
|
437
466
|
import "./chunk-DMTGGOSA.js";
|
|
438
467
|
import "./chunk-YQ3U5MUC.js";
|
|
439
|
-
import "./chunk-
|
|
468
|
+
import "./chunk-THJNPLI4.js";
|
|
440
469
|
import {
|
|
441
470
|
init_esbuild_shims
|
|
442
471
|
} from "./chunk-5O2XNYP6.js";
|
|
@@ -455,7 +484,6 @@ import { createHash as createHash3, timingSafeEqual } from "node:crypto";
|
|
|
455
484
|
|
|
456
485
|
// packages/cli/src/serve/acp-http/dispatch.ts
|
|
457
486
|
init_esbuild_shims();
|
|
458
|
-
import path9 from "node:path";
|
|
459
487
|
|
|
460
488
|
// packages/cli/src/serve/fs/errors.ts
|
|
461
489
|
init_esbuild_shims();
|
|
@@ -629,9 +657,9 @@ async function findExistingAncestor(absolute) {
|
|
|
629
657
|
let current = absolute;
|
|
630
658
|
const tailParts = [];
|
|
631
659
|
for (let i = 0; i < MAX_ANCESTOR_HOPS; i++) {
|
|
632
|
-
let
|
|
660
|
+
let stat3 = null;
|
|
633
661
|
try {
|
|
634
|
-
|
|
662
|
+
stat3 = await fsp.stat(current);
|
|
635
663
|
} catch (err) {
|
|
636
664
|
const code = err?.code;
|
|
637
665
|
if (code === "ENOENT" || code === "ENOTDIR") {
|
|
@@ -639,8 +667,8 @@ async function findExistingAncestor(absolute) {
|
|
|
639
667
|
throw err;
|
|
640
668
|
}
|
|
641
669
|
}
|
|
642
|
-
if (
|
|
643
|
-
if (tailParts.length > 0 && !
|
|
670
|
+
if (stat3) {
|
|
671
|
+
if (tailParts.length > 0 && !stat3.isDirectory()) {
|
|
644
672
|
throw new FsError(
|
|
645
673
|
"parse_error",
|
|
646
674
|
`path component is not a directory: ${absolute}`,
|
|
@@ -713,7 +741,7 @@ async function resolveWithinWorkspace(input, boundWorkspaces, intent) {
|
|
|
713
741
|
boundCanonicals
|
|
714
742
|
);
|
|
715
743
|
if (boundCanonical !== void 0) {
|
|
716
|
-
const finalPathIsSymlink = await fsp.lstat(absolute).then((
|
|
744
|
+
const finalPathIsSymlink = await fsp.lstat(absolute).then((stat3) => stat3.isSymbolicLink()).catch((lstatErr) => {
|
|
717
745
|
if (lstatErr.code === "ENOENT" || lstatErr.code === "ENOTDIR") {
|
|
718
746
|
return false;
|
|
719
747
|
}
|
|
@@ -1204,8 +1232,8 @@ var WorkspaceFileSystemImpl = class {
|
|
|
1204
1232
|
const toRead = Math.min(maxBytes, available);
|
|
1205
1233
|
buf = Buffer.allocUnsafe(toRead);
|
|
1206
1234
|
if (toRead > 0) {
|
|
1207
|
-
const
|
|
1208
|
-
buf =
|
|
1235
|
+
const read2 = await fh.read(buf, 0, toRead, offset);
|
|
1236
|
+
buf = read2.bytesRead === toRead ? buf : buf.subarray(0, read2.bytesRead);
|
|
1209
1237
|
}
|
|
1210
1238
|
const afterRead = await fh.stat();
|
|
1211
1239
|
assertSameFile(st, afterRead, p, "read");
|
|
@@ -1746,17 +1774,17 @@ var WorkspaceFileSystemImpl = class {
|
|
|
1746
1774
|
* for their `sendFsError` serializer.
|
|
1747
1775
|
*/
|
|
1748
1776
|
recordAndWrap(err, intent, input) {
|
|
1749
|
-
const
|
|
1777
|
+
const fs6 = wrapAsFsError(err);
|
|
1750
1778
|
this.deps.audit.recordDenied(this.deps.ctx, {
|
|
1751
1779
|
intent,
|
|
1752
1780
|
input,
|
|
1753
|
-
errorKind:
|
|
1754
|
-
hint:
|
|
1781
|
+
errorKind: fs6.kind,
|
|
1782
|
+
hint: fs6.hint,
|
|
1755
1783
|
// Quote the underlying OS / FsError message so audit
|
|
1756
1784
|
// consumers debugging a production incident can see the
|
|
1757
1785
|
// actual cause (errno text, byte counts, glob pattern,
|
|
1758
1786
|
// etc.) rather than just `errorKind` + `hint`.
|
|
1759
|
-
message:
|
|
1787
|
+
message: fs6.message,
|
|
1760
1788
|
// For glob denials (parse_error pattern rejection,
|
|
1761
1789
|
// catastrophic walk failures) the input IS the pattern
|
|
1762
1790
|
// already; surfacing it on the dedicated `pattern` field
|
|
@@ -1765,7 +1793,7 @@ var WorkspaceFileSystemImpl = class {
|
|
|
1765
1793
|
// branching on intent.
|
|
1766
1794
|
pattern: intent === "glob" ? input : void 0
|
|
1767
1795
|
});
|
|
1768
|
-
return
|
|
1796
|
+
return fs6;
|
|
1769
1797
|
}
|
|
1770
1798
|
};
|
|
1771
1799
|
var CONTENT_HASH_RE = /^sha256:[0-9a-f]{64}$/;
|
|
@@ -1873,9 +1901,9 @@ async function readStableRegularFileBuffer(p, pre) {
|
|
|
1873
1901
|
const out = Buffer.alloc(opened.size);
|
|
1874
1902
|
let offset = 0;
|
|
1875
1903
|
while (offset < opened.size) {
|
|
1876
|
-
const
|
|
1877
|
-
if (
|
|
1878
|
-
offset +=
|
|
1904
|
+
const read2 = await fh.read(out, offset, opened.size - offset, offset);
|
|
1905
|
+
if (read2.bytesRead === 0) break;
|
|
1906
|
+
offset += read2.bytesRead;
|
|
1879
1907
|
}
|
|
1880
1908
|
const afterRead = await fh.stat();
|
|
1881
1909
|
assertSameFile(opened, afterRead, p, "read");
|
|
@@ -2130,15 +2158,15 @@ async function hashRegularFileAtPath(p, pre) {
|
|
|
2130
2158
|
const buf = Buffer.allocUnsafe(64 * 1024);
|
|
2131
2159
|
let offset = 0;
|
|
2132
2160
|
while (offset < opened.size) {
|
|
2133
|
-
const
|
|
2161
|
+
const read2 = await fh.read(
|
|
2134
2162
|
buf,
|
|
2135
2163
|
0,
|
|
2136
2164
|
Math.min(buf.length, opened.size - offset),
|
|
2137
2165
|
offset
|
|
2138
2166
|
);
|
|
2139
|
-
if (
|
|
2140
|
-
hash.update(buf.subarray(0,
|
|
2141
|
-
offset +=
|
|
2167
|
+
if (read2.bytesRead === 0) break;
|
|
2168
|
+
hash.update(buf.subarray(0, read2.bytesRead));
|
|
2169
|
+
offset += read2.bytesRead;
|
|
2142
2170
|
}
|
|
2143
2171
|
} finally {
|
|
2144
2172
|
await fh.close();
|
|
@@ -2247,7 +2275,7 @@ async function renameWithRetryLocal(src, dest, retries, delayMs) {
|
|
|
2247
2275
|
const retryable = code === "EPERM" || code === "EACCES";
|
|
2248
2276
|
if (!retryable || attempt === retries) throw err;
|
|
2249
2277
|
await new Promise(
|
|
2250
|
-
(
|
|
2278
|
+
(resolve6) => setTimeout(resolve6, delayMs * 2 ** attempt)
|
|
2251
2279
|
);
|
|
2252
2280
|
}
|
|
2253
2281
|
}
|
|
@@ -2502,12 +2530,12 @@ __name(applyReadHeaders, "applyReadHeaders");
|
|
|
2502
2530
|
function sendFsError(res, err, route) {
|
|
2503
2531
|
applyReadHeaders(res);
|
|
2504
2532
|
if (isFsError(err)) {
|
|
2505
|
-
const
|
|
2506
|
-
res.status(
|
|
2507
|
-
errorKind:
|
|
2508
|
-
error:
|
|
2509
|
-
hint:
|
|
2510
|
-
status:
|
|
2533
|
+
const fs6 = err;
|
|
2534
|
+
res.status(fs6.status).json({
|
|
2535
|
+
errorKind: fs6.kind,
|
|
2536
|
+
error: fs6.message,
|
|
2537
|
+
hint: fs6.hint,
|
|
2538
|
+
status: fs6.status
|
|
2511
2539
|
});
|
|
2512
2540
|
return;
|
|
2513
2541
|
}
|
|
@@ -2609,13 +2637,13 @@ async function handleGetFile(req, res, deps) {
|
|
|
2609
2637
|
});
|
|
2610
2638
|
return;
|
|
2611
2639
|
}
|
|
2612
|
-
const
|
|
2640
|
+
const fs6 = factory.forRequest({
|
|
2613
2641
|
originatorClientId: clientId ?? void 0,
|
|
2614
2642
|
route: ROUTE2
|
|
2615
2643
|
});
|
|
2616
2644
|
try {
|
|
2617
|
-
const resolved = await
|
|
2618
|
-
const out = await
|
|
2645
|
+
const resolved = await fs6.resolve(queryPath, "read");
|
|
2646
|
+
const out = await fs6.readText(resolved, { maxBytes, line, limit });
|
|
2619
2647
|
const returnedBytes = Buffer.byteLength(out.content, "utf-8");
|
|
2620
2648
|
applyReadHeaders(res);
|
|
2621
2649
|
res.status(200).json({
|
|
@@ -2669,13 +2697,13 @@ async function handleGetFileBytes(req, res, deps) {
|
|
|
2669
2697
|
});
|
|
2670
2698
|
return;
|
|
2671
2699
|
}
|
|
2672
|
-
const
|
|
2700
|
+
const fs6 = factory.forRequest({
|
|
2673
2701
|
originatorClientId: clientId ?? void 0,
|
|
2674
2702
|
route: ROUTE2
|
|
2675
2703
|
});
|
|
2676
2704
|
try {
|
|
2677
|
-
const resolved = await
|
|
2678
|
-
const out = await
|
|
2705
|
+
const resolved = await fs6.resolve(queryPath, "read");
|
|
2706
|
+
const out = await fs6.readBytesWindow(resolved, {
|
|
2679
2707
|
offset: offset ?? 0,
|
|
2680
2708
|
maxBytes: maxBytes ?? DEFAULT_FILE_BYTES_MAX_BYTES
|
|
2681
2709
|
});
|
|
@@ -2703,13 +2731,13 @@ async function handleGetStat(req, res, deps) {
|
|
|
2703
2731
|
if (clientId === null) return;
|
|
2704
2732
|
const queryPath = requireStringQuery(res, req.query["path"], "path", ROUTE2);
|
|
2705
2733
|
if (queryPath === null) return;
|
|
2706
|
-
const
|
|
2734
|
+
const fs6 = factory.forRequest({
|
|
2707
2735
|
originatorClientId: clientId ?? void 0,
|
|
2708
2736
|
route: ROUTE2
|
|
2709
2737
|
});
|
|
2710
2738
|
try {
|
|
2711
|
-
const resolved = await
|
|
2712
|
-
const st = await
|
|
2739
|
+
const resolved = await fs6.resolve(queryPath, "stat");
|
|
2740
|
+
const st = await fs6.stat(resolved);
|
|
2713
2741
|
applyReadHeaders(res);
|
|
2714
2742
|
res.status(200).json({
|
|
2715
2743
|
kind: "stat",
|
|
@@ -2732,13 +2760,13 @@ async function handleGetList(req, res, deps) {
|
|
|
2732
2760
|
const queryPath = requireStringQuery(res, req.query["path"], "path", ROUTE2);
|
|
2733
2761
|
if (queryPath === null) return;
|
|
2734
2762
|
const includeIgnored = parseBoolFlag(req.query["includeIgnored"]);
|
|
2735
|
-
const
|
|
2763
|
+
const fs6 = factory.forRequest({
|
|
2736
2764
|
originatorClientId: clientId ?? void 0,
|
|
2737
2765
|
route: ROUTE2
|
|
2738
2766
|
});
|
|
2739
2767
|
try {
|
|
2740
|
-
const resolved = await
|
|
2741
|
-
const entries = await
|
|
2768
|
+
const resolved = await fs6.resolve(queryPath, "list");
|
|
2769
|
+
const entries = await fs6.list(resolved, {
|
|
2742
2770
|
includeIgnored,
|
|
2743
2771
|
maxEntries: MAX_LIST_ENTRIES + 1
|
|
2744
2772
|
});
|
|
@@ -2791,15 +2819,15 @@ async function handleGetGlob(req, res, deps) {
|
|
|
2791
2819
|
}
|
|
2792
2820
|
const cwdRaw = req.query["cwd"];
|
|
2793
2821
|
const cwdString = typeof cwdRaw === "string" && cwdRaw.length > 0 ? cwdRaw : void 0;
|
|
2794
|
-
const
|
|
2822
|
+
const fs6 = factory.forRequest({
|
|
2795
2823
|
originatorClientId: clientId ?? void 0,
|
|
2796
2824
|
route: ROUTE2
|
|
2797
2825
|
});
|
|
2798
2826
|
const start = performance.now();
|
|
2799
2827
|
try {
|
|
2800
|
-
const cwdResolved = cwdString ? await
|
|
2828
|
+
const cwdResolved = cwdString ? await fs6.resolve(cwdString, "list") : void 0;
|
|
2801
2829
|
const cap = maxResults ?? DEFAULT_GLOB_MAX_RESULTS;
|
|
2802
|
-
const probe = await
|
|
2830
|
+
const probe = await fs6.glob(pattern, {
|
|
2803
2831
|
cwd: cwdResolved,
|
|
2804
2832
|
includeIgnored,
|
|
2805
2833
|
maxResults: cap + 1
|
|
@@ -2861,7 +2889,7 @@ function registerWorkspaceFileReadRoutes(app, deps) {
|
|
|
2861
2889
|
}
|
|
2862
2890
|
__name(registerWorkspaceFileReadRoutes, "registerWorkspaceFileReadRoutes");
|
|
2863
2891
|
function registerWorkspaceQualifiedFileReadRoutes(app, deps) {
|
|
2864
|
-
const
|
|
2892
|
+
const resolve6 = /* @__PURE__ */ __name((req, res) => {
|
|
2865
2893
|
const runtime = resolveWorkspaceRuntimeFromParam(
|
|
2866
2894
|
deps.workspaceRegistry,
|
|
2867
2895
|
req,
|
|
@@ -2875,23 +2903,23 @@ function registerWorkspaceQualifiedFileReadRoutes(app, deps) {
|
|
|
2875
2903
|
return true;
|
|
2876
2904
|
}, "resolve");
|
|
2877
2905
|
app.get("/workspaces/:workspace/file", (req, res) => {
|
|
2878
|
-
if (!
|
|
2906
|
+
if (!resolve6(req, res)) return;
|
|
2879
2907
|
void handleGetFile(req, res, deps);
|
|
2880
2908
|
});
|
|
2881
2909
|
app.get("/workspaces/:workspace/file/bytes", (req, res) => {
|
|
2882
|
-
if (!
|
|
2910
|
+
if (!resolve6(req, res)) return;
|
|
2883
2911
|
void handleGetFileBytes(req, res, deps);
|
|
2884
2912
|
});
|
|
2885
2913
|
app.get("/workspaces/:workspace/stat", (req, res) => {
|
|
2886
|
-
if (!
|
|
2914
|
+
if (!resolve6(req, res)) return;
|
|
2887
2915
|
void handleGetStat(req, res, deps);
|
|
2888
2916
|
});
|
|
2889
2917
|
app.get("/workspaces/:workspace/list", (req, res) => {
|
|
2890
|
-
if (!
|
|
2918
|
+
if (!resolve6(req, res)) return;
|
|
2891
2919
|
void handleGetList(req, res, deps);
|
|
2892
2920
|
});
|
|
2893
2921
|
app.get("/workspaces/:workspace/glob", (req, res) => {
|
|
2894
|
-
if (!
|
|
2922
|
+
if (!resolve6(req, res)) return;
|
|
2895
2923
|
void handleGetGlob(req, res, deps);
|
|
2896
2924
|
});
|
|
2897
2925
|
}
|
|
@@ -2973,7 +3001,7 @@ function validateClientId(clientId, deps, res) {
|
|
|
2973
3001
|
}
|
|
2974
3002
|
__name(validateClientId, "validateClientId");
|
|
2975
3003
|
function createSetupGithubFileOps(factory, route, originatorClientId) {
|
|
2976
|
-
const
|
|
3004
|
+
const fs6 = factory.forRequest({
|
|
2977
3005
|
route,
|
|
2978
3006
|
...originatorClientId ? { originatorClientId } : {}
|
|
2979
3007
|
});
|
|
@@ -2996,14 +3024,14 @@ function createSetupGithubFileOps(factory, route, originatorClientId) {
|
|
|
2996
3024
|
]);
|
|
2997
3025
|
},
|
|
2998
3026
|
async writeTextFile(_gitRepoRoot, relativePath, content) {
|
|
2999
|
-
const resolved = await
|
|
3000
|
-
const out = await
|
|
3027
|
+
const resolved = await fs6.resolve(relativePath, "write");
|
|
3028
|
+
const out = await fs6.writeTextOverwrite(resolved, content);
|
|
3001
3029
|
return { sizeBytes: out.sizeBytes };
|
|
3002
3030
|
},
|
|
3003
3031
|
async readTextFile(_gitRepoRoot, relativePath) {
|
|
3004
3032
|
try {
|
|
3005
|
-
const resolved = await
|
|
3006
|
-
const out = await
|
|
3033
|
+
const resolved = await fs6.resolve(relativePath, "read");
|
|
3034
|
+
const out = await fs6.readText(resolved);
|
|
3007
3035
|
return out.content;
|
|
3008
3036
|
} catch (error2) {
|
|
3009
3037
|
if (isFsError(error2) && error2.kind === "path_not_found") {
|
|
@@ -3024,15 +3052,15 @@ async function ensureDirectoryWithoutSymlink(root, segments) {
|
|
|
3024
3052
|
checkedSegments.push(segment);
|
|
3025
3053
|
const label = `Workspace path "${checkedSegments.join("/")}"`;
|
|
3026
3054
|
try {
|
|
3027
|
-
const
|
|
3028
|
-
if (
|
|
3055
|
+
const stat3 = await fsp3.lstat(current);
|
|
3056
|
+
if (stat3.isSymbolicLink()) {
|
|
3029
3057
|
throw new SetupGithubError(
|
|
3030
3058
|
"github_setup_invalid_workspace",
|
|
3031
3059
|
`${label} must not be a symlink.`,
|
|
3032
3060
|
400
|
|
3033
3061
|
);
|
|
3034
3062
|
}
|
|
3035
|
-
if (!
|
|
3063
|
+
if (!stat3.isDirectory()) {
|
|
3036
3064
|
throw new SetupGithubError(
|
|
3037
3065
|
"github_setup_invalid_workspace",
|
|
3038
3066
|
`${label} must be a directory.`,
|
|
@@ -3069,15 +3097,15 @@ async function ensureDirectoryWithoutSymlink(root, segments) {
|
|
|
3069
3097
|
}
|
|
3070
3098
|
__name(ensureDirectoryWithoutSymlink, "ensureDirectoryWithoutSymlink");
|
|
3071
3099
|
async function assertDirectoryWithoutSymlink(target, label) {
|
|
3072
|
-
const
|
|
3073
|
-
if (
|
|
3100
|
+
const stat3 = await fsp3.lstat(target);
|
|
3101
|
+
if (stat3.isSymbolicLink()) {
|
|
3074
3102
|
throw new SetupGithubError(
|
|
3075
3103
|
"github_setup_invalid_workspace",
|
|
3076
3104
|
`${label} must not be a symlink.`,
|
|
3077
3105
|
400
|
|
3078
3106
|
);
|
|
3079
3107
|
}
|
|
3080
|
-
if (!
|
|
3108
|
+
if (!stat3.isDirectory()) {
|
|
3081
3109
|
throw new SetupGithubError(
|
|
3082
3110
|
"github_setup_invalid_workspace",
|
|
3083
3111
|
`${label} must be a directory.`,
|
|
@@ -4718,12 +4746,12 @@ async function collectWorkspaceMemoryStatus(boundWorkspace) {
|
|
|
4718
4746
|
for (const filename of filenames) {
|
|
4719
4747
|
const candidate = path8.join(globalDir, filename);
|
|
4720
4748
|
try {
|
|
4721
|
-
const
|
|
4722
|
-
if (
|
|
4749
|
+
const stat3 = await fs.stat(candidate);
|
|
4750
|
+
if (stat3.isFile()) {
|
|
4723
4751
|
files.push({
|
|
4724
4752
|
absolutePath: candidate,
|
|
4725
4753
|
scope: "global",
|
|
4726
|
-
bytes:
|
|
4754
|
+
bytes: stat3.size
|
|
4727
4755
|
});
|
|
4728
4756
|
}
|
|
4729
4757
|
} catch (err) {
|
|
@@ -4767,12 +4795,12 @@ async function walkWorkspaceForMemory(start, filenames, errors) {
|
|
|
4767
4795
|
for (const filename of filenames) {
|
|
4768
4796
|
const candidate = path8.join(start, filename);
|
|
4769
4797
|
try {
|
|
4770
|
-
const
|
|
4771
|
-
if (
|
|
4798
|
+
const stat3 = await fs.stat(candidate);
|
|
4799
|
+
if (stat3.isFile()) {
|
|
4772
4800
|
out.push({
|
|
4773
4801
|
absolutePath: candidate,
|
|
4774
4802
|
scope: "workspace",
|
|
4775
|
-
bytes:
|
|
4803
|
+
bytes: stat3.size
|
|
4776
4804
|
});
|
|
4777
4805
|
}
|
|
4778
4806
|
} catch (err) {
|
|
@@ -6563,6 +6591,43 @@ function errMsg(err) {
|
|
|
6563
6591
|
return err instanceof Error ? err.message : String(err);
|
|
6564
6592
|
}
|
|
6565
6593
|
__name(errMsg, "errMsg");
|
|
6594
|
+
var SESSION_WRITER_RPC_ERRORS = {
|
|
6595
|
+
session_writer_conflict: {
|
|
6596
|
+
code: SESSION_WRITER_RPC_CODES.session_writer_conflict,
|
|
6597
|
+
message: "This session is already open in another Qwen process."
|
|
6598
|
+
},
|
|
6599
|
+
session_writer_lost: {
|
|
6600
|
+
code: SESSION_WRITER_RPC_CODES.session_writer_lost,
|
|
6601
|
+
message: "Write ownership for this session was lost."
|
|
6602
|
+
},
|
|
6603
|
+
session_transcript_changed: {
|
|
6604
|
+
code: SESSION_WRITER_RPC_CODES.session_transcript_changed,
|
|
6605
|
+
message: "The session transcript changed outside its active writer."
|
|
6606
|
+
},
|
|
6607
|
+
session_writer_unavailable: {
|
|
6608
|
+
code: SESSION_WRITER_RPC_CODES.session_writer_unavailable,
|
|
6609
|
+
message: "Session write ownership could not be verified."
|
|
6610
|
+
}
|
|
6611
|
+
};
|
|
6612
|
+
function sessionWriterRpcError(err) {
|
|
6613
|
+
if (!err || typeof err !== "object") return void 0;
|
|
6614
|
+
const candidate = err;
|
|
6615
|
+
const data = isObject(candidate["data"]) ? candidate["data"] : void 0;
|
|
6616
|
+
const errorKind = data?.["errorKind"] ?? candidate["errorKind"];
|
|
6617
|
+
if (typeof errorKind !== "string" || !(errorKind in SESSION_WRITER_RPC_ERRORS)) {
|
|
6618
|
+
return void 0;
|
|
6619
|
+
}
|
|
6620
|
+
const typedKind = errorKind;
|
|
6621
|
+
const expected = SESSION_WRITER_RPC_ERRORS[typedKind];
|
|
6622
|
+
const code = candidate["code"] ?? candidate["rpcCode"];
|
|
6623
|
+
if (code !== expected.code) return void 0;
|
|
6624
|
+
return {
|
|
6625
|
+
code: expected.code,
|
|
6626
|
+
message: expected.message,
|
|
6627
|
+
data: { errorKind: typedKind }
|
|
6628
|
+
};
|
|
6629
|
+
}
|
|
6630
|
+
__name(sessionWriterRpcError, "sessionWriterRpcError");
|
|
6566
6631
|
var debugLogger2 = createDebugLogger("ACP_HTTP_DISPATCH");
|
|
6567
6632
|
var SESSION_SHELL_METHOD = `${QWEN_METHOD_NS}session/shell`;
|
|
6568
6633
|
var INVALID_PERMISSION_OUTCOME_ERROR = '`outcome` must be `{ outcome: "cancelled" }` or `{ outcome: "selected", optionId: string }`';
|
|
@@ -6695,10 +6760,11 @@ function parseOptionalWorkspaceCwd2(params, boundWorkspace) {
|
|
|
6695
6760
|
`\`cwd\` exceeds the ${MAX_WORKSPACE_PATH_LENGTH}-character limit`
|
|
6696
6761
|
);
|
|
6697
6762
|
}
|
|
6698
|
-
|
|
6763
|
+
const sandboxCwd = translateAndCheckAbsoluteWorkspacePath(cwd);
|
|
6764
|
+
if (sandboxCwd === null) {
|
|
6699
6765
|
throw new AcpParamError("`cwd` must be an absolute path when provided");
|
|
6700
6766
|
}
|
|
6701
|
-
return
|
|
6767
|
+
return sandboxCwd;
|
|
6702
6768
|
}
|
|
6703
6769
|
__name(parseOptionalWorkspaceCwd2, "parseOptionalWorkspaceCwd");
|
|
6704
6770
|
function validatePrompt(params) {
|
|
@@ -6775,6 +6841,8 @@ function pickSessionArtifactInput(params) {
|
|
|
6775
6841
|
}
|
|
6776
6842
|
__name(pickSessionArtifactInput, "pickSessionArtifactInput");
|
|
6777
6843
|
function toRpcError(err) {
|
|
6844
|
+
const writerError = sessionWriterRpcError(err);
|
|
6845
|
+
if (writerError) return writerError;
|
|
6778
6846
|
if (err instanceof AcpParamError || err instanceof InvalidCursorError) {
|
|
6779
6847
|
return { code: RPC.INVALID_PARAMS, message: err.message };
|
|
6780
6848
|
}
|
|
@@ -7511,22 +7579,21 @@ var AcpDispatcher = class {
|
|
|
7511
7579
|
conn.ownedSessions.delete(sessionId);
|
|
7512
7580
|
conn.closingSessions.add(sessionId);
|
|
7513
7581
|
let closeStarted = false;
|
|
7514
|
-
const
|
|
7515
|
-
closeStarted = true;
|
|
7582
|
+
const closeLocalSessionStream = /* @__PURE__ */ __name(() => {
|
|
7516
7583
|
try {
|
|
7517
|
-
|
|
7518
|
-
|
|
7519
|
-
|
|
7584
|
+
conn.closeSessionStream(sessionId);
|
|
7585
|
+
} catch (teardownErr) {
|
|
7586
|
+
writeStderrLine(
|
|
7587
|
+
`qwen serve: /acp session/close local teardown failed (${logSafe(sessionId)}): ${logSafe(errMsg(teardownErr))}`
|
|
7520
7588
|
);
|
|
7521
|
-
} finally {
|
|
7522
|
-
try {
|
|
7523
|
-
conn.closeSessionStream(sessionId);
|
|
7524
|
-
} catch (teardownErr) {
|
|
7525
|
-
writeStderrLine(
|
|
7526
|
-
`qwen serve: /acp session/close local teardown failed (${logSafe(sessionId)}): ${logSafe(errMsg(teardownErr))}`
|
|
7527
|
-
);
|
|
7528
|
-
}
|
|
7529
7589
|
}
|
|
7590
|
+
}, "closeLocalSessionStream");
|
|
7591
|
+
const closeSession = /* @__PURE__ */ __name(async () => {
|
|
7592
|
+
closeStarted = true;
|
|
7593
|
+
await this.bridge.closeSession(
|
|
7594
|
+
sessionId,
|
|
7595
|
+
this.sessionCtx(conn, sessionId, loopback)
|
|
7596
|
+
);
|
|
7530
7597
|
}, "closeSession");
|
|
7531
7598
|
try {
|
|
7532
7599
|
try {
|
|
@@ -7548,11 +7615,19 @@ var AcpDispatcher = class {
|
|
|
7548
7615
|
} catch (err) {
|
|
7549
7616
|
if (!closeStarted) {
|
|
7550
7617
|
conn.ownedSessions.add(sessionId);
|
|
7618
|
+
} else {
|
|
7619
|
+
try {
|
|
7620
|
+
this.bridge.getSessionSummary(sessionId);
|
|
7621
|
+
conn.ownedSessions.add(sessionId);
|
|
7622
|
+
} catch {
|
|
7623
|
+
closeLocalSessionStream();
|
|
7624
|
+
}
|
|
7551
7625
|
}
|
|
7552
7626
|
throw err;
|
|
7553
7627
|
} finally {
|
|
7554
7628
|
conn.closingSessions.delete(sessionId);
|
|
7555
7629
|
}
|
|
7630
|
+
closeLocalSessionStream();
|
|
7556
7631
|
this.replyConn(conn, id, {});
|
|
7557
7632
|
return;
|
|
7558
7633
|
}
|
|
@@ -8977,7 +9052,7 @@ var AcpDispatcher = class {
|
|
|
8977
9052
|
);
|
|
8978
9053
|
return;
|
|
8979
9054
|
}
|
|
8980
|
-
const
|
|
9055
|
+
const fs6 = this.fsFactory.forRequest({
|
|
8981
9056
|
originatorClientId: conn.clientId,
|
|
8982
9057
|
route: `ACP ${method}`
|
|
8983
9058
|
});
|
|
@@ -9029,8 +9104,8 @@ var AcpDispatcher = class {
|
|
|
9029
9104
|
);
|
|
9030
9105
|
return;
|
|
9031
9106
|
}
|
|
9032
|
-
const resolved = await
|
|
9033
|
-
const out = await
|
|
9107
|
+
const resolved = await fs6.resolve(p, "read");
|
|
9108
|
+
const out = await fs6.readText(resolved, { maxBytes, line, limit });
|
|
9034
9109
|
this.replyConn(conn, id, {
|
|
9035
9110
|
path: p,
|
|
9036
9111
|
content: out.content,
|
|
@@ -9052,7 +9127,7 @@ var AcpDispatcher = class {
|
|
|
9052
9127
|
conn.sendConn(error(id, RPC.INVALID_PARAMS, "`path` required"));
|
|
9053
9128
|
return;
|
|
9054
9129
|
}
|
|
9055
|
-
const
|
|
9130
|
+
const fs6 = this.fsFactory.forRequest({
|
|
9056
9131
|
originatorClientId: conn.clientId,
|
|
9057
9132
|
route: `ACP ${method}`
|
|
9058
9133
|
});
|
|
@@ -9088,8 +9163,8 @@ var AcpDispatcher = class {
|
|
|
9088
9163
|
);
|
|
9089
9164
|
return;
|
|
9090
9165
|
}
|
|
9091
|
-
const resolved = await
|
|
9092
|
-
const buf = await
|
|
9166
|
+
const resolved = await fs6.resolve(p, "read");
|
|
9167
|
+
const buf = await fs6.readBytesWindow(resolved, { offset, maxBytes });
|
|
9093
9168
|
this.replyConn(conn, id, { path: p, ...buf });
|
|
9094
9169
|
return;
|
|
9095
9170
|
}
|
|
@@ -9107,12 +9182,12 @@ var AcpDispatcher = class {
|
|
|
9107
9182
|
conn.sendConn(error(id, RPC.INVALID_PARAMS, "`path` required"));
|
|
9108
9183
|
return;
|
|
9109
9184
|
}
|
|
9110
|
-
const
|
|
9185
|
+
const fs6 = this.fsFactory.forRequest({
|
|
9111
9186
|
originatorClientId: conn.clientId,
|
|
9112
9187
|
route: `ACP ${method}`
|
|
9113
9188
|
});
|
|
9114
|
-
const resolved = await
|
|
9115
|
-
const result = await
|
|
9189
|
+
const resolved = await fs6.resolve(p, "read");
|
|
9190
|
+
const result = await fs6.stat(resolved);
|
|
9116
9191
|
this.replyConn(conn, id, { path: p, ...result });
|
|
9117
9192
|
return;
|
|
9118
9193
|
}
|
|
@@ -9130,13 +9205,13 @@ var AcpDispatcher = class {
|
|
|
9130
9205
|
conn.sendConn(error(id, RPC.INVALID_PARAMS, "`path` required"));
|
|
9131
9206
|
return;
|
|
9132
9207
|
}
|
|
9133
|
-
const
|
|
9208
|
+
const fs6 = this.fsFactory.forRequest({
|
|
9134
9209
|
originatorClientId: conn.clientId,
|
|
9135
9210
|
route: `ACP ${method}`
|
|
9136
9211
|
});
|
|
9137
|
-
const resolved = await
|
|
9212
|
+
const resolved = await fs6.resolve(p, "read");
|
|
9138
9213
|
const MAX_LIST = 2e3;
|
|
9139
|
-
const entries = await
|
|
9214
|
+
const entries = await fs6.list(resolved, { maxEntries: MAX_LIST + 1 });
|
|
9140
9215
|
const truncated = entries.length > MAX_LIST;
|
|
9141
9216
|
this.replyConn(conn, id, {
|
|
9142
9217
|
path: p,
|
|
@@ -9161,7 +9236,7 @@ var AcpDispatcher = class {
|
|
|
9161
9236
|
);
|
|
9162
9237
|
return;
|
|
9163
9238
|
}
|
|
9164
|
-
const
|
|
9239
|
+
const fs6 = this.fsFactory.forRequest({
|
|
9165
9240
|
originatorClientId: conn.clientId,
|
|
9166
9241
|
route: `ACP ${method}`
|
|
9167
9242
|
});
|
|
@@ -9181,7 +9256,7 @@ var AcpDispatcher = class {
|
|
|
9181
9256
|
);
|
|
9182
9257
|
return;
|
|
9183
9258
|
}
|
|
9184
|
-
const matches = await
|
|
9259
|
+
const matches = await fs6.glob(pattern, {
|
|
9185
9260
|
maxResults: maxResults + 1
|
|
9186
9261
|
});
|
|
9187
9262
|
const truncated = matches.length > maxResults;
|
|
@@ -9213,11 +9288,11 @@ var AcpDispatcher = class {
|
|
|
9213
9288
|
);
|
|
9214
9289
|
return;
|
|
9215
9290
|
}
|
|
9216
|
-
const
|
|
9291
|
+
const fs6 = this.fsFactory.forRequest({
|
|
9217
9292
|
originatorClientId: conn.clientId,
|
|
9218
9293
|
route: `ACP ${method}`
|
|
9219
9294
|
});
|
|
9220
|
-
const resolved = await
|
|
9295
|
+
const resolved = await fs6.resolve(p, "write");
|
|
9221
9296
|
if (Buffer.byteLength(params["content"], "utf8") > 10 * 1024 * 1024) {
|
|
9222
9297
|
if (id !== void 0)
|
|
9223
9298
|
conn.sendConn(
|
|
@@ -9225,7 +9300,7 @@ var AcpDispatcher = class {
|
|
|
9225
9300
|
);
|
|
9226
9301
|
return;
|
|
9227
9302
|
}
|
|
9228
|
-
await
|
|
9303
|
+
await fs6.writeTextOverwrite(resolved, params["content"]);
|
|
9229
9304
|
this.replyConn(conn, id, { ok: true, path: p });
|
|
9230
9305
|
return;
|
|
9231
9306
|
}
|
|
@@ -9254,12 +9329,12 @@ var AcpDispatcher = class {
|
|
|
9254
9329
|
);
|
|
9255
9330
|
return;
|
|
9256
9331
|
}
|
|
9257
|
-
const
|
|
9332
|
+
const fs6 = this.fsFactory.forRequest({
|
|
9258
9333
|
originatorClientId: conn.clientId,
|
|
9259
9334
|
route: `ACP ${method}`
|
|
9260
9335
|
});
|
|
9261
|
-
const resolved = await
|
|
9262
|
-
const result = await
|
|
9336
|
+
const resolved = await fs6.resolve(p, "write");
|
|
9337
|
+
const result = await fs6.edit(
|
|
9263
9338
|
resolved,
|
|
9264
9339
|
params["oldText"],
|
|
9265
9340
|
params["newText"]
|
|
@@ -10802,9 +10877,9 @@ var SseStream = class {
|
|
|
10802
10877
|
return next;
|
|
10803
10878
|
}
|
|
10804
10879
|
doWrite(chunk) {
|
|
10805
|
-
return new Promise((
|
|
10880
|
+
return new Promise((resolve6, reject) => {
|
|
10806
10881
|
if (this.closed || this.res.writableEnded) {
|
|
10807
|
-
|
|
10882
|
+
resolve6();
|
|
10808
10883
|
return;
|
|
10809
10884
|
}
|
|
10810
10885
|
let ok;
|
|
@@ -10815,7 +10890,7 @@ var SseStream = class {
|
|
|
10815
10890
|
return;
|
|
10816
10891
|
}
|
|
10817
10892
|
if (ok) {
|
|
10818
|
-
|
|
10893
|
+
resolve6();
|
|
10819
10894
|
return;
|
|
10820
10895
|
}
|
|
10821
10896
|
const cleanup = /* @__PURE__ */ __name(() => {
|
|
@@ -10825,11 +10900,11 @@ var SseStream = class {
|
|
|
10825
10900
|
}, "cleanup");
|
|
10826
10901
|
const onDrain = /* @__PURE__ */ __name(() => {
|
|
10827
10902
|
cleanup();
|
|
10828
|
-
|
|
10903
|
+
resolve6();
|
|
10829
10904
|
}, "onDrain");
|
|
10830
10905
|
const onCloseEv = /* @__PURE__ */ __name(() => {
|
|
10831
10906
|
cleanup();
|
|
10832
|
-
|
|
10907
|
+
resolve6();
|
|
10833
10908
|
}, "onCloseEv");
|
|
10834
10909
|
const onErrorEv = /* @__PURE__ */ __name((err) => {
|
|
10835
10910
|
cleanup();
|
|
@@ -10891,14 +10966,14 @@ var WsStream = class {
|
|
|
10891
10966
|
send(message, _id) {
|
|
10892
10967
|
const data = JSON.stringify(message);
|
|
10893
10968
|
const next = this.writeChain.then(
|
|
10894
|
-
() => new Promise((
|
|
10969
|
+
() => new Promise((resolve6, reject) => {
|
|
10895
10970
|
if (this._closed) {
|
|
10896
|
-
|
|
10971
|
+
resolve6();
|
|
10897
10972
|
return;
|
|
10898
10973
|
}
|
|
10899
10974
|
this.ws.send(data, (err) => {
|
|
10900
10975
|
if (err) reject(err);
|
|
10901
|
-
else
|
|
10976
|
+
else resolve6();
|
|
10902
10977
|
});
|
|
10903
10978
|
})
|
|
10904
10979
|
);
|
|
@@ -11203,7 +11278,7 @@ var CdpReverseLink = class {
|
|
|
11203
11278
|
throw { code: -32e3, message: "CDP tunnel closed" };
|
|
11204
11279
|
}
|
|
11205
11280
|
await this.attach();
|
|
11206
|
-
return new Promise((
|
|
11281
|
+
return new Promise((resolve6, reject) => {
|
|
11207
11282
|
if (this.disposed) {
|
|
11208
11283
|
reject({ code: -32e3, message: "CDP tunnel closed" });
|
|
11209
11284
|
return;
|
|
@@ -11214,7 +11289,7 @@ var CdpReverseLink = class {
|
|
|
11214
11289
|
`CDP command id=${id} method=${method} timed out after ${this.commandTimeoutMs}ms`
|
|
11215
11290
|
);
|
|
11216
11291
|
const progressTimer = this.armProgressLog(id, method);
|
|
11217
|
-
this.pending.set(id, { resolve:
|
|
11292
|
+
this.pending.set(id, { resolve: resolve6, reject, timer, progressTimer });
|
|
11218
11293
|
try {
|
|
11219
11294
|
this.log?.(
|
|
11220
11295
|
`qwen serve: /cdp forwarded command id=${id} method=${method} to extension`
|
|
@@ -11241,7 +11316,7 @@ var CdpReverseLink = class {
|
|
|
11241
11316
|
if (this.attached) return Promise.resolve({});
|
|
11242
11317
|
if (this.attachPromise) return this.attachPromise;
|
|
11243
11318
|
this.attachPromise = new Promise(
|
|
11244
|
-
(
|
|
11319
|
+
(resolve6, reject) => {
|
|
11245
11320
|
if (this.disposed) {
|
|
11246
11321
|
reject({ code: -32e3, message: "CDP tunnel closed" });
|
|
11247
11322
|
return;
|
|
@@ -11251,7 +11326,7 @@ var CdpReverseLink = class {
|
|
|
11251
11326
|
this.pendingAttach = {
|
|
11252
11327
|
id,
|
|
11253
11328
|
pending: {
|
|
11254
|
-
resolve: /* @__PURE__ */ __name((result) =>
|
|
11329
|
+
resolve: /* @__PURE__ */ __name((result) => resolve6(result ?? {}), "resolve"),
|
|
11255
11330
|
reject,
|
|
11256
11331
|
timer
|
|
11257
11332
|
}
|
|
@@ -11819,7 +11894,7 @@ function isAcpChannelUnavailable(err) {
|
|
|
11819
11894
|
}
|
|
11820
11895
|
__name(isAcpChannelUnavailable, "isAcpChannelUnavailable");
|
|
11821
11896
|
function delay(ms) {
|
|
11822
|
-
return new Promise((
|
|
11897
|
+
return new Promise((resolve6) => setTimeout(resolve6, ms));
|
|
11823
11898
|
}
|
|
11824
11899
|
__name(delay, "delay");
|
|
11825
11900
|
function buildChromeDevToolsMcpRuntimeConfig(localPort, hostname, env) {
|
|
@@ -13700,7 +13775,7 @@ var CdpTunnelRegistry = class {
|
|
|
13700
13775
|
// packages/cli/src/serve/web-shell-static.ts
|
|
13701
13776
|
init_esbuild_shims();
|
|
13702
13777
|
var import_express2 = __toESM(require_express(), 1);
|
|
13703
|
-
import * as
|
|
13778
|
+
import * as path9 from "node:path";
|
|
13704
13779
|
var WEB_SHELL_CSP_DIRECTIVES = [
|
|
13705
13780
|
"default-src 'self'",
|
|
13706
13781
|
"script-src 'self' 'unsafe-inline' 'unsafe-eval' 'wasm-unsafe-eval'",
|
|
@@ -13728,7 +13803,7 @@ function isDocumentNavigation(req) {
|
|
|
13728
13803
|
}
|
|
13729
13804
|
__name(isDocumentNavigation, "isDocumentNavigation");
|
|
13730
13805
|
function createSendIndex(webShellDir, frameAncestors = []) {
|
|
13731
|
-
const indexPath =
|
|
13806
|
+
const indexPath = path9.join(webShellDir, "index.html");
|
|
13732
13807
|
const csp = buildWebShellCsp(frameAncestors);
|
|
13733
13808
|
return (res) => {
|
|
13734
13809
|
res.status(200).set("Content-Security-Policy", csp).set("X-Content-Type-Options", "nosniff").set("Referrer-Policy", "no-referrer").set(
|
|
@@ -13764,7 +13839,7 @@ function mountWebShellAssets(app, webShellDir, frameAncestors = []) {
|
|
|
13764
13839
|
const sendIndex = createSendIndex(webShellDir, frameAncestors);
|
|
13765
13840
|
app.use(
|
|
13766
13841
|
"/assets",
|
|
13767
|
-
import_express2.default.static(
|
|
13842
|
+
import_express2.default.static(path9.join(webShellDir, "assets"), {
|
|
13768
13843
|
index: false,
|
|
13769
13844
|
immutable: true,
|
|
13770
13845
|
maxAge: "1y"
|
|
@@ -15109,7 +15184,7 @@ function createFifoTaskQueue(limit) {
|
|
|
15109
15184
|
Promise.resolve().then(() => item.task(release)).then(item.resolve, item.reject).finally(release);
|
|
15110
15185
|
}
|
|
15111
15186
|
}, "pump");
|
|
15112
|
-
const enqueue = /* @__PURE__ */ __name((task, options = {}) => new Promise((
|
|
15187
|
+
const enqueue = /* @__PURE__ */ __name((task, options = {}) => new Promise((resolve6, reject) => {
|
|
15113
15188
|
if (options.signal?.aborted) {
|
|
15114
15189
|
reject(abortReason(options.signal));
|
|
15115
15190
|
return;
|
|
@@ -15118,7 +15193,7 @@ function createFifoTaskQueue(limit) {
|
|
|
15118
15193
|
task,
|
|
15119
15194
|
...options.signal ? { signal: options.signal } : {},
|
|
15120
15195
|
...options.onStart ? { onStart: options.onStart } : {},
|
|
15121
|
-
resolve:
|
|
15196
|
+
resolve: resolve6,
|
|
15122
15197
|
reject
|
|
15123
15198
|
};
|
|
15124
15199
|
if (options.signal) {
|
|
@@ -15160,6 +15235,14 @@ var redactExtensionDisplaySource = /* @__PURE__ */ __name((source) => {
|
|
|
15160
15235
|
var EXTENSION_PREPARATION_CONCURRENCY = 2;
|
|
15161
15236
|
var EXTENSION_REFRESH_TIMEOUT_MS = 3e4;
|
|
15162
15237
|
var RECONCILE_SLOW_MS = 3e4;
|
|
15238
|
+
var resolveExtensionLocale = /* @__PURE__ */ __name((workspaceDir) => {
|
|
15239
|
+
const configuredLanguage = loadSettings(workspaceDir).merged.general?.language;
|
|
15240
|
+
const requestedLocale = resolveLanguageSetting(configuredLanguage);
|
|
15241
|
+
if (requestedLocale === "auto") {
|
|
15242
|
+
return detectSystemLanguage();
|
|
15243
|
+
}
|
|
15244
|
+
return resolveSupportedLanguage(requestedLocale) ?? requestedLocale;
|
|
15245
|
+
}, "resolveExtensionLocale");
|
|
15163
15246
|
var EXTENSION_QUEUE_FULL_MESSAGE = "Extension operation queue is full";
|
|
15164
15247
|
function createExtensionsController(deps) {
|
|
15165
15248
|
const { boundWorkspace, bridge, workspace } = deps;
|
|
@@ -15187,6 +15270,7 @@ function createExtensionsController(deps) {
|
|
|
15187
15270
|
}, "acquireOperationSlot");
|
|
15188
15271
|
const createExtensionManager = /* @__PURE__ */ __name((workspaceDir = boundWorkspace, trustedOverride, interactions) => new ExtensionManager({
|
|
15189
15272
|
workspaceDir,
|
|
15273
|
+
locale: resolveExtensionLocale(workspaceDir),
|
|
15190
15274
|
isWorkspaceTrusted: trustedOverride ?? getWorkspaceTrustStatus(loadSettings(workspaceDir).merged, workspaceDir).effective.state === "trusted",
|
|
15191
15275
|
requestConsent: /* @__PURE__ */ __name(() => Promise.resolve(), "requestConsent"),
|
|
15192
15276
|
networkPolicy: "public",
|
|
@@ -15714,8 +15798,9 @@ function createExtensionsController(deps) {
|
|
|
15714
15798
|
})();
|
|
15715
15799
|
}, "runQueuedExtensionMutation");
|
|
15716
15800
|
const buildLocalExtensionsStatus = /* @__PURE__ */ __name(async () => {
|
|
15801
|
+
const locale = resolveExtensionLocale(boundWorkspace);
|
|
15717
15802
|
const now = Date.now();
|
|
15718
|
-
if (extensionsStatusCache && extensionsStatusCache.expiresAt > now) {
|
|
15803
|
+
if (extensionsStatusCache?.locale === locale && extensionsStatusCache.expiresAt > now) {
|
|
15719
15804
|
return extensionsStatusCache.value;
|
|
15720
15805
|
}
|
|
15721
15806
|
const extensionManager = createExtensionManager();
|
|
@@ -15771,6 +15856,7 @@ function createExtensionsController(deps) {
|
|
|
15771
15856
|
extensions: entries
|
|
15772
15857
|
};
|
|
15773
15858
|
extensionsStatusCache = {
|
|
15859
|
+
locale,
|
|
15774
15860
|
expiresAt: Date.now() + 2e3,
|
|
15775
15861
|
value: status
|
|
15776
15862
|
};
|
|
@@ -15939,7 +16025,7 @@ function registerWorkspaceExtensionRoutes(app, deps) {
|
|
|
15939
16025
|
...interaction,
|
|
15940
16026
|
id: crypto2.randomUUID()
|
|
15941
16027
|
};
|
|
15942
|
-
return new Promise((
|
|
16028
|
+
return new Promise((resolve6, reject) => {
|
|
15943
16029
|
const timeout = setTimeout(() => {
|
|
15944
16030
|
pendingExtensionInteractions.delete(operationId);
|
|
15945
16031
|
controller.updateOperation(operationId, {
|
|
@@ -15953,7 +16039,7 @@ function registerWorkspaceExtensionRoutes(app, deps) {
|
|
|
15953
16039
|
timeout.unref?.();
|
|
15954
16040
|
pendingExtensionInteractions.set(operationId, {
|
|
15955
16041
|
interaction: pendingInteraction,
|
|
15956
|
-
resolve:
|
|
16042
|
+
resolve: resolve6,
|
|
15957
16043
|
reject,
|
|
15958
16044
|
timeout
|
|
15959
16045
|
});
|
|
@@ -15998,8 +16084,8 @@ function registerWorkspaceExtensionRoutes(app, deps) {
|
|
|
15998
16084
|
const reserveRuntimeReconciliation = /* @__PURE__ */ __name(() => {
|
|
15999
16085
|
let provideTask;
|
|
16000
16086
|
const task = new Promise(
|
|
16001
|
-
(
|
|
16002
|
-
provideTask =
|
|
16087
|
+
(resolve6) => {
|
|
16088
|
+
provideTask = resolve6;
|
|
16003
16089
|
}
|
|
16004
16090
|
);
|
|
16005
16091
|
const queued = runtimeReconciliationQueue.run(async () => {
|
|
@@ -16100,9 +16186,9 @@ function registerWorkspaceExtensionRoutes(app, deps) {
|
|
|
16100
16186
|
generationPoller.unref();
|
|
16101
16187
|
app.locals.stopExtensionGenerationReconciler = () => clearInterval(generationPoller);
|
|
16102
16188
|
}
|
|
16103
|
-
const registerFor = /* @__PURE__ */ __name((base,
|
|
16189
|
+
const registerFor = /* @__PURE__ */ __name((base, resolve6) => {
|
|
16104
16190
|
app.get(base, async (req, res) => {
|
|
16105
|
-
const ctrl =
|
|
16191
|
+
const ctrl = resolve6(req, res, false);
|
|
16106
16192
|
if (!ctrl) return;
|
|
16107
16193
|
try {
|
|
16108
16194
|
res.status(200).json(await ctrl.buildLocalExtensionsStatus());
|
|
@@ -16111,12 +16197,12 @@ function registerWorkspaceExtensionRoutes(app, deps) {
|
|
|
16111
16197
|
}
|
|
16112
16198
|
});
|
|
16113
16199
|
app.get(`${base}/operations`, async (req, res) => {
|
|
16114
|
-
const ctrl =
|
|
16200
|
+
const ctrl = resolve6(req, res, false);
|
|
16115
16201
|
if (!ctrl) return;
|
|
16116
16202
|
res.status(200).json({ v: 1, operations: ctrl.getActiveOperations() });
|
|
16117
16203
|
});
|
|
16118
16204
|
app.get(`${base}/operations/:operationId`, async (req, res) => {
|
|
16119
|
-
const ctrl =
|
|
16205
|
+
const ctrl = resolve6(req, res, false);
|
|
16120
16206
|
if (!ctrl) return;
|
|
16121
16207
|
try {
|
|
16122
16208
|
const operationId = req.params["operationId"];
|
|
@@ -16160,7 +16246,7 @@ function registerWorkspaceExtensionRoutes(app, deps) {
|
|
|
16160
16246
|
`${base}/operations/:operationId/interactions/:interactionId`,
|
|
16161
16247
|
mutate({ strict: true }),
|
|
16162
16248
|
async (req, res) => {
|
|
16163
|
-
const ctrl =
|
|
16249
|
+
const ctrl = resolve6(req, res, false);
|
|
16164
16250
|
if (!ctrl) return;
|
|
16165
16251
|
try {
|
|
16166
16252
|
if (!ctrl.validateExtensionMutationClient(req, res, {
|
|
@@ -16229,7 +16315,7 @@ function registerWorkspaceExtensionRoutes(app, deps) {
|
|
|
16229
16315
|
}
|
|
16230
16316
|
);
|
|
16231
16317
|
app.post(`${base}/install`, mutate({ strict: true }), async (req, res) => {
|
|
16232
|
-
const ctrl =
|
|
16318
|
+
const ctrl = resolve6(req, res, true);
|
|
16233
16319
|
if (!ctrl) return;
|
|
16234
16320
|
try {
|
|
16235
16321
|
if (!ctrl.validateExtensionMutationClient(req, res, {
|
|
@@ -16412,7 +16498,7 @@ function registerWorkspaceExtensionRoutes(app, deps) {
|
|
|
16412
16498
|
`${base}/check-updates`,
|
|
16413
16499
|
mutate({ strict: true }),
|
|
16414
16500
|
async (req, res) => {
|
|
16415
|
-
const ctrl =
|
|
16501
|
+
const ctrl = resolve6(req, res, true);
|
|
16416
16502
|
if (!ctrl) return;
|
|
16417
16503
|
let timer;
|
|
16418
16504
|
let releaseOperationSlot;
|
|
@@ -16476,7 +16562,7 @@ function registerWorkspaceExtensionRoutes(app, deps) {
|
|
|
16476
16562
|
}
|
|
16477
16563
|
);
|
|
16478
16564
|
app.post(`${base}/refresh`, mutate({ strict: true }), async (req, res) => {
|
|
16479
|
-
const ctrl =
|
|
16565
|
+
const ctrl = resolve6(req, res, true);
|
|
16480
16566
|
if (!ctrl) return;
|
|
16481
16567
|
try {
|
|
16482
16568
|
if (!ctrl.validateExtensionMutationClient(req, res, {
|
|
@@ -16500,7 +16586,7 @@ function registerWorkspaceExtensionRoutes(app, deps) {
|
|
|
16500
16586
|
`${base}/:name/enable`,
|
|
16501
16587
|
mutate({ strict: true }),
|
|
16502
16588
|
async (req, res) => {
|
|
16503
|
-
const ctrl =
|
|
16589
|
+
const ctrl = resolve6(req, res, true);
|
|
16504
16590
|
if (!ctrl) return;
|
|
16505
16591
|
try {
|
|
16506
16592
|
if (!ctrl.validateExtensionMutationClient(req, res, {
|
|
@@ -16547,7 +16633,7 @@ function registerWorkspaceExtensionRoutes(app, deps) {
|
|
|
16547
16633
|
`${base}/:name/disable`,
|
|
16548
16634
|
mutate({ strict: true }),
|
|
16549
16635
|
async (req, res) => {
|
|
16550
|
-
const ctrl =
|
|
16636
|
+
const ctrl = resolve6(req, res, true);
|
|
16551
16637
|
if (!ctrl) return;
|
|
16552
16638
|
try {
|
|
16553
16639
|
if (!ctrl.validateExtensionMutationClient(req, res, {
|
|
@@ -16594,7 +16680,7 @@ function registerWorkspaceExtensionRoutes(app, deps) {
|
|
|
16594
16680
|
`${base}/:name/update`,
|
|
16595
16681
|
mutate({ strict: true }),
|
|
16596
16682
|
async (req, res) => {
|
|
16597
|
-
const ctrl =
|
|
16683
|
+
const ctrl = resolve6(req, res, true);
|
|
16598
16684
|
if (!ctrl) return;
|
|
16599
16685
|
try {
|
|
16600
16686
|
if (!ctrl.validateExtensionMutationClient(req, res, {
|
|
@@ -16677,7 +16763,7 @@ function registerWorkspaceExtensionRoutes(app, deps) {
|
|
|
16677
16763
|
}
|
|
16678
16764
|
);
|
|
16679
16765
|
app.delete(`${base}/:name`, mutate({ strict: true }), async (req, res) => {
|
|
16680
|
-
const ctrl =
|
|
16766
|
+
const ctrl = resolve6(req, res, true);
|
|
16681
16767
|
if (!ctrl) return;
|
|
16682
16768
|
try {
|
|
16683
16769
|
if (!ctrl.validateExtensionMutationClient(req, res, {
|
|
@@ -17439,13 +17525,13 @@ async function handlePostFileWrite(req, res, deps) {
|
|
|
17439
17525
|
req
|
|
17440
17526
|
);
|
|
17441
17527
|
if (originatorClientId === null) return;
|
|
17442
|
-
const
|
|
17528
|
+
const fs6 = factory.forRequest({
|
|
17443
17529
|
originatorClientId,
|
|
17444
17530
|
route: ROUTE2
|
|
17445
17531
|
});
|
|
17446
17532
|
try {
|
|
17447
|
-
const resolved = await
|
|
17448
|
-
const out = await
|
|
17533
|
+
const resolved = await fs6.resolve(queryPath, "write");
|
|
17534
|
+
const out = await fs6.writeTextAtomic(resolved, content, {
|
|
17449
17535
|
mode,
|
|
17450
17536
|
...expectedHash ? { expectedHash } : {},
|
|
17451
17537
|
...bom !== void 0 ? { bom } : {},
|
|
@@ -17498,13 +17584,13 @@ async function handlePostFileEdit(req, res, deps) {
|
|
|
17498
17584
|
req
|
|
17499
17585
|
);
|
|
17500
17586
|
if (originatorClientId === null) return;
|
|
17501
|
-
const
|
|
17587
|
+
const fs6 = factory.forRequest({
|
|
17502
17588
|
originatorClientId,
|
|
17503
17589
|
route: ROUTE2
|
|
17504
17590
|
});
|
|
17505
17591
|
try {
|
|
17506
|
-
const resolved = await
|
|
17507
|
-
const out = await
|
|
17592
|
+
const resolved = await fs6.resolve(queryPath, "edit");
|
|
17593
|
+
const out = await fs6.editAtomic(resolved, oldText, newText, {
|
|
17508
17594
|
expectedHash
|
|
17509
17595
|
});
|
|
17510
17596
|
applyReadHeaders(res);
|
|
@@ -17538,7 +17624,7 @@ function registerWorkspaceFileWriteRoutes(app, deps) {
|
|
|
17538
17624
|
}
|
|
17539
17625
|
__name(registerWorkspaceFileWriteRoutes, "registerWorkspaceFileWriteRoutes");
|
|
17540
17626
|
function registerWorkspaceQualifiedFileWriteRoutes(app, deps) {
|
|
17541
|
-
const
|
|
17627
|
+
const resolve6 = /* @__PURE__ */ __name((req, res) => {
|
|
17542
17628
|
const runtime = resolveWorkspaceRuntimeFromParam(
|
|
17543
17629
|
deps.workspaceRegistry,
|
|
17544
17630
|
req,
|
|
@@ -17556,7 +17642,7 @@ function registerWorkspaceQualifiedFileWriteRoutes(app, deps) {
|
|
|
17556
17642
|
"/workspaces/:workspace/file/write",
|
|
17557
17643
|
deps.mutate({ strict: true }),
|
|
17558
17644
|
(req, res) => {
|
|
17559
|
-
if (!
|
|
17645
|
+
if (!resolve6(req, res)) return;
|
|
17560
17646
|
void handlePostFileWrite(req, res, deps);
|
|
17561
17647
|
}
|
|
17562
17648
|
);
|
|
@@ -17564,7 +17650,7 @@ function registerWorkspaceQualifiedFileWriteRoutes(app, deps) {
|
|
|
17564
17650
|
"/workspaces/:workspace/file/edit",
|
|
17565
17651
|
deps.mutate({ strict: true }),
|
|
17566
17652
|
(req, res) => {
|
|
17567
|
-
if (!
|
|
17653
|
+
if (!resolve6(req, res)) return;
|
|
17568
17654
|
void handlePostFileEdit(req, res, deps);
|
|
17569
17655
|
}
|
|
17570
17656
|
);
|
|
@@ -17832,6 +17918,18 @@ var legacySessionTelemetryRoutes = [
|
|
|
17832
17918
|
attribution: "handler_resolved",
|
|
17833
17919
|
route: "GET /session/:id/tasks"
|
|
17834
17920
|
},
|
|
17921
|
+
{
|
|
17922
|
+
method: "GET",
|
|
17923
|
+
path: "/session/:id/subagents/:toolCallId",
|
|
17924
|
+
attribution: "handler_resolved",
|
|
17925
|
+
route: "GET /session/:id/subagents/:toolCallId"
|
|
17926
|
+
},
|
|
17927
|
+
{
|
|
17928
|
+
method: "POST",
|
|
17929
|
+
path: "/session/:id/subagents/:toolCallId/cancel",
|
|
17930
|
+
attribution: "handler_resolved",
|
|
17931
|
+
route: "POST /session/:id/subagents/:toolCallId/cancel"
|
|
17932
|
+
},
|
|
17835
17933
|
{
|
|
17836
17934
|
method: "GET",
|
|
17837
17935
|
path: "/session/:id/lsp",
|
|
@@ -18309,7 +18407,7 @@ function daemonTelemetryMiddleware(resolveWorkspaceCwd, recordRequest) {
|
|
|
18309
18407
|
deferredRuntimePath: deferredRuntime.path
|
|
18310
18408
|
} : {}
|
|
18311
18409
|
},
|
|
18312
|
-
async (span) => await new Promise((
|
|
18410
|
+
async (span) => await new Promise((resolve6, reject) => {
|
|
18313
18411
|
let done = false;
|
|
18314
18412
|
const finish = /* @__PURE__ */ __name(() => {
|
|
18315
18413
|
if (done) return;
|
|
@@ -18339,7 +18437,7 @@ function daemonTelemetryMiddleware(resolveWorkspaceCwd, recordRequest) {
|
|
|
18339
18437
|
if (!successfulSse && route.route !== "GET /daemon/status" && route.route !== "POST /session/:id/heartbeat") {
|
|
18340
18438
|
recordRequest?.(durationMs, res.statusCode);
|
|
18341
18439
|
}
|
|
18342
|
-
|
|
18440
|
+
resolve6();
|
|
18343
18441
|
}, "finish");
|
|
18344
18442
|
res.once("finish", finish);
|
|
18345
18443
|
res.once("close", finish);
|
|
@@ -18514,21 +18612,11 @@ __name(registerPermissionRoutes, "registerPermissionRoutes");
|
|
|
18514
18612
|
// packages/cli/src/serve/routes/session.ts
|
|
18515
18613
|
init_esbuild_shims();
|
|
18516
18614
|
import * as crypto3 from "node:crypto";
|
|
18517
|
-
import * as
|
|
18615
|
+
import * as fs4 from "node:fs";
|
|
18616
|
+
import * as path10 from "node:path";
|
|
18518
18617
|
|
|
18519
18618
|
// packages/cli/src/serve/server/prompt-deadline.ts
|
|
18520
18619
|
init_esbuild_shims();
|
|
18521
|
-
var PromptDeadlineExceededError = class extends Error {
|
|
18522
|
-
static {
|
|
18523
|
-
__name(this, "PromptDeadlineExceededError");
|
|
18524
|
-
}
|
|
18525
|
-
deadlineMs;
|
|
18526
|
-
constructor(deadlineMs) {
|
|
18527
|
-
super(`prompt exceeded the ${deadlineMs}ms deadline`);
|
|
18528
|
-
this.name = "PromptDeadlineExceededError";
|
|
18529
|
-
this.deadlineMs = deadlineMs;
|
|
18530
|
-
}
|
|
18531
|
-
};
|
|
18532
18620
|
function resolvePromptDeadlineMs(serverMs, requestMs) {
|
|
18533
18621
|
if (serverMs === void 0 || !Number.isFinite(serverMs) || serverMs <= 0) {
|
|
18534
18622
|
return void 0;
|
|
@@ -18638,6 +18726,25 @@ function encodeMetadataSessionCursor(last, filter, archiveState) {
|
|
|
18638
18726
|
).toString("base64url");
|
|
18639
18727
|
}
|
|
18640
18728
|
__name(encodeMetadataSessionCursor, "encodeMetadataSessionCursor");
|
|
18729
|
+
async function enrichWorktreeSidecars(bySessionId, sessionService, archiveState = "active") {
|
|
18730
|
+
for (const [sessionId, summary] of bySessionId) {
|
|
18731
|
+
if (summary.worktree) continue;
|
|
18732
|
+
const sidecar = await readWorktreeSession(
|
|
18733
|
+
sessionService.getWorktreeSessionPathForArchiveState(
|
|
18734
|
+
sessionId,
|
|
18735
|
+
archiveState
|
|
18736
|
+
)
|
|
18737
|
+
).catch(() => null);
|
|
18738
|
+
if (sidecar) {
|
|
18739
|
+
summary.worktree = {
|
|
18740
|
+
slug: sidecar.slug,
|
|
18741
|
+
path: sidecar.worktreePath,
|
|
18742
|
+
branch: sidecar.worktreeBranch
|
|
18743
|
+
};
|
|
18744
|
+
}
|
|
18745
|
+
}
|
|
18746
|
+
}
|
|
18747
|
+
__name(enrichWorktreeSidecars, "enrichWorktreeSidecars");
|
|
18641
18748
|
function toSummary2(item) {
|
|
18642
18749
|
return {
|
|
18643
18750
|
sessionId: item.sessionId,
|
|
@@ -18783,6 +18890,7 @@ async function listOrganizedWorkspaceSessionsForResponse(bridge, workspaceCwd, o
|
|
|
18783
18890
|
applyOrganization(session, snapshot.sessions.get(session.sessionId))
|
|
18784
18891
|
);
|
|
18785
18892
|
}
|
|
18893
|
+
await enrichWorktreeSidecars(bySessionId, sessionService, archiveState);
|
|
18786
18894
|
if (readOptions.mergeLive !== false && archiveState !== "archived" && isFirstPage) {
|
|
18787
18895
|
try {
|
|
18788
18896
|
const liveSessions = bridge.listWorkspaceSessions(workspaceCwd);
|
|
@@ -18868,6 +18976,7 @@ async function listWorkspaceSessionsByMetadataForResponse(bridge, workspaceCwd,
|
|
|
18868
18976
|
for (const session of persisted.sessions) {
|
|
18869
18977
|
bySessionId.set(session.sessionId, session);
|
|
18870
18978
|
}
|
|
18979
|
+
await enrichWorktreeSidecars(bySessionId, sessionService, archiveState);
|
|
18871
18980
|
let liveMergeFailed = false;
|
|
18872
18981
|
if (readOptions.mergeLive !== false && archiveState !== "archived") {
|
|
18873
18982
|
try {
|
|
@@ -18970,6 +19079,7 @@ async function listWorkspaceSessionsForResponse(bridge, workspaceCwd, options, r
|
|
|
18970
19079
|
for (const item of persisted.items) {
|
|
18971
19080
|
bySessionId.set(item.sessionId, toSummary2(item));
|
|
18972
19081
|
}
|
|
19082
|
+
await enrichWorktreeSidecars(bySessionId, sessionService, archiveState);
|
|
18973
19083
|
if (archiveState === "archived" || readOptions.mergeLive === false) {
|
|
18974
19084
|
const sessions2 = [...bySessionId.values()];
|
|
18975
19085
|
const nextCursor2 = persisted.nextCursor != null ? String(persisted.nextCursor) : void 0;
|
|
@@ -19108,123 +19218,831 @@ async function exportSessionTranscript(params) {
|
|
|
19108
19218
|
}
|
|
19109
19219
|
__name(exportSessionTranscript, "exportSessionTranscript");
|
|
19110
19220
|
|
|
19111
|
-
// packages/cli/src/serve/
|
|
19112
|
-
|
|
19113
|
-
|
|
19114
|
-
|
|
19115
|
-
|
|
19116
|
-
var
|
|
19117
|
-
|
|
19118
|
-
|
|
19119
|
-
|
|
19120
|
-
|
|
19121
|
-
|
|
19122
|
-
|
|
19123
|
-
|
|
19124
|
-
);
|
|
19221
|
+
// packages/cli/src/serve/virtual-subagent-sessions.ts
|
|
19222
|
+
init_esbuild_shims();
|
|
19223
|
+
import * as fs3 from "node:fs/promises";
|
|
19224
|
+
import { createReadStream } from "node:fs";
|
|
19225
|
+
import readline from "node:readline";
|
|
19226
|
+
var PREFIX = "subagent.";
|
|
19227
|
+
var POLL_INTERVAL_MS = 250;
|
|
19228
|
+
var TARGET_RETENTION_MS = 6e4;
|
|
19229
|
+
async function readFirstUserText(filePath) {
|
|
19230
|
+
const stream = createReadStream(filePath);
|
|
19231
|
+
const lines = readline.createInterface({
|
|
19232
|
+
input: stream,
|
|
19233
|
+
crlfDelay: Infinity
|
|
19234
|
+
});
|
|
19235
|
+
try {
|
|
19236
|
+
for await (const line of lines) {
|
|
19237
|
+
const trimmed = line.trim();
|
|
19238
|
+
if (!trimmed) continue;
|
|
19239
|
+
for (const record of parseLineTolerant(trimmed, filePath)) {
|
|
19240
|
+
if (record.type !== "user") continue;
|
|
19241
|
+
return record.message?.parts?.find(
|
|
19242
|
+
(part) => typeof part.text === "string"
|
|
19243
|
+
)?.text;
|
|
19244
|
+
}
|
|
19245
|
+
}
|
|
19246
|
+
return void 0;
|
|
19247
|
+
} catch (error2) {
|
|
19248
|
+
if (error2.code === "ENOENT") return void 0;
|
|
19249
|
+
throw error2;
|
|
19250
|
+
} finally {
|
|
19251
|
+
lines.close();
|
|
19252
|
+
stream.destroy();
|
|
19253
|
+
}
|
|
19254
|
+
}
|
|
19255
|
+
__name(readFirstUserText, "readFirstUserText");
|
|
19256
|
+
function asRecord(value) {
|
|
19257
|
+
return typeof value === "object" && value !== null ? value : void 0;
|
|
19258
|
+
}
|
|
19259
|
+
__name(asRecord, "asRecord");
|
|
19260
|
+
function finiteNonNegative(value) {
|
|
19261
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : void 0;
|
|
19262
|
+
}
|
|
19263
|
+
__name(finiteNonNegative, "finiteNonNegative");
|
|
19264
|
+
function normalizeTaskStatus(status) {
|
|
19265
|
+
if (typeof status !== "string") return void 0;
|
|
19266
|
+
if (status === "success") return "completed";
|
|
19267
|
+
if (status === "error") return "failed";
|
|
19268
|
+
if (status === "background") return "running";
|
|
19269
|
+
return status;
|
|
19270
|
+
}
|
|
19271
|
+
__name(normalizeTaskStatus, "normalizeTaskStatus");
|
|
19272
|
+
function durationBetween(start, end) {
|
|
19273
|
+
if (!end) return void 0;
|
|
19274
|
+
const startTime = Date.parse(start);
|
|
19275
|
+
const endTime = Date.parse(end);
|
|
19276
|
+
return Number.isFinite(startTime) && Number.isFinite(endTime) ? Math.max(0, endTime - startTime) : void 0;
|
|
19277
|
+
}
|
|
19278
|
+
__name(durationBetween, "durationBetween");
|
|
19279
|
+
function findToolCallMetrics(records, toolCallId) {
|
|
19280
|
+
const toolResult = records.find(
|
|
19281
|
+
(record) => record.toolCallResult?.callId === toolCallId
|
|
19282
|
+
)?.toolCallResult;
|
|
19283
|
+
const display = asRecord(toolResult?.resultDisplay);
|
|
19284
|
+
const summary = asRecord(display?.["executionSummary"]);
|
|
19285
|
+
return {
|
|
19286
|
+
status: normalizeTaskStatus(display?.["status"]) ?? normalizeTaskStatus(toolResult?.status),
|
|
19287
|
+
durationMs: finiteNonNegative(summary?.["totalDurationMs"]),
|
|
19288
|
+
totalTokens: finiteNonNegative(summary?.["totalTokens"]) ?? finiteNonNegative(display?.["tokenCount"]),
|
|
19289
|
+
inputTokens: finiteNonNegative(summary?.["inputTokens"]),
|
|
19290
|
+
outputTokens: finiteNonNegative(summary?.["outputTokens"]),
|
|
19291
|
+
cachedTokens: finiteNonNegative(summary?.["cachedTokens"])
|
|
19292
|
+
};
|
|
19125
19293
|
}
|
|
19126
|
-
__name(
|
|
19127
|
-
function
|
|
19128
|
-
return
|
|
19129
|
-
data: ${JSON.stringify({ v: 1, ...data })}
|
|
19130
|
-
|
|
19131
|
-
`;
|
|
19294
|
+
__name(findToolCallMetrics, "findToolCallMetrics");
|
|
19295
|
+
function encodePart(value) {
|
|
19296
|
+
return Buffer.from(value, "utf8").toString("base64url");
|
|
19132
19297
|
}
|
|
19133
|
-
__name(
|
|
19134
|
-
function
|
|
19135
|
-
|
|
19136
|
-
return
|
|
19137
|
-
}
|
|
19138
|
-
|
|
19139
|
-
const flush = res.flush;
|
|
19140
|
-
flush?.call(res);
|
|
19141
|
-
if (writable) {
|
|
19142
|
-
return res.destroyed ? Promise.reject(new Error("Generation SSE connection destroyed")) : Promise.resolve();
|
|
19298
|
+
__name(encodePart, "encodePart");
|
|
19299
|
+
function decodePart(value) {
|
|
19300
|
+
try {
|
|
19301
|
+
return Buffer.from(value, "base64url").toString("utf8");
|
|
19302
|
+
} catch {
|
|
19303
|
+
return void 0;
|
|
19143
19304
|
}
|
|
19144
|
-
return new Promise((resolve5, reject) => {
|
|
19145
|
-
const cleanup = /* @__PURE__ */ __name(() => {
|
|
19146
|
-
res.off("drain", onDrain);
|
|
19147
|
-
res.off("close", onClose);
|
|
19148
|
-
res.off("error", onError);
|
|
19149
|
-
}, "cleanup");
|
|
19150
|
-
const onDrain = /* @__PURE__ */ __name(() => {
|
|
19151
|
-
cleanup();
|
|
19152
|
-
resolve5();
|
|
19153
|
-
}, "onDrain");
|
|
19154
|
-
const onClose = /* @__PURE__ */ __name(() => {
|
|
19155
|
-
cleanup();
|
|
19156
|
-
reject(new Error("Generation SSE connection closed"));
|
|
19157
|
-
}, "onClose");
|
|
19158
|
-
const onError = /* @__PURE__ */ __name((error2) => {
|
|
19159
|
-
cleanup();
|
|
19160
|
-
reject(error2);
|
|
19161
|
-
}, "onError");
|
|
19162
|
-
res.once("drain", onDrain);
|
|
19163
|
-
res.once("close", onClose);
|
|
19164
|
-
res.once("error", onError);
|
|
19165
|
-
if (res.destroyed) onClose();
|
|
19166
|
-
});
|
|
19167
19305
|
}
|
|
19168
|
-
__name(
|
|
19169
|
-
function
|
|
19170
|
-
return
|
|
19171
|
-
}
|
|
19172
|
-
__name(isReadOnlyWorkspaceInspection, "isReadOnlyWorkspaceInspection");
|
|
19173
|
-
function runWorkspaceInspectionWithLogPolicy(runtime, read) {
|
|
19174
|
-
return isReadOnlyWorkspaceInspection(runtime) ? runWithoutDebugLogSession(read) : read();
|
|
19306
|
+
__name(decodePart, "decodePart");
|
|
19307
|
+
function isValidVirtualSessionPart(value) {
|
|
19308
|
+
return /^[a-zA-Z0-9_-]{1,500}$/.test(value);
|
|
19175
19309
|
}
|
|
19176
|
-
__name(
|
|
19177
|
-
function
|
|
19178
|
-
if (
|
|
19179
|
-
|
|
19180
|
-
|
|
19181
|
-
|
|
19182
|
-
errorKind: "client_id_required"
|
|
19183
|
-
});
|
|
19184
|
-
return false;
|
|
19310
|
+
__name(isValidVirtualSessionPart, "isValidVirtualSessionPart");
|
|
19311
|
+
function createVirtualSubagentSessionId(parentSessionId, agentId) {
|
|
19312
|
+
if (!isValidVirtualSessionPart(parentSessionId) || !isValidVirtualSessionPart(agentId)) {
|
|
19313
|
+
throw new Error("Virtual subagent session ids require valid id parts");
|
|
19314
|
+
}
|
|
19315
|
+
return `${PREFIX}${encodePart(parentSessionId)}.${encodePart(agentId)}`;
|
|
19185
19316
|
}
|
|
19186
|
-
__name(
|
|
19187
|
-
function
|
|
19188
|
-
if (!(
|
|
19189
|
-
return
|
|
19317
|
+
__name(createVirtualSubagentSessionId, "createVirtualSubagentSessionId");
|
|
19318
|
+
function parseVirtualSubagentSessionId(sessionId) {
|
|
19319
|
+
if (!sessionId.startsWith(PREFIX) || sessionId.length > 2e3) {
|
|
19320
|
+
return void 0;
|
|
19190
19321
|
}
|
|
19191
|
-
|
|
19322
|
+
const parts = sessionId.slice(PREFIX.length).split(".");
|
|
19323
|
+
if (parts.length !== 2) return void 0;
|
|
19324
|
+
const parentSessionId = decodePart(parts[0]);
|
|
19325
|
+
const agentId = decodePart(parts[1]);
|
|
19326
|
+
if (!parentSessionId || !agentId || !isValidVirtualSessionPart(parentSessionId) || !isValidVirtualSessionPart(agentId)) {
|
|
19327
|
+
return void 0;
|
|
19328
|
+
}
|
|
19329
|
+
return { parentSessionId, agentId };
|
|
19330
|
+
}
|
|
19331
|
+
__name(parseVirtualSubagentSessionId, "parseVirtualSubagentSessionId");
|
|
19332
|
+
function replayCursorState(sessionId, position, leafUuid, startTime, lastUpdated) {
|
|
19333
|
+
return {
|
|
19192
19334
|
v: 1,
|
|
19193
|
-
|
|
19194
|
-
|
|
19195
|
-
|
|
19196
|
-
|
|
19197
|
-
|
|
19198
|
-
|
|
19199
|
-
|
|
19335
|
+
sessionId,
|
|
19336
|
+
fileIdentity: { dev: 0, ino: 0 },
|
|
19337
|
+
snapshotSize: position,
|
|
19338
|
+
position,
|
|
19339
|
+
leafUuid,
|
|
19340
|
+
startTime,
|
|
19341
|
+
lastUpdated
|
|
19342
|
+
};
|
|
19200
19343
|
}
|
|
19201
|
-
__name(
|
|
19202
|
-
|
|
19203
|
-
|
|
19204
|
-
|
|
19344
|
+
__name(replayCursorState, "replayCursorState");
|
|
19345
|
+
var VirtualSubagentTarget = class _VirtualSubagentTarget {
|
|
19346
|
+
constructor(sessionId, parentSessionId, task, workspaceCwd, onExpired) {
|
|
19347
|
+
this.sessionId = sessionId;
|
|
19348
|
+
this.parentSessionId = parentSessionId;
|
|
19349
|
+
this.task = task;
|
|
19350
|
+
this.workspaceCwd = workspaceCwd;
|
|
19351
|
+
this.onExpired = onExpired;
|
|
19205
19352
|
}
|
|
19206
|
-
|
|
19207
|
-
|
|
19208
|
-
|
|
19209
|
-
|
|
19210
|
-
|
|
19211
|
-
|
|
19212
|
-
|
|
19213
|
-
|
|
19214
|
-
|
|
19215
|
-
|
|
19216
|
-
|
|
19217
|
-
|
|
19218
|
-
|
|
19219
|
-
|
|
19220
|
-
|
|
19221
|
-
|
|
19222
|
-
|
|
19353
|
+
static {
|
|
19354
|
+
__name(this, "VirtualSubagentTarget");
|
|
19355
|
+
}
|
|
19356
|
+
bus = new EventBus(1024, 8);
|
|
19357
|
+
events = [];
|
|
19358
|
+
snapshotDelivered = false;
|
|
19359
|
+
offset = 0;
|
|
19360
|
+
transcriptIdentity;
|
|
19361
|
+
streamOffset = 0;
|
|
19362
|
+
streamIdentity;
|
|
19363
|
+
streamReady = false;
|
|
19364
|
+
canonicalThroughTimestamp = 0;
|
|
19365
|
+
completedStreamRounds = /* @__PURE__ */ new Set();
|
|
19366
|
+
streamedRounds = /* @__PURE__ */ new Set();
|
|
19367
|
+
streamRunIds = /* @__PURE__ */ new Set();
|
|
19368
|
+
legacyStreamedSinceCanonical = false;
|
|
19369
|
+
replayState;
|
|
19370
|
+
initialized = false;
|
|
19371
|
+
refreshPromise = Promise.resolve();
|
|
19372
|
+
snapshotPromise = Promise.resolve();
|
|
19373
|
+
pollTimer;
|
|
19374
|
+
subscribers = 0;
|
|
19375
|
+
retentionTimer;
|
|
19376
|
+
updateStatus(status) {
|
|
19377
|
+
const wasRunning = this.task.status === "running";
|
|
19378
|
+
this.task.status = status;
|
|
19379
|
+
if (status !== "running" && this.pollTimer) {
|
|
19380
|
+
clearInterval(this.pollTimer);
|
|
19381
|
+
this.pollTimer = void 0;
|
|
19382
|
+
}
|
|
19383
|
+
if (wasRunning && status !== "running") {
|
|
19384
|
+
void this.refreshLive().catch(() => void 0);
|
|
19385
|
+
}
|
|
19386
|
+
}
|
|
19387
|
+
rememberEvent(event) {
|
|
19388
|
+
if (event && !this.snapshotDelivered) this.events.push(event);
|
|
19389
|
+
}
|
|
19390
|
+
resetCanonicalState() {
|
|
19391
|
+
this.offset = 0;
|
|
19392
|
+
this.replayState = void 0;
|
|
19393
|
+
this.canonicalThroughTimestamp = 0;
|
|
19394
|
+
this.completedStreamRounds.clear();
|
|
19395
|
+
this.streamRunIds.clear();
|
|
19396
|
+
this.streamedRounds.clear();
|
|
19397
|
+
this.legacyStreamedSinceCanonical = false;
|
|
19398
|
+
}
|
|
19399
|
+
resetStreamState() {
|
|
19400
|
+
this.streamOffset = 0;
|
|
19401
|
+
this.completedStreamRounds.clear();
|
|
19402
|
+
this.streamRunIds.clear();
|
|
19403
|
+
this.streamedRounds.clear();
|
|
19404
|
+
this.legacyStreamedSinceCanonical = false;
|
|
19405
|
+
}
|
|
19406
|
+
async readNewRecords(endOffset) {
|
|
19407
|
+
let handle;
|
|
19408
|
+
try {
|
|
19409
|
+
handle = await fs3.open(this.task.outputFile, "r");
|
|
19410
|
+
const stat3 = await handle.stat();
|
|
19411
|
+
const identity = `${stat3.dev}:${stat3.ino}`;
|
|
19412
|
+
if (this.transcriptIdentity !== void 0 && this.transcriptIdentity !== identity || stat3.size < this.offset) {
|
|
19413
|
+
this.resetCanonicalState();
|
|
19414
|
+
}
|
|
19415
|
+
this.transcriptIdentity = identity;
|
|
19416
|
+
const size = Math.min(stat3.size, endOffset ?? stat3.size);
|
|
19417
|
+
if (size <= this.offset) return [];
|
|
19418
|
+
const bytes = Buffer.alloc(size - this.offset);
|
|
19419
|
+
const { bytesRead } = await handle.read(
|
|
19420
|
+
bytes,
|
|
19421
|
+
0,
|
|
19422
|
+
bytes.length,
|
|
19423
|
+
this.offset
|
|
19424
|
+
);
|
|
19425
|
+
const chunk = bytes.subarray(0, bytesRead);
|
|
19426
|
+
const lastNewline = chunk.lastIndexOf(10);
|
|
19427
|
+
if (lastNewline < 0) return [];
|
|
19428
|
+
const complete = chunk.subarray(0, lastNewline + 1);
|
|
19429
|
+
this.offset += complete.length;
|
|
19430
|
+
return complete.toString("utf8").split("\n").flatMap((line) => {
|
|
19431
|
+
const trimmed = line.trim();
|
|
19432
|
+
return trimmed ? parseLineTolerant(trimmed, this.task.outputFile) : [];
|
|
19433
|
+
});
|
|
19434
|
+
} catch (error2) {
|
|
19435
|
+
if (error2.code === "ENOENT") {
|
|
19436
|
+
if (this.transcriptIdentity !== void 0) {
|
|
19437
|
+
this.transcriptIdentity = void 0;
|
|
19438
|
+
this.resetCanonicalState();
|
|
19439
|
+
}
|
|
19440
|
+
return [];
|
|
19441
|
+
}
|
|
19442
|
+
throw error2;
|
|
19443
|
+
} finally {
|
|
19444
|
+
await handle?.close();
|
|
19445
|
+
}
|
|
19223
19446
|
}
|
|
19224
|
-
|
|
19225
|
-
|
|
19226
|
-
|
|
19227
|
-
|
|
19447
|
+
async readStreamUpdates(endOffset) {
|
|
19448
|
+
const replayingExisting = !this.streamReady;
|
|
19449
|
+
this.streamReady = true;
|
|
19450
|
+
const filePath = `${this.task.outputFile}.stream`;
|
|
19451
|
+
let handle;
|
|
19452
|
+
try {
|
|
19453
|
+
handle = await fs3.open(filePath, "r");
|
|
19454
|
+
const stat3 = await handle.stat();
|
|
19455
|
+
const identity = `${stat3.dev}:${stat3.ino}`;
|
|
19456
|
+
if (this.streamIdentity !== void 0 && this.streamIdentity !== identity) {
|
|
19457
|
+
this.resetStreamState();
|
|
19458
|
+
}
|
|
19459
|
+
this.streamIdentity = identity;
|
|
19460
|
+
if (stat3.size < this.streamOffset) this.resetStreamState();
|
|
19461
|
+
const size = Math.min(stat3.size, endOffset ?? stat3.size);
|
|
19462
|
+
if (size <= this.streamOffset) return;
|
|
19463
|
+
const bytes = Buffer.alloc(size - this.streamOffset);
|
|
19464
|
+
const { bytesRead } = await handle.read(
|
|
19465
|
+
bytes,
|
|
19466
|
+
0,
|
|
19467
|
+
bytes.length,
|
|
19468
|
+
this.streamOffset
|
|
19469
|
+
);
|
|
19470
|
+
const chunk = bytes.subarray(0, bytesRead);
|
|
19471
|
+
const lastNewline = chunk.lastIndexOf(10);
|
|
19472
|
+
if (lastNewline < 0) return;
|
|
19473
|
+
const complete = chunk.subarray(0, lastNewline + 1);
|
|
19474
|
+
this.streamOffset += complete.length;
|
|
19475
|
+
const records = complete.toString("utf8").split("\n").flatMap((line) => {
|
|
19476
|
+
const trimmed = line.trim();
|
|
19477
|
+
return trimmed ? parseLineTolerant(trimmed, filePath) : [];
|
|
19478
|
+
});
|
|
19479
|
+
for (const record of records) {
|
|
19480
|
+
if (record.v !== 1 || typeof record.text !== "string" || typeof record.timestamp !== "number") {
|
|
19481
|
+
continue;
|
|
19482
|
+
}
|
|
19483
|
+
const roundKey = typeof record.runId === "string" && typeof record.round === "number" ? `${record.runId}:${record.round}` : void 0;
|
|
19484
|
+
if (typeof record.runId === "string") {
|
|
19485
|
+
this.streamRunIds.add(record.runId);
|
|
19486
|
+
}
|
|
19487
|
+
if ((roundKey ? this.completedStreamRounds.has(roundKey) : record.timestamp <= this.canonicalThroughTimestamp) || replayingExisting && typeof record.round !== "number") {
|
|
19488
|
+
continue;
|
|
19489
|
+
}
|
|
19490
|
+
const event = this.bus.publish({
|
|
19491
|
+
type: "session_update",
|
|
19492
|
+
data: createTranscriptMessageUpdate({
|
|
19493
|
+
role: "assistant",
|
|
19494
|
+
text: record.text,
|
|
19495
|
+
timestamp: record.timestamp,
|
|
19496
|
+
...record.thought ? { thought: true } : {}
|
|
19497
|
+
})
|
|
19498
|
+
});
|
|
19499
|
+
this.rememberEvent(event);
|
|
19500
|
+
if (roundKey) this.streamedRounds.add(roundKey);
|
|
19501
|
+
else this.legacyStreamedSinceCanonical = true;
|
|
19502
|
+
}
|
|
19503
|
+
for (const completed of this.completedStreamRounds) {
|
|
19504
|
+
const runId = completed.slice(0, completed.lastIndexOf(":"));
|
|
19505
|
+
if (!this.streamRunIds.has(runId)) {
|
|
19506
|
+
this.completedStreamRounds.delete(completed);
|
|
19507
|
+
}
|
|
19508
|
+
}
|
|
19509
|
+
} catch (error2) {
|
|
19510
|
+
if (error2.code !== "ENOENT") throw error2;
|
|
19511
|
+
this.streamIdentity = void 0;
|
|
19512
|
+
this.streamOffset = 0;
|
|
19513
|
+
this.streamRunIds.clear();
|
|
19514
|
+
this.streamedRounds.clear();
|
|
19515
|
+
this.legacyStreamedSinceCanonical = false;
|
|
19516
|
+
} finally {
|
|
19517
|
+
await handle?.close();
|
|
19518
|
+
}
|
|
19519
|
+
}
|
|
19520
|
+
refreshOnce = /* @__PURE__ */ __name(async (endOffset) => {
|
|
19521
|
+
let records = await this.readNewRecords(endOffset);
|
|
19522
|
+
if (records.length === 0) {
|
|
19523
|
+
this.initialized = true;
|
|
19524
|
+
return;
|
|
19525
|
+
}
|
|
19526
|
+
for (const record of records) {
|
|
19527
|
+
if (record.type === "assistant" && (record.usageMetadata !== void 0 || record.message?.parts?.some((part) => typeof part.text === "string"))) {
|
|
19528
|
+
if (typeof record.agentRunId === "string" && typeof record.agentRound === "number") {
|
|
19529
|
+
this.completedStreamRounds.add(
|
|
19530
|
+
`${record.agentRunId}:${record.agentRound}`
|
|
19531
|
+
);
|
|
19532
|
+
}
|
|
19533
|
+
const timestamp = Date.parse(record.timestamp);
|
|
19534
|
+
if (Number.isFinite(timestamp)) {
|
|
19535
|
+
this.canonicalThroughTimestamp = Math.max(
|
|
19536
|
+
this.canonicalThroughTimestamp,
|
|
19537
|
+
timestamp
|
|
19538
|
+
);
|
|
19539
|
+
}
|
|
19540
|
+
}
|
|
19541
|
+
}
|
|
19542
|
+
if (this.streamedRounds.size > 0 || this.legacyStreamedSinceCanonical) {
|
|
19543
|
+
records = records.filter((record) => {
|
|
19544
|
+
const roundKey = typeof record.agentRunId === "string" && typeof record.agentRound === "number" ? `${record.agentRunId}:${record.agentRound}` : void 0;
|
|
19545
|
+
if (roundKey && this.streamedRounds.delete(roundKey)) return false;
|
|
19546
|
+
if (!this.legacyStreamedSinceCanonical || record.type !== "assistant" || record.message?.parts?.some((part) => part.functionCall)) {
|
|
19547
|
+
return true;
|
|
19548
|
+
}
|
|
19549
|
+
this.legacyStreamedSinceCanonical = false;
|
|
19550
|
+
return false;
|
|
19551
|
+
});
|
|
19552
|
+
if (records.length === 0) {
|
|
19553
|
+
this.initialized = true;
|
|
19554
|
+
return;
|
|
19555
|
+
}
|
|
19556
|
+
}
|
|
19557
|
+
const startTime = records[0]?.timestamp ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
19558
|
+
const lastUpdated = records[records.length - 1]?.timestamp ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
19559
|
+
const page = {
|
|
19560
|
+
sessionId: this.sessionId,
|
|
19561
|
+
filePath: this.task.outputFile,
|
|
19562
|
+
records,
|
|
19563
|
+
gaps: [],
|
|
19564
|
+
hasMore: true,
|
|
19565
|
+
replay: this.replayState,
|
|
19566
|
+
startTime,
|
|
19567
|
+
lastUpdated,
|
|
19568
|
+
nextCursorState: replayCursorState(
|
|
19569
|
+
this.sessionId,
|
|
19570
|
+
this.offset,
|
|
19571
|
+
records[records.length - 1]?.uuid ?? "",
|
|
19572
|
+
startTime,
|
|
19573
|
+
lastUpdated
|
|
19574
|
+
)
|
|
19575
|
+
};
|
|
19576
|
+
let nextReplayState;
|
|
19577
|
+
const replay = await replayTranscriptRecordPage({
|
|
19578
|
+
sessionId: this.sessionId,
|
|
19579
|
+
page,
|
|
19580
|
+
encodeCursor: /* @__PURE__ */ __name((state) => {
|
|
19581
|
+
nextReplayState = state.replay;
|
|
19582
|
+
return "virtual-subagent-replay";
|
|
19583
|
+
}, "encodeCursor")
|
|
19584
|
+
});
|
|
19585
|
+
this.replayState = nextReplayState;
|
|
19586
|
+
const inputs = replay.updates.map((update) => ({
|
|
19587
|
+
type: "session_update",
|
|
19588
|
+
data: update
|
|
19589
|
+
}));
|
|
19590
|
+
const published = this.initialized ? inputs.flatMap((input) => {
|
|
19591
|
+
const event = this.bus.publish(input);
|
|
19592
|
+
return event ? [event] : [];
|
|
19593
|
+
}) : this.bus.seedReplayEvents(inputs);
|
|
19594
|
+
if (!this.snapshotDelivered) this.events.push(...published);
|
|
19595
|
+
this.initialized = true;
|
|
19596
|
+
}, "refreshOnce");
|
|
19597
|
+
refreshAt(bounds) {
|
|
19598
|
+
return this.refreshOnce(bounds?.transcript).then(async () => {
|
|
19599
|
+
if (this.task.status === "running") {
|
|
19600
|
+
await this.readStreamUpdates(bounds?.stream);
|
|
19601
|
+
}
|
|
19602
|
+
});
|
|
19603
|
+
}
|
|
19604
|
+
enqueueRefresh(work) {
|
|
19605
|
+
const result = this.refreshPromise.catch(() => void 0).then(work);
|
|
19606
|
+
this.refreshPromise = result.then(
|
|
19607
|
+
() => void 0,
|
|
19608
|
+
() => void 0
|
|
19609
|
+
);
|
|
19610
|
+
return result;
|
|
19611
|
+
}
|
|
19612
|
+
refreshLive() {
|
|
19613
|
+
return this.enqueueRefresh(() => this.refreshAt());
|
|
19614
|
+
}
|
|
19615
|
+
async captureReadBounds() {
|
|
19616
|
+
const size = /* @__PURE__ */ __name(async (filePath) => {
|
|
19617
|
+
try {
|
|
19618
|
+
return (await fs3.stat(filePath)).size;
|
|
19619
|
+
} catch (error2) {
|
|
19620
|
+
if (error2.code === "ENOENT") return 0;
|
|
19621
|
+
throw error2;
|
|
19622
|
+
}
|
|
19623
|
+
}, "size");
|
|
19624
|
+
const [transcript, stream] = await Promise.all([
|
|
19625
|
+
size(this.task.outputFile),
|
|
19626
|
+
size(`${this.task.outputFile}.stream`)
|
|
19627
|
+
]);
|
|
19628
|
+
return { transcript, stream };
|
|
19629
|
+
}
|
|
19630
|
+
async createSnapshotOnce() {
|
|
19631
|
+
if (!this.snapshotDelivered) {
|
|
19632
|
+
await this.refreshLive();
|
|
19633
|
+
const snapshot = [...this.events];
|
|
19634
|
+
this.events.length = 0;
|
|
19635
|
+
this.snapshotDelivered = true;
|
|
19636
|
+
return { events: snapshot, lastEventId: this.bus.lastEventId };
|
|
19637
|
+
}
|
|
19638
|
+
return this.enqueueRefresh(async () => {
|
|
19639
|
+
const bounds = await this.captureReadBounds();
|
|
19640
|
+
const target = new _VirtualSubagentTarget(
|
|
19641
|
+
this.sessionId,
|
|
19642
|
+
this.parentSessionId,
|
|
19643
|
+
this.task,
|
|
19644
|
+
this.workspaceCwd,
|
|
19645
|
+
() => void 0
|
|
19646
|
+
);
|
|
19647
|
+
await target.refreshAt(bounds);
|
|
19648
|
+
await this.refreshAt(bounds);
|
|
19649
|
+
return {
|
|
19650
|
+
events: [...target.events],
|
|
19651
|
+
lastEventId: this.bus.lastEventId
|
|
19652
|
+
};
|
|
19653
|
+
});
|
|
19654
|
+
}
|
|
19655
|
+
createSnapshot() {
|
|
19656
|
+
const snapshot = this.snapshotPromise.then(() => this.createSnapshotOnce());
|
|
19657
|
+
this.snapshotPromise = snapshot.then(
|
|
19658
|
+
() => void 0,
|
|
19659
|
+
() => void 0
|
|
19660
|
+
);
|
|
19661
|
+
return snapshot;
|
|
19662
|
+
}
|
|
19663
|
+
async load(clientId) {
|
|
19664
|
+
const snapshot = await this.createSnapshot();
|
|
19665
|
+
if (this.subscribers === 0) this.scheduleRetention();
|
|
19666
|
+
return {
|
|
19667
|
+
sessionId: this.sessionId,
|
|
19668
|
+
workspaceCwd: this.workspaceCwd,
|
|
19669
|
+
attached: true,
|
|
19670
|
+
...clientId ? { clientId } : {},
|
|
19671
|
+
createdAt: new Date(this.task.startTime).toISOString(),
|
|
19672
|
+
hasActivePrompt: this.task.status === "running",
|
|
19673
|
+
state: {},
|
|
19674
|
+
compactedReplay: snapshot.events,
|
|
19675
|
+
liveJournal: [],
|
|
19676
|
+
historyHasMore: false,
|
|
19677
|
+
lastEventId: snapshot.lastEventId
|
|
19678
|
+
};
|
|
19679
|
+
}
|
|
19680
|
+
async *iterate(opts) {
|
|
19681
|
+
if (this.retentionTimer) {
|
|
19682
|
+
clearTimeout(this.retentionTimer);
|
|
19683
|
+
this.retentionTimer = void 0;
|
|
19684
|
+
}
|
|
19685
|
+
this.subscribers++;
|
|
19686
|
+
try {
|
|
19687
|
+
await this.refreshLive();
|
|
19688
|
+
if (!this.snapshotDelivered) {
|
|
19689
|
+
this.events.length = 0;
|
|
19690
|
+
this.snapshotDelivered = true;
|
|
19691
|
+
}
|
|
19692
|
+
if (this.task.status === "running" && !this.pollTimer) {
|
|
19693
|
+
this.pollTimer = setInterval(() => {
|
|
19694
|
+
void this.refreshLive().catch(() => void 0);
|
|
19695
|
+
}, POLL_INTERVAL_MS);
|
|
19696
|
+
this.pollTimer.unref();
|
|
19697
|
+
}
|
|
19698
|
+
yield* this.bus.subscribe(opts);
|
|
19699
|
+
} finally {
|
|
19700
|
+
this.subscribers--;
|
|
19701
|
+
if (this.subscribers === 0) {
|
|
19702
|
+
if (this.pollTimer) clearInterval(this.pollTimer);
|
|
19703
|
+
this.pollTimer = void 0;
|
|
19704
|
+
this.scheduleRetention();
|
|
19705
|
+
}
|
|
19706
|
+
}
|
|
19707
|
+
}
|
|
19708
|
+
subscribe(opts) {
|
|
19709
|
+
return {
|
|
19710
|
+
[Symbol.asyncIterator]: () => this.iterate(opts)
|
|
19711
|
+
};
|
|
19712
|
+
}
|
|
19713
|
+
scheduleRetention() {
|
|
19714
|
+
if (this.retentionTimer) clearTimeout(this.retentionTimer);
|
|
19715
|
+
this.retentionTimer = setTimeout(this.onExpired, TARGET_RETENTION_MS);
|
|
19716
|
+
this.retentionTimer.unref();
|
|
19717
|
+
}
|
|
19718
|
+
};
|
|
19719
|
+
var VirtualSubagentSessions = class {
|
|
19720
|
+
static {
|
|
19721
|
+
__name(this, "VirtualSubagentSessions");
|
|
19722
|
+
}
|
|
19723
|
+
targets = /* @__PURE__ */ new Map();
|
|
19724
|
+
async findTask(runtime, parentSessionId, predicate) {
|
|
19725
|
+
const status = await runtime.bridge.getSessionTasksStatus(parentSessionId);
|
|
19726
|
+
const task = status.tasks.find(
|
|
19727
|
+
(candidate) => candidate.kind === "agent" && typeof candidate.outputFile === "string" && predicate(candidate)
|
|
19728
|
+
);
|
|
19729
|
+
if (task?.kind === "agent" && task.outputFile) {
|
|
19730
|
+
return {
|
|
19731
|
+
id: task.id,
|
|
19732
|
+
title: task.label,
|
|
19733
|
+
outputFile: task.outputFile,
|
|
19734
|
+
status: task.status,
|
|
19735
|
+
startTime: task.startTime,
|
|
19736
|
+
durationMs: task.stats?.durationMs ?? (task.endTime === void 0 ? void 0 : Math.max(0, task.endTime - task.startTime)),
|
|
19737
|
+
totalTokens: task.stats?.totalTokens
|
|
19738
|
+
};
|
|
19739
|
+
}
|
|
19740
|
+
const runtimeDir = runtime.env.effectiveEnv?.["QWEN_RUNTIME_DIR"];
|
|
19741
|
+
const projectDir = Storage.runWithRuntimeBaseDir(
|
|
19742
|
+
runtimeDir,
|
|
19743
|
+
runtime.workspaceCwd,
|
|
19744
|
+
() => new Storage(runtime.workspaceCwd).getProjectDir()
|
|
19745
|
+
);
|
|
19746
|
+
const sessionDir = getSubagentSessionDir(projectDir, parentSessionId);
|
|
19747
|
+
let names;
|
|
19748
|
+
try {
|
|
19749
|
+
names = await fs3.readdir(sessionDir);
|
|
19750
|
+
} catch (error2) {
|
|
19751
|
+
if (error2.code === "ENOENT") return void 0;
|
|
19752
|
+
throw error2;
|
|
19753
|
+
}
|
|
19754
|
+
for (const name of names) {
|
|
19755
|
+
if (!name.endsWith(".meta.json")) continue;
|
|
19756
|
+
const metaPath = `${sessionDir}/${name}`;
|
|
19757
|
+
const meta = readAgentMeta(metaPath);
|
|
19758
|
+
if (!meta || !predicate({
|
|
19759
|
+
kind: "agent",
|
|
19760
|
+
id: meta.agentId,
|
|
19761
|
+
toolUseId: meta.toolUseId,
|
|
19762
|
+
outputFile: metaPath.slice(0, -".meta.json".length) + ".jsonl"
|
|
19763
|
+
})) {
|
|
19764
|
+
continue;
|
|
19765
|
+
}
|
|
19766
|
+
return {
|
|
19767
|
+
id: meta.agentId,
|
|
19768
|
+
title: meta.description || meta.agentType,
|
|
19769
|
+
outputFile: metaPath.slice(0, -".meta.json".length) + ".jsonl",
|
|
19770
|
+
status: meta.status ?? "completed",
|
|
19771
|
+
startTime: Number.isFinite(Date.parse(meta.createdAt)) ? Date.parse(meta.createdAt) : Date.now(),
|
|
19772
|
+
durationMs: durationBetween(meta.createdAt, meta.lastUpdatedAt)
|
|
19773
|
+
};
|
|
19774
|
+
}
|
|
19775
|
+
return void 0;
|
|
19776
|
+
}
|
|
19777
|
+
async findLegacyTaskByToolCall(runtime, parentSessionId, toolCallId) {
|
|
19778
|
+
const runtimeDir = runtime.env.effectiveEnv?.["QWEN_RUNTIME_DIR"];
|
|
19779
|
+
const projectDir = Storage.runWithRuntimeBaseDir(
|
|
19780
|
+
runtimeDir,
|
|
19781
|
+
runtime.workspaceCwd,
|
|
19782
|
+
() => new Storage(runtime.workspaceCwd).getProjectDir()
|
|
19783
|
+
);
|
|
19784
|
+
const parentRecords = await read(
|
|
19785
|
+
`${projectDir}/chats/${parentSessionId}.jsonl`
|
|
19786
|
+
);
|
|
19787
|
+
let root;
|
|
19788
|
+
for (const record of parentRecords) {
|
|
19789
|
+
for (const part of record.message?.parts ?? []) {
|
|
19790
|
+
const call = part.functionCall;
|
|
19791
|
+
if (call?.id !== toolCallId || call.name !== "agent") continue;
|
|
19792
|
+
const args = call.args;
|
|
19793
|
+
root = {
|
|
19794
|
+
timestamp: Date.parse(record.timestamp),
|
|
19795
|
+
...typeof args?.["description"] === "string" ? { description: args["description"] } : {},
|
|
19796
|
+
...typeof args?.["prompt"] === "string" ? { prompt: args["prompt"] } : {},
|
|
19797
|
+
...typeof args?.["subagent_type"] === "string" ? { agentType: args["subagent_type"] } : {}
|
|
19798
|
+
};
|
|
19799
|
+
break;
|
|
19800
|
+
}
|
|
19801
|
+
if (root) break;
|
|
19802
|
+
}
|
|
19803
|
+
if (!root) return void 0;
|
|
19804
|
+
const sessionDir = getSubagentSessionDir(projectDir, parentSessionId);
|
|
19805
|
+
let names;
|
|
19806
|
+
try {
|
|
19807
|
+
names = await fs3.readdir(sessionDir);
|
|
19808
|
+
} catch (error2) {
|
|
19809
|
+
if (error2.code === "ENOENT") return void 0;
|
|
19810
|
+
throw error2;
|
|
19811
|
+
}
|
|
19812
|
+
const candidates = [];
|
|
19813
|
+
for (const name of names) {
|
|
19814
|
+
if (!name.endsWith(".meta.json")) continue;
|
|
19815
|
+
const metaPath = `${sessionDir}/${name}`;
|
|
19816
|
+
const meta = readAgentMeta(metaPath);
|
|
19817
|
+
if (!meta) continue;
|
|
19818
|
+
const outputFile = metaPath.slice(0, -".meta.json".length) + ".jsonl";
|
|
19819
|
+
const launchPrompt = await readFirstUserText(outputFile);
|
|
19820
|
+
let score = 0;
|
|
19821
|
+
if (root.prompt && launchPrompt === root.prompt) score += 8;
|
|
19822
|
+
if (root.description && meta.description === root.description) score += 4;
|
|
19823
|
+
if (root.agentType && meta.agentType === root.agentType) score += 2;
|
|
19824
|
+
const startTime = Date.parse(meta.createdAt);
|
|
19825
|
+
const delta = Math.abs(startTime - root.timestamp);
|
|
19826
|
+
if (Number.isFinite(delta) && delta <= 6e4) score += 1;
|
|
19827
|
+
if (score === 0) continue;
|
|
19828
|
+
candidates.push({
|
|
19829
|
+
id: meta.agentId,
|
|
19830
|
+
title: meta.description || meta.agentType,
|
|
19831
|
+
outputFile,
|
|
19832
|
+
status: meta.status ?? "completed",
|
|
19833
|
+
startTime: Number.isFinite(startTime) ? startTime : Date.now(),
|
|
19834
|
+
durationMs: durationBetween(meta.createdAt, meta.lastUpdatedAt),
|
|
19835
|
+
score,
|
|
19836
|
+
delta
|
|
19837
|
+
});
|
|
19838
|
+
}
|
|
19839
|
+
candidates.sort((a, b) => b.score - a.score || a.delta - b.delta);
|
|
19840
|
+
const selected = candidates[0];
|
|
19841
|
+
if (!selected) return void 0;
|
|
19842
|
+
const metrics = findToolCallMetrics(parentRecords, toolCallId);
|
|
19843
|
+
return {
|
|
19844
|
+
...selected,
|
|
19845
|
+
status: metrics.status ?? selected.status,
|
|
19846
|
+
durationMs: metrics.durationMs ?? selected.durationMs,
|
|
19847
|
+
totalTokens: metrics.totalTokens ?? selected.totalTokens,
|
|
19848
|
+
inputTokens: metrics.inputTokens ?? selected.inputTokens,
|
|
19849
|
+
outputTokens: metrics.outputTokens ?? selected.outputTokens,
|
|
19850
|
+
cachedTokens: metrics.cachedTokens ?? selected.cachedTokens
|
|
19851
|
+
};
|
|
19852
|
+
}
|
|
19853
|
+
async readParentToolCallMetrics(runtime, parentSessionId, toolCallId) {
|
|
19854
|
+
const runtimeDir = runtime.env.effectiveEnv?.["QWEN_RUNTIME_DIR"];
|
|
19855
|
+
const projectDir = Storage.runWithRuntimeBaseDir(
|
|
19856
|
+
runtimeDir,
|
|
19857
|
+
runtime.workspaceCwd,
|
|
19858
|
+
() => new Storage(runtime.workspaceCwd).getProjectDir()
|
|
19859
|
+
);
|
|
19860
|
+
const records = await read(
|
|
19861
|
+
`${projectDir}/chats/${parentSessionId}.jsonl`
|
|
19862
|
+
);
|
|
19863
|
+
return findToolCallMetrics(records, toolCallId);
|
|
19864
|
+
}
|
|
19865
|
+
async resolve(runtime, parentSessionId, toolCallId) {
|
|
19866
|
+
let task = await this.findTask(
|
|
19867
|
+
runtime,
|
|
19868
|
+
parentSessionId,
|
|
19869
|
+
(candidate) => candidate.toolUseId === toolCallId || candidate.id.endsWith(`-${toolCallId}`)
|
|
19870
|
+
);
|
|
19871
|
+
const metrics = task && task.status !== "running" ? await this.readParentToolCallMetrics(
|
|
19872
|
+
runtime,
|
|
19873
|
+
parentSessionId,
|
|
19874
|
+
toolCallId
|
|
19875
|
+
) : void 0;
|
|
19876
|
+
task ??= await this.findLegacyTaskByToolCall(
|
|
19877
|
+
runtime,
|
|
19878
|
+
parentSessionId,
|
|
19879
|
+
toolCallId
|
|
19880
|
+
);
|
|
19881
|
+
if (!task) return void 0;
|
|
19882
|
+
const sessionId = createVirtualSubagentSessionId(parentSessionId, task.id);
|
|
19883
|
+
const status = task.status;
|
|
19884
|
+
this.targets.get(`${runtime.workspaceId}:${sessionId}`)?.updateStatus(status);
|
|
19885
|
+
return {
|
|
19886
|
+
sessionId,
|
|
19887
|
+
taskId: task.id,
|
|
19888
|
+
title: task.title,
|
|
19889
|
+
status,
|
|
19890
|
+
durationMs: metrics?.durationMs ?? task.durationMs,
|
|
19891
|
+
totalTokens: metrics?.totalTokens ?? task.totalTokens,
|
|
19892
|
+
inputTokens: metrics?.inputTokens ?? task.inputTokens,
|
|
19893
|
+
outputTokens: metrics?.outputTokens ?? task.outputTokens,
|
|
19894
|
+
cachedTokens: metrics?.cachedTokens ?? task.cachedTokens
|
|
19895
|
+
};
|
|
19896
|
+
}
|
|
19897
|
+
async getTarget(runtime, sessionId) {
|
|
19898
|
+
const targetKey = `${runtime.workspaceId}:${sessionId}`;
|
|
19899
|
+
const cached = this.targets.get(targetKey);
|
|
19900
|
+
if (cached) return cached;
|
|
19901
|
+
const key = parseVirtualSubagentSessionId(sessionId);
|
|
19902
|
+
if (!key) return void 0;
|
|
19903
|
+
const task = await this.findTask(
|
|
19904
|
+
runtime,
|
|
19905
|
+
key.parentSessionId,
|
|
19906
|
+
(candidate) => candidate.id === key.agentId
|
|
19907
|
+
);
|
|
19908
|
+
if (!task) return void 0;
|
|
19909
|
+
const existing = this.targets.get(targetKey);
|
|
19910
|
+
if (existing) return existing;
|
|
19911
|
+
const target = new VirtualSubagentTarget(
|
|
19912
|
+
sessionId,
|
|
19913
|
+
key.parentSessionId,
|
|
19914
|
+
task,
|
|
19915
|
+
runtime.workspaceCwd,
|
|
19916
|
+
() => this.targets.delete(targetKey)
|
|
19917
|
+
);
|
|
19918
|
+
this.targets.set(targetKey, target);
|
|
19919
|
+
return target;
|
|
19920
|
+
}
|
|
19921
|
+
async load(runtime, sessionId, clientId) {
|
|
19922
|
+
return (await this.getTarget(runtime, sessionId))?.load(clientId);
|
|
19923
|
+
}
|
|
19924
|
+
async subscribe(runtime, sessionId, opts) {
|
|
19925
|
+
return (await this.getTarget(runtime, sessionId))?.subscribe(opts);
|
|
19926
|
+
}
|
|
19927
|
+
};
|
|
19928
|
+
|
|
19929
|
+
// packages/cli/src/serve/routes/session.ts
|
|
19930
|
+
var WORKSPACE_TRANSCRIPT_RESPONSE_MAX_BYTES = 32 * 1024 * 1024;
|
|
19931
|
+
var WORKSPACE_TRANSCRIPT_CURSOR_MAX_BYTES = 64 * 1024;
|
|
19932
|
+
var TRANSCRIPT_CURSOR_TOO_LARGE_REPLAY_ERROR = "Transcript pagination state exceeds the safe limit";
|
|
19933
|
+
var GENERATION_HEARTBEAT_MS = 15e3;
|
|
19934
|
+
var PRIMARY_ONLY_LIVE_SESSION_ROUTES = [
|
|
19935
|
+
"POST /session/:id/branch",
|
|
19936
|
+
"POST /session/:id/fork",
|
|
19937
|
+
"POST /session/:id/cd"
|
|
19938
|
+
];
|
|
19939
|
+
function isPrimaryOnlyLiveSessionRoute(route) {
|
|
19940
|
+
return PRIMARY_ONLY_LIVE_SESSION_ROUTES.includes(
|
|
19941
|
+
route
|
|
19942
|
+
);
|
|
19943
|
+
}
|
|
19944
|
+
__name(isPrimaryOnlyLiveSessionRoute, "isPrimaryOnlyLiveSessionRoute");
|
|
19945
|
+
function formatGenerationSse(event, data) {
|
|
19946
|
+
return `event: ${event}
|
|
19947
|
+
data: ${JSON.stringify({ v: 1, ...data })}
|
|
19948
|
+
|
|
19949
|
+
`;
|
|
19950
|
+
}
|
|
19951
|
+
__name(formatGenerationSse, "formatGenerationSse");
|
|
19952
|
+
function writeGenerationSseChunk(res, chunk) {
|
|
19953
|
+
if (res.destroyed) {
|
|
19954
|
+
return Promise.reject(new Error("Generation SSE connection destroyed"));
|
|
19955
|
+
}
|
|
19956
|
+
const writable = res.write(chunk);
|
|
19957
|
+
const flush = res.flush;
|
|
19958
|
+
flush?.call(res);
|
|
19959
|
+
if (writable) {
|
|
19960
|
+
return res.destroyed ? Promise.reject(new Error("Generation SSE connection destroyed")) : Promise.resolve();
|
|
19961
|
+
}
|
|
19962
|
+
return new Promise((resolve6, reject) => {
|
|
19963
|
+
const cleanup = /* @__PURE__ */ __name(() => {
|
|
19964
|
+
res.off("drain", onDrain);
|
|
19965
|
+
res.off("close", onClose);
|
|
19966
|
+
res.off("error", onError);
|
|
19967
|
+
}, "cleanup");
|
|
19968
|
+
const onDrain = /* @__PURE__ */ __name(() => {
|
|
19969
|
+
cleanup();
|
|
19970
|
+
resolve6();
|
|
19971
|
+
}, "onDrain");
|
|
19972
|
+
const onClose = /* @__PURE__ */ __name(() => {
|
|
19973
|
+
cleanup();
|
|
19974
|
+
reject(new Error("Generation SSE connection closed"));
|
|
19975
|
+
}, "onClose");
|
|
19976
|
+
const onError = /* @__PURE__ */ __name((error2) => {
|
|
19977
|
+
cleanup();
|
|
19978
|
+
reject(error2);
|
|
19979
|
+
}, "onError");
|
|
19980
|
+
res.once("drain", onDrain);
|
|
19981
|
+
res.once("close", onClose);
|
|
19982
|
+
res.once("error", onError);
|
|
19983
|
+
if (res.destroyed) onClose();
|
|
19984
|
+
});
|
|
19985
|
+
}
|
|
19986
|
+
__name(writeGenerationSseChunk, "writeGenerationSseChunk");
|
|
19987
|
+
function isReadOnlyWorkspaceInspection(runtime) {
|
|
19988
|
+
return !runtime.primary && !runtime.trusted;
|
|
19989
|
+
}
|
|
19990
|
+
__name(isReadOnlyWorkspaceInspection, "isReadOnlyWorkspaceInspection");
|
|
19991
|
+
function runWorkspaceInspectionWithLogPolicy(runtime, read2) {
|
|
19992
|
+
return isReadOnlyWorkspaceInspection(runtime) ? runWithoutDebugLogSession(read2) : read2();
|
|
19993
|
+
}
|
|
19994
|
+
__name(runWorkspaceInspectionWithLogPolicy, "runWorkspaceInspectionWithLogPolicy");
|
|
19995
|
+
function requireSessionArtifactClientId(clientId, res) {
|
|
19996
|
+
if (clientId !== void 0) return true;
|
|
19997
|
+
res.status(403).json({
|
|
19998
|
+
error: "Session artifact access requires a session-bound client id",
|
|
19999
|
+
code: "client_id_required",
|
|
20000
|
+
errorKind: "client_id_required"
|
|
20001
|
+
});
|
|
20002
|
+
return false;
|
|
20003
|
+
}
|
|
20004
|
+
__name(requireSessionArtifactClientId, "requireSessionArtifactClientId");
|
|
20005
|
+
function sendArtifactValidationError(res, err) {
|
|
20006
|
+
if (!(err instanceof SessionArtifactValidationError)) {
|
|
20007
|
+
return false;
|
|
20008
|
+
}
|
|
20009
|
+
res.status(400).json({
|
|
20010
|
+
v: 1,
|
|
20011
|
+
error: {
|
|
20012
|
+
code: err.code,
|
|
20013
|
+
message: err.message,
|
|
20014
|
+
...err.field ? { field: err.field } : {}
|
|
20015
|
+
}
|
|
20016
|
+
});
|
|
20017
|
+
return true;
|
|
20018
|
+
}
|
|
20019
|
+
__name(sendArtifactValidationError, "sendArtifactValidationError");
|
|
20020
|
+
function sendSessionOrganizationError(res, err) {
|
|
20021
|
+
if (!(err instanceof SessionOrganizationError)) {
|
|
20022
|
+
return false;
|
|
20023
|
+
}
|
|
20024
|
+
const status = err.code === "group_name_conflict" ? 409 : err.code === "group_not_found" ? 404 : err.code === "session_organization_store_unreadable" ? 500 : 400;
|
|
20025
|
+
res.status(status).json({
|
|
20026
|
+
error: err.message,
|
|
20027
|
+
code: err.code,
|
|
20028
|
+
...err.field !== void 0 ? { field: err.field } : {}
|
|
20029
|
+
});
|
|
20030
|
+
return true;
|
|
20031
|
+
}
|
|
20032
|
+
__name(sendSessionOrganizationError, "sendSessionOrganizationError");
|
|
20033
|
+
function parseTranscriptLimitQuery(rawLimit, res) {
|
|
20034
|
+
if (rawLimit === void 0) return void 0;
|
|
20035
|
+
if (typeof rawLimit !== "string" || rawLimit.trim() === "") {
|
|
20036
|
+
res.status(400).json({
|
|
20037
|
+
error: "`limit` must be a positive integer",
|
|
20038
|
+
code: "invalid_transcript_limit"
|
|
20039
|
+
});
|
|
20040
|
+
return null;
|
|
20041
|
+
}
|
|
20042
|
+
if (!/^\d+$/.test(rawLimit)) {
|
|
20043
|
+
res.status(400).json({
|
|
20044
|
+
error: "`limit` must be a positive integer",
|
|
20045
|
+
code: "invalid_transcript_limit"
|
|
19228
20046
|
});
|
|
19229
20047
|
return null;
|
|
19230
20048
|
}
|
|
@@ -19334,7 +20152,8 @@ function registerSessionRoutes(app, deps) {
|
|
|
19334
20152
|
sendBridgeError: sendBridgeError2,
|
|
19335
20153
|
daemonLog,
|
|
19336
20154
|
promptDeadlineMs,
|
|
19337
|
-
sessionShellCommandEnabled
|
|
20155
|
+
sessionShellCommandEnabled,
|
|
20156
|
+
virtualSubagentSessions
|
|
19338
20157
|
} = deps;
|
|
19339
20158
|
const LANGUAGE_CODES = deps.languageCodes;
|
|
19340
20159
|
const transcriptCursorMasterKey = crypto3.randomBytes(32);
|
|
@@ -19433,7 +20252,7 @@ function registerSessionRoutes(app, deps) {
|
|
|
19433
20252
|
const workspaceParam = req.params[paramName] ?? "";
|
|
19434
20253
|
const byId = workspaceRegistry.getByWorkspaceId(workspaceParam);
|
|
19435
20254
|
if (byId) return byId;
|
|
19436
|
-
if (!
|
|
20255
|
+
if (!path10.isAbsolute(workspaceParam)) {
|
|
19437
20256
|
res.status(400).json({
|
|
19438
20257
|
error: `\`:${paramName}\` must decode to a workspace id or absolute path`
|
|
19439
20258
|
});
|
|
@@ -19847,7 +20666,7 @@ function registerSessionRoutes(app, deps) {
|
|
|
19847
20666
|
})), "serializeSessionErrors");
|
|
19848
20667
|
const resolveWorkspaceParam = /* @__PURE__ */ __name((req, res) => {
|
|
19849
20668
|
const workspaceCwd = req.params["id"] ?? "";
|
|
19850
|
-
if (!
|
|
20669
|
+
if (!path10.isAbsolute(workspaceCwd)) {
|
|
19851
20670
|
res.status(400).json({ error: "`:id` must decode to an absolute workspace path" });
|
|
19852
20671
|
return null;
|
|
19853
20672
|
}
|
|
@@ -19919,6 +20738,68 @@ function registerSessionRoutes(app, deps) {
|
|
|
19919
20738
|
}
|
|
19920
20739
|
const clientId = parseClientIdHeader(req, res);
|
|
19921
20740
|
if (clientId === null) return;
|
|
20741
|
+
let worktreeMeta;
|
|
20742
|
+
const rawWorktree = body["worktree"];
|
|
20743
|
+
if (rawWorktree !== void 0 && rawWorktree !== null) {
|
|
20744
|
+
if (typeof rawWorktree !== "object" || Array.isArray(rawWorktree)) {
|
|
20745
|
+
res.status(400).json({
|
|
20746
|
+
error: '`worktree` must be an object (e.g. `{}` or `{"slug":"my-task"}`)',
|
|
20747
|
+
code: "invalid_worktree"
|
|
20748
|
+
});
|
|
20749
|
+
return;
|
|
20750
|
+
}
|
|
20751
|
+
const wtReq = rawWorktree;
|
|
20752
|
+
let wtService;
|
|
20753
|
+
try {
|
|
20754
|
+
wtService = new GitWorktreeService(workspaceCwd);
|
|
20755
|
+
} catch {
|
|
20756
|
+
res.status(500).json({
|
|
20757
|
+
error: "Failed to initialize worktree service",
|
|
20758
|
+
code: "worktree_init_failed"
|
|
20759
|
+
});
|
|
20760
|
+
return;
|
|
20761
|
+
}
|
|
20762
|
+
if (!await wtService.isGitRepository()) {
|
|
20763
|
+
res.status(400).json({
|
|
20764
|
+
error: "Worktree isolation requires a git repository",
|
|
20765
|
+
code: "worktree_not_git_repo"
|
|
20766
|
+
});
|
|
20767
|
+
return;
|
|
20768
|
+
}
|
|
20769
|
+
const rawSlug = wtReq["slug"];
|
|
20770
|
+
let slug;
|
|
20771
|
+
if (rawSlug === void 0 || rawSlug === null) {
|
|
20772
|
+
slug = GitWorktreeService.generateAutoSlug();
|
|
20773
|
+
} else if (typeof rawSlug !== "string" || rawSlug.length === 0) {
|
|
20774
|
+
res.status(400).json({
|
|
20775
|
+
error: "`worktree.slug` must be a non-empty string when provided",
|
|
20776
|
+
code: "worktree_invalid_slug"
|
|
20777
|
+
});
|
|
20778
|
+
return;
|
|
20779
|
+
} else {
|
|
20780
|
+
slug = rawSlug;
|
|
20781
|
+
}
|
|
20782
|
+
const slugError = GitWorktreeService.validateUserWorktreeSlug(slug);
|
|
20783
|
+
if (slugError) {
|
|
20784
|
+
res.status(400).json({ error: slugError, code: "worktree_invalid_slug" });
|
|
20785
|
+
return;
|
|
20786
|
+
}
|
|
20787
|
+
const baseBranch = await wtService.getCurrentBranch().catch(() => void 0);
|
|
20788
|
+
const wtResult = await wtService.createUserWorktree(slug, baseBranch);
|
|
20789
|
+
if (!wtResult.success || !wtResult.worktree) {
|
|
20790
|
+
res.status(500).json({
|
|
20791
|
+
error: wtResult.error ?? "Failed to create worktree",
|
|
20792
|
+
code: "worktree_create_failed"
|
|
20793
|
+
});
|
|
20794
|
+
return;
|
|
20795
|
+
}
|
|
20796
|
+
worktreeMeta = {
|
|
20797
|
+
slug,
|
|
20798
|
+
path: wtResult.worktree.path,
|
|
20799
|
+
branch: wtResult.worktree.branch
|
|
20800
|
+
};
|
|
20801
|
+
sessionScope = "thread";
|
|
20802
|
+
}
|
|
19922
20803
|
try {
|
|
19923
20804
|
const session = await runtime.bridge.spawnOrAttach({
|
|
19924
20805
|
workspaceCwd,
|
|
@@ -19927,7 +20808,8 @@ function registerSessionRoutes(app, deps) {
|
|
|
19927
20808
|
...sessionScope !== void 0 ? { sessionScope } : {},
|
|
19928
20809
|
...approvalMode !== void 0 ? { approvalMode } : {},
|
|
19929
20810
|
...source.sourceType !== void 0 ? { sourceType: source.sourceType } : {},
|
|
19930
|
-
...source.sourceId !== void 0 ? { sourceId: source.sourceId } : {}
|
|
20811
|
+
...source.sourceId !== void 0 ? { sourceId: source.sourceId } : {},
|
|
20812
|
+
...worktreeMeta ? { worktree: worktreeMeta } : {}
|
|
19931
20813
|
});
|
|
19932
20814
|
if (daemonLog) {
|
|
19933
20815
|
daemonLog.info(
|
|
@@ -19954,6 +20836,10 @@ function registerSessionRoutes(app, deps) {
|
|
|
19954
20836
|
await new SessionService(runtime.workspaceCwd).removeSession(
|
|
19955
20837
|
session.sessionId
|
|
19956
20838
|
);
|
|
20839
|
+
if (worktreeMeta) {
|
|
20840
|
+
await new GitWorktreeService(workspaceCwd).removeUserWorktree(worktreeMeta.slug, { deleteBranch: true }).catch(() => {
|
|
20841
|
+
});
|
|
20842
|
+
}
|
|
19957
20843
|
}
|
|
19958
20844
|
} catch {
|
|
19959
20845
|
}
|
|
@@ -19963,14 +20849,128 @@ function registerSessionRoutes(app, deps) {
|
|
|
19963
20849
|
}
|
|
19964
20850
|
return;
|
|
19965
20851
|
}
|
|
20852
|
+
if (worktreeMeta) {
|
|
20853
|
+
try {
|
|
20854
|
+
const createAllowedRoots = [
|
|
20855
|
+
path10.join(workspaceCwd, ".qwen", "worktrees")
|
|
20856
|
+
];
|
|
20857
|
+
let createRepoTop = null;
|
|
20858
|
+
try {
|
|
20859
|
+
createRepoTop = await new GitWorktreeService(
|
|
20860
|
+
workspaceCwd
|
|
20861
|
+
).getRepoTopLevel();
|
|
20862
|
+
} catch {
|
|
20863
|
+
}
|
|
20864
|
+
if (createRepoTop && createRepoTop !== workspaceCwd) {
|
|
20865
|
+
createAllowedRoots.push(
|
|
20866
|
+
path10.join(createRepoTop, ".qwen", "worktrees")
|
|
20867
|
+
);
|
|
20868
|
+
}
|
|
20869
|
+
await runtime.bridge.changeSessionCwd(session.sessionId, {
|
|
20870
|
+
path: worktreeMeta.path,
|
|
20871
|
+
allowedRoots: createAllowedRoots
|
|
20872
|
+
});
|
|
20873
|
+
await writeWorktreeSessionMarker(
|
|
20874
|
+
worktreeMeta.path,
|
|
20875
|
+
session.sessionId
|
|
20876
|
+
).catch(() => {
|
|
20877
|
+
});
|
|
20878
|
+
await writeWorktreeSession(
|
|
20879
|
+
new SessionService(workspaceCwd).getWorktreeSessionPath(
|
|
20880
|
+
session.sessionId
|
|
20881
|
+
),
|
|
20882
|
+
{
|
|
20883
|
+
slug: worktreeMeta.slug,
|
|
20884
|
+
worktreePath: worktreeMeta.path,
|
|
20885
|
+
worktreeBranch: worktreeMeta.branch,
|
|
20886
|
+
originalCwd: workspaceCwd,
|
|
20887
|
+
originalBranch: "",
|
|
20888
|
+
originalHeadCommit: ""
|
|
20889
|
+
}
|
|
20890
|
+
).catch(() => {
|
|
20891
|
+
});
|
|
20892
|
+
} catch (cdErr) {
|
|
20893
|
+
if (daemonLog) {
|
|
20894
|
+
daemonLog.warn("worktree cd failed, rolling back", {
|
|
20895
|
+
sessionId: session.sessionId,
|
|
20896
|
+
error: cdErr instanceof Error ? cdErr.message : String(cdErr)
|
|
20897
|
+
});
|
|
20898
|
+
}
|
|
20899
|
+
const killed = await runtime.bridge.killSession(session.sessionId, { requireZeroAttaches: true }).catch(() => false);
|
|
20900
|
+
if (killed) {
|
|
20901
|
+
await new SessionService(workspaceCwd).removeSession(session.sessionId).catch(() => {
|
|
20902
|
+
});
|
|
20903
|
+
}
|
|
20904
|
+
await new GitWorktreeService(workspaceCwd).removeUserWorktree(worktreeMeta.slug, { deleteBranch: true }).catch(() => {
|
|
20905
|
+
});
|
|
20906
|
+
res.status(500).json({
|
|
20907
|
+
error: "Failed to relocate session into worktree",
|
|
20908
|
+
code: "worktree_relocate_failed"
|
|
20909
|
+
});
|
|
20910
|
+
return;
|
|
20911
|
+
}
|
|
20912
|
+
}
|
|
19966
20913
|
res.status(200).json(session);
|
|
19967
20914
|
} catch (err) {
|
|
20915
|
+
if (worktreeMeta) {
|
|
20916
|
+
await new GitWorktreeService(workspaceCwd).removeUserWorktree(worktreeMeta.slug, { deleteBranch: true }).catch(() => {
|
|
20917
|
+
});
|
|
20918
|
+
}
|
|
19968
20919
|
sendBridgeError2(res, err, { route: "POST /session" });
|
|
19969
20920
|
}
|
|
19970
20921
|
});
|
|
19971
20922
|
const restoreSessionHandler = /* @__PURE__ */ __name((action) => async (req, res) => {
|
|
19972
20923
|
const sessionId = requireSessionId(req, res);
|
|
19973
20924
|
if (!sessionId) return;
|
|
20925
|
+
const virtualKey = parseVirtualSubagentSessionId(sessionId);
|
|
20926
|
+
if (virtualKey) {
|
|
20927
|
+
const route2 = `POST /session/:id/${action}`;
|
|
20928
|
+
if (action !== "load") {
|
|
20929
|
+
res.status(400).json({
|
|
20930
|
+
error: `Virtual subagent sessions do not support ${action}`,
|
|
20931
|
+
code: "unsupported_action",
|
|
20932
|
+
sessionId
|
|
20933
|
+
});
|
|
20934
|
+
return;
|
|
20935
|
+
}
|
|
20936
|
+
if (!virtualSubagentSessions) {
|
|
20937
|
+
res.status(404).json({
|
|
20938
|
+
error: `No session with id "${sessionId}"`,
|
|
20939
|
+
code: "session_not_found",
|
|
20940
|
+
sessionId
|
|
20941
|
+
});
|
|
20942
|
+
return;
|
|
20943
|
+
}
|
|
20944
|
+
const runtime2 = requireSessionRuntime({
|
|
20945
|
+
sessionId: virtualKey.parentSessionId,
|
|
20946
|
+
route: route2,
|
|
20947
|
+
res,
|
|
20948
|
+
workspaceRegistry,
|
|
20949
|
+
daemonLog
|
|
20950
|
+
});
|
|
20951
|
+
if (!runtime2) return;
|
|
20952
|
+
const clientId2 = parseClientIdHeader(req, res);
|
|
20953
|
+
if (clientId2 === null) return;
|
|
20954
|
+
try {
|
|
20955
|
+
const session = await virtualSubagentSessions.load(
|
|
20956
|
+
runtime2,
|
|
20957
|
+
sessionId,
|
|
20958
|
+
clientId2
|
|
20959
|
+
);
|
|
20960
|
+
if (!session) {
|
|
20961
|
+
res.status(404).json({
|
|
20962
|
+
error: "Subagent session not found",
|
|
20963
|
+
code: "session_not_found",
|
|
20964
|
+
sessionId
|
|
20965
|
+
});
|
|
20966
|
+
return;
|
|
20967
|
+
}
|
|
20968
|
+
res.status(200).json(session);
|
|
20969
|
+
} catch (err) {
|
|
20970
|
+
sendBridgeError2(res, err, { route: route2, sessionId });
|
|
20971
|
+
}
|
|
20972
|
+
return;
|
|
20973
|
+
}
|
|
19974
20974
|
const body = safeBody(req);
|
|
19975
20975
|
const route = `POST /session/:id/${action}`;
|
|
19976
20976
|
let resolvedRuntime;
|
|
@@ -20050,6 +21050,72 @@ function registerSessionRoutes(app, deps) {
|
|
|
20050
21050
|
}
|
|
20051
21051
|
return;
|
|
20052
21052
|
}
|
|
21053
|
+
if (!session.worktree) {
|
|
21054
|
+
const sidecar = await readWorktreeSession(
|
|
21055
|
+
new SessionService(workspaceCwd).getWorktreeSessionPath(sessionId)
|
|
21056
|
+
).catch(() => null);
|
|
21057
|
+
if (sidecar) {
|
|
21058
|
+
let realTarget;
|
|
21059
|
+
const candidateRoots = [
|
|
21060
|
+
path10.join(workspaceCwd, ".qwen", "worktrees")
|
|
21061
|
+
];
|
|
21062
|
+
try {
|
|
21063
|
+
realTarget = fs4.realpathSync(sidecar.worktreePath);
|
|
21064
|
+
let repoTop = null;
|
|
21065
|
+
try {
|
|
21066
|
+
repoTop = await new GitWorktreeService(
|
|
21067
|
+
workspaceCwd
|
|
21068
|
+
).getRepoTopLevel();
|
|
21069
|
+
} catch {
|
|
21070
|
+
}
|
|
21071
|
+
if (repoTop && repoTop !== workspaceCwd) {
|
|
21072
|
+
candidateRoots.push(path10.join(repoTop, ".qwen", "worktrees"));
|
|
21073
|
+
}
|
|
21074
|
+
const contained = candidateRoots.some((root) => {
|
|
21075
|
+
try {
|
|
21076
|
+
const realRoot = fs4.realpathSync(root);
|
|
21077
|
+
const rel = path10.relative(realRoot, realTarget);
|
|
21078
|
+
return !rel.startsWith("..") && !path10.isAbsolute(rel);
|
|
21079
|
+
} catch {
|
|
21080
|
+
return false;
|
|
21081
|
+
}
|
|
21082
|
+
});
|
|
21083
|
+
if (!contained) {
|
|
21084
|
+
realTarget = void 0;
|
|
21085
|
+
}
|
|
21086
|
+
} catch {
|
|
21087
|
+
realTarget = void 0;
|
|
21088
|
+
}
|
|
21089
|
+
if (!realTarget) {
|
|
21090
|
+
daemonLog?.warn("worktree sidecar path failed containment", {
|
|
21091
|
+
sessionId,
|
|
21092
|
+
path: sidecar.worktreePath
|
|
21093
|
+
});
|
|
21094
|
+
} else {
|
|
21095
|
+
const wt = {
|
|
21096
|
+
slug: sidecar.slug,
|
|
21097
|
+
path: realTarget,
|
|
21098
|
+
branch: sidecar.worktreeBranch
|
|
21099
|
+
};
|
|
21100
|
+
try {
|
|
21101
|
+
if (!session.hasActivePrompt) {
|
|
21102
|
+
await runtime.bridge.changeSessionCwd(sessionId, {
|
|
21103
|
+
path: wt.path,
|
|
21104
|
+
allowedRoots: candidateRoots
|
|
21105
|
+
});
|
|
21106
|
+
}
|
|
21107
|
+
runtime.bridge.setSessionWorktree(sessionId, wt);
|
|
21108
|
+
session.worktree = wt;
|
|
21109
|
+
} catch (restoreErr) {
|
|
21110
|
+
daemonLog?.warn("worktree restore failed on load/resume", {
|
|
21111
|
+
sessionId,
|
|
21112
|
+
worktreePath: wt.path,
|
|
21113
|
+
error: restoreErr instanceof Error ? restoreErr.message : String(restoreErr)
|
|
21114
|
+
});
|
|
21115
|
+
}
|
|
21116
|
+
}
|
|
21117
|
+
}
|
|
21118
|
+
}
|
|
20053
21119
|
res.status(200).json(session);
|
|
20054
21120
|
} catch (err) {
|
|
20055
21121
|
sendBridgeError2(res, err, {
|
|
@@ -20062,6 +21128,112 @@ function registerSessionRoutes(app, deps) {
|
|
|
20062
21128
|
}, "restoreSessionHandler");
|
|
20063
21129
|
app.post("/session/:id/load", mutate(), restoreSessionHandler("load"));
|
|
20064
21130
|
app.post("/session/:id/resume", mutate(), restoreSessionHandler("resume"));
|
|
21131
|
+
app.get("/session/:id/subagents/:toolCallId", async (req, res) => {
|
|
21132
|
+
const route = "GET /session/:id/subagents/:toolCallId";
|
|
21133
|
+
const sessionId = requireSessionId(req, res);
|
|
21134
|
+
if (!sessionId) return;
|
|
21135
|
+
if (!virtualSubagentSessions) {
|
|
21136
|
+
res.status(404).json({
|
|
21137
|
+
error: `No session with id "${sessionId}"`,
|
|
21138
|
+
code: "session_not_found",
|
|
21139
|
+
sessionId
|
|
21140
|
+
});
|
|
21141
|
+
return;
|
|
21142
|
+
}
|
|
21143
|
+
const toolCallId = req.params["toolCallId"];
|
|
21144
|
+
if (!toolCallId || toolCallId.length > 500) {
|
|
21145
|
+
res.status(400).json({
|
|
21146
|
+
error: "`toolCallId` must be a non-empty tool call id",
|
|
21147
|
+
code: "invalid_tool_call_id"
|
|
21148
|
+
});
|
|
21149
|
+
return;
|
|
21150
|
+
}
|
|
21151
|
+
const runtime = requireSessionRuntime({
|
|
21152
|
+
sessionId,
|
|
21153
|
+
route,
|
|
21154
|
+
res,
|
|
21155
|
+
workspaceRegistry,
|
|
21156
|
+
daemonLog
|
|
21157
|
+
});
|
|
21158
|
+
if (!runtime) return;
|
|
21159
|
+
try {
|
|
21160
|
+
const resolved = await virtualSubagentSessions.resolve(
|
|
21161
|
+
runtime,
|
|
21162
|
+
sessionId,
|
|
21163
|
+
toolCallId
|
|
21164
|
+
);
|
|
21165
|
+
if (!resolved) {
|
|
21166
|
+
res.status(404).json({
|
|
21167
|
+
error: "Subagent session not found",
|
|
21168
|
+
code: "session_not_found",
|
|
21169
|
+
sessionId,
|
|
21170
|
+
toolCallId
|
|
21171
|
+
});
|
|
21172
|
+
return;
|
|
21173
|
+
}
|
|
21174
|
+
res.status(200).set("Cache-Control", "no-store").json(resolved);
|
|
21175
|
+
} catch (err) {
|
|
21176
|
+
sendBridgeError2(res, err, { route, sessionId });
|
|
21177
|
+
}
|
|
21178
|
+
});
|
|
21179
|
+
app.post(
|
|
21180
|
+
"/session/:id/subagents/:toolCallId/cancel",
|
|
21181
|
+
mutate(),
|
|
21182
|
+
async (req, res) => {
|
|
21183
|
+
const route = "POST /session/:id/subagents/:toolCallId/cancel";
|
|
21184
|
+
const sessionId = requireSessionId(req, res);
|
|
21185
|
+
if (!sessionId) return;
|
|
21186
|
+
if (!virtualSubagentSessions) {
|
|
21187
|
+
res.status(404).json({
|
|
21188
|
+
error: `No session with id "${sessionId}"`,
|
|
21189
|
+
code: "session_not_found",
|
|
21190
|
+
sessionId
|
|
21191
|
+
});
|
|
21192
|
+
return;
|
|
21193
|
+
}
|
|
21194
|
+
const toolCallId = req.params["toolCallId"];
|
|
21195
|
+
if (!toolCallId || toolCallId.length > 500) {
|
|
21196
|
+
res.status(400).json({
|
|
21197
|
+
error: "`toolCallId` must be a non-empty tool call id",
|
|
21198
|
+
code: "invalid_tool_call_id"
|
|
21199
|
+
});
|
|
21200
|
+
return;
|
|
21201
|
+
}
|
|
21202
|
+
const runtime = requireSessionRuntime({
|
|
21203
|
+
sessionId,
|
|
21204
|
+
route,
|
|
21205
|
+
res,
|
|
21206
|
+
workspaceRegistry,
|
|
21207
|
+
daemonLog
|
|
21208
|
+
});
|
|
21209
|
+
if (!runtime) return;
|
|
21210
|
+
try {
|
|
21211
|
+
const resolved = await virtualSubagentSessions.resolve(
|
|
21212
|
+
runtime,
|
|
21213
|
+
sessionId,
|
|
21214
|
+
toolCallId
|
|
21215
|
+
);
|
|
21216
|
+
if (!resolved) {
|
|
21217
|
+
res.status(404).json({
|
|
21218
|
+
error: "Subagent session not found",
|
|
21219
|
+
code: "session_not_found",
|
|
21220
|
+
sessionId,
|
|
21221
|
+
toolCallId
|
|
21222
|
+
});
|
|
21223
|
+
return;
|
|
21224
|
+
}
|
|
21225
|
+
res.status(200).json(
|
|
21226
|
+
await runtime.bridge.cancelSessionTask(
|
|
21227
|
+
sessionId,
|
|
21228
|
+
resolved.taskId,
|
|
21229
|
+
"agent"
|
|
21230
|
+
)
|
|
21231
|
+
);
|
|
21232
|
+
} catch (err) {
|
|
21233
|
+
sendBridgeError2(res, err, { route, sessionId });
|
|
21234
|
+
}
|
|
21235
|
+
}
|
|
21236
|
+
);
|
|
20065
21237
|
app.post(
|
|
20066
21238
|
"/session/:id/branch",
|
|
20067
21239
|
mutate(),
|
|
@@ -20131,7 +21303,7 @@ function registerSessionRoutes(app, deps) {
|
|
|
20131
21303
|
async (req, res, sessionId) => {
|
|
20132
21304
|
const body = safeBody(req);
|
|
20133
21305
|
const targetPath = body["path"];
|
|
20134
|
-
if (typeof targetPath !== "string" || targetPath.length === 0 || !
|
|
21306
|
+
if (typeof targetPath !== "string" || targetPath.length === 0 || !path10.isAbsolute(targetPath)) {
|
|
20135
21307
|
res.status(400).json({
|
|
20136
21308
|
error: "`path` is required and must be an absolute path",
|
|
20137
21309
|
code: "invalid_path"
|
|
@@ -20361,6 +21533,28 @@ function registerSessionRoutes(app, deps) {
|
|
|
20361
21533
|
});
|
|
20362
21534
|
app.get(
|
|
20363
21535
|
"/session/:id/context",
|
|
21536
|
+
(req, res, next) => {
|
|
21537
|
+
const sessionId = req.params["id"];
|
|
21538
|
+
const key = sessionId ? parseVirtualSubagentSessionId(sessionId) : void 0;
|
|
21539
|
+
if (!sessionId || !key) {
|
|
21540
|
+
next();
|
|
21541
|
+
return;
|
|
21542
|
+
}
|
|
21543
|
+
const runtime = requireSessionRuntime({
|
|
21544
|
+
sessionId: key.parentSessionId,
|
|
21545
|
+
route: "GET /session/:id/context",
|
|
21546
|
+
res,
|
|
21547
|
+
workspaceRegistry,
|
|
21548
|
+
daemonLog
|
|
21549
|
+
});
|
|
21550
|
+
if (!runtime) return;
|
|
21551
|
+
res.status(200).json({
|
|
21552
|
+
v: 1,
|
|
21553
|
+
sessionId,
|
|
21554
|
+
workspaceCwd: runtime.workspaceCwd,
|
|
21555
|
+
state: {}
|
|
21556
|
+
});
|
|
21557
|
+
},
|
|
20364
21558
|
withOwnerReadSession(
|
|
20365
21559
|
"GET /session/:id/context",
|
|
20366
21560
|
async (_req, res, sessionId, runtime) => {
|
|
@@ -20392,6 +21586,28 @@ function registerSessionRoutes(app, deps) {
|
|
|
20392
21586
|
);
|
|
20393
21587
|
app.get(
|
|
20394
21588
|
"/session/:id/supported-commands",
|
|
21589
|
+
(req, res, next) => {
|
|
21590
|
+
const sessionId = req.params["id"];
|
|
21591
|
+
const key = sessionId ? parseVirtualSubagentSessionId(sessionId) : void 0;
|
|
21592
|
+
if (!sessionId || !key) {
|
|
21593
|
+
next();
|
|
21594
|
+
return;
|
|
21595
|
+
}
|
|
21596
|
+
const runtime = requireSessionRuntime({
|
|
21597
|
+
sessionId: key.parentSessionId,
|
|
21598
|
+
route: "GET /session/:id/supported-commands",
|
|
21599
|
+
res,
|
|
21600
|
+
workspaceRegistry,
|
|
21601
|
+
daemonLog
|
|
21602
|
+
});
|
|
21603
|
+
if (!runtime) return;
|
|
21604
|
+
res.status(200).json({
|
|
21605
|
+
v: 1,
|
|
21606
|
+
sessionId,
|
|
21607
|
+
availableCommands: [],
|
|
21608
|
+
availableSkills: []
|
|
21609
|
+
});
|
|
21610
|
+
},
|
|
20395
21611
|
withOwnerReadSession(
|
|
20396
21612
|
"GET /session/:id/supported-commands",
|
|
20397
21613
|
async (_req, res, sessionId, runtime) => {
|
|
@@ -20633,15 +21849,6 @@ function registerSessionRoutes(app, deps) {
|
|
|
20633
21849
|
promptDeadlineMs,
|
|
20634
21850
|
requestDeadlineMs
|
|
20635
21851
|
);
|
|
20636
|
-
let deadlineTimer;
|
|
20637
|
-
if (effectiveDeadlineMs !== void 0) {
|
|
20638
|
-
deadlineTimer = setTimeout(() => {
|
|
20639
|
-
if (!abort.signal.aborted) {
|
|
20640
|
-
abort.abort(new PromptDeadlineExceededError(effectiveDeadlineMs));
|
|
20641
|
-
}
|
|
20642
|
-
}, effectiveDeadlineMs);
|
|
20643
|
-
deadlineTimer.unref();
|
|
20644
|
-
}
|
|
20645
21852
|
let promptPromise;
|
|
20646
21853
|
try {
|
|
20647
21854
|
promptPromise = ownerBridge.sendPrompt(
|
|
@@ -20654,11 +21861,11 @@ function registerSessionRoutes(app, deps) {
|
|
|
20654
21861
|
abort.signal,
|
|
20655
21862
|
{
|
|
20656
21863
|
...clientId !== void 0 ? { clientId } : {},
|
|
20657
|
-
promptId
|
|
21864
|
+
promptId,
|
|
21865
|
+
...effectiveDeadlineMs !== void 0 ? { deadlineMs: effectiveDeadlineMs } : {}
|
|
20658
21866
|
}
|
|
20659
21867
|
);
|
|
20660
21868
|
} catch (err) {
|
|
20661
|
-
if (deadlineTimer !== void 0) clearTimeout(deadlineTimer);
|
|
20662
21869
|
res.off("close", onResClose);
|
|
20663
21870
|
res.off("finish", onResFinish);
|
|
20664
21871
|
if (daemonLog && err instanceof PromptQueueFullError) {
|
|
@@ -20703,9 +21910,7 @@ function registerSessionRoutes(app, deps) {
|
|
|
20703
21910
|
);
|
|
20704
21911
|
}
|
|
20705
21912
|
}
|
|
20706
|
-
).
|
|
20707
|
-
if (deadlineTimer !== void 0) clearTimeout(deadlineTimer);
|
|
20708
|
-
}).catch(() => {
|
|
21913
|
+
).catch(() => {
|
|
20709
21914
|
});
|
|
20710
21915
|
if (daemonLog) {
|
|
20711
21916
|
daemonLog.info("prompt enqueued", { sessionId, promptId, clientId });
|
|
@@ -20799,6 +22004,29 @@ function registerSessionRoutes(app, deps) {
|
|
|
20799
22004
|
app.post(
|
|
20800
22005
|
"/session/:id/heartbeat",
|
|
20801
22006
|
mutate(),
|
|
22007
|
+
(req, res, next) => {
|
|
22008
|
+
const sessionId = req.params["id"];
|
|
22009
|
+
const key = sessionId ? parseVirtualSubagentSessionId(sessionId) : void 0;
|
|
22010
|
+
if (!sessionId || !key) {
|
|
22011
|
+
next();
|
|
22012
|
+
return;
|
|
22013
|
+
}
|
|
22014
|
+
const runtime = requireSessionRuntime({
|
|
22015
|
+
sessionId: key.parentSessionId,
|
|
22016
|
+
route: "POST /session/:id/heartbeat",
|
|
22017
|
+
res,
|
|
22018
|
+
workspaceRegistry,
|
|
22019
|
+
daemonLog
|
|
22020
|
+
});
|
|
22021
|
+
if (!runtime) return;
|
|
22022
|
+
const clientId = parseClientIdHeader(req, res);
|
|
22023
|
+
if (clientId === null) return;
|
|
22024
|
+
res.status(200).json({
|
|
22025
|
+
sessionId,
|
|
22026
|
+
...clientId ? { clientId } : {},
|
|
22027
|
+
lastSeenAt: Date.now()
|
|
22028
|
+
});
|
|
22029
|
+
},
|
|
20802
22030
|
withOwnerMutableSession(
|
|
20803
22031
|
"POST /session/:id/heartbeat",
|
|
20804
22032
|
(req, res, sessionId, runtime) => {
|
|
@@ -20815,6 +22043,25 @@ function registerSessionRoutes(app, deps) {
|
|
|
20815
22043
|
app.post(
|
|
20816
22044
|
"/session/:id/detach",
|
|
20817
22045
|
mutate(),
|
|
22046
|
+
(req, res, next) => {
|
|
22047
|
+
const sessionId = req.params["id"];
|
|
22048
|
+
const key = sessionId ? parseVirtualSubagentSessionId(sessionId) : void 0;
|
|
22049
|
+
if (!sessionId || !key) {
|
|
22050
|
+
next();
|
|
22051
|
+
return;
|
|
22052
|
+
}
|
|
22053
|
+
const runtime = requireSessionRuntime({
|
|
22054
|
+
sessionId: key.parentSessionId,
|
|
22055
|
+
route: "POST /session/:id/detach",
|
|
22056
|
+
res,
|
|
22057
|
+
workspaceRegistry,
|
|
22058
|
+
daemonLog
|
|
22059
|
+
});
|
|
22060
|
+
if (!runtime) return;
|
|
22061
|
+
const clientId = parseClientIdHeader(req, res);
|
|
22062
|
+
if (clientId === null) return;
|
|
22063
|
+
res.status(204).end();
|
|
22064
|
+
},
|
|
20818
22065
|
withOwnerMutableSession(
|
|
20819
22066
|
"POST /session/:id/detach",
|
|
20820
22067
|
async (req, res, sessionId, runtime) => {
|
|
@@ -22578,7 +23825,7 @@ __name(registerUsageStatsRoutes, "registerUsageStatsRoutes");
|
|
|
22578
23825
|
// packages/cli/src/serve/scheduled-task-keepalive.ts
|
|
22579
23826
|
init_esbuild_shims();
|
|
22580
23827
|
import * as fsSync from "node:fs";
|
|
22581
|
-
import * as
|
|
23828
|
+
import * as path11 from "node:path";
|
|
22582
23829
|
var log = createDebugLogger("SCHED_KEEPALIVE");
|
|
22583
23830
|
function collectBoundSessionIds(tasks) {
|
|
22584
23831
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -22789,8 +24036,8 @@ function startScheduledTaskKeepalive(opts) {
|
|
|
22789
24036
|
timer.unref?.();
|
|
22790
24037
|
let bindDebounce;
|
|
22791
24038
|
const cronFilePath = getCronFilePath(boundWorkspace);
|
|
22792
|
-
const cronDir =
|
|
22793
|
-
const cronFileName =
|
|
24039
|
+
const cronDir = path11.dirname(cronFilePath);
|
|
24040
|
+
const cronFileName = path11.basename(cronFilePath);
|
|
22794
24041
|
let fileWatcher;
|
|
22795
24042
|
try {
|
|
22796
24043
|
fsSync.mkdirSync(cronDir, { recursive: true });
|
|
@@ -22881,7 +24128,7 @@ async function rehydrateScheduledTaskSessions(deps) {
|
|
|
22881
24128
|
}
|
|
22882
24129
|
__name(rehydrateScheduledTaskSessions, "rehydrateScheduledTaskSessions");
|
|
22883
24130
|
function withTimeout(p, ms, label) {
|
|
22884
|
-
return new Promise((
|
|
24131
|
+
return new Promise((resolve6, reject) => {
|
|
22885
24132
|
const timer = setTimeout(() => {
|
|
22886
24133
|
reject(new Error(`${label} timed out after ${ms}ms`));
|
|
22887
24134
|
}, ms);
|
|
@@ -22889,7 +24136,7 @@ function withTimeout(p, ms, label) {
|
|
|
22889
24136
|
p.then(
|
|
22890
24137
|
(v) => {
|
|
22891
24138
|
clearTimeout(timer);
|
|
22892
|
-
|
|
24139
|
+
resolve6(v);
|
|
22893
24140
|
},
|
|
22894
24141
|
(e) => {
|
|
22895
24142
|
clearTimeout(timer);
|
|
@@ -22973,7 +24220,7 @@ function registerWorkspaceStatusRoutes(app, deps) {
|
|
|
22973
24220
|
const ctx = buildWorkspaceCtx("POST /workspace/acp/preheat");
|
|
22974
24221
|
const timeoutMsRaw = req.query["timeoutMs"];
|
|
22975
24222
|
const timeoutMs = typeof timeoutMsRaw === "string" && timeoutMsRaw.trim() ? Number(timeoutMsRaw) : void 0;
|
|
22976
|
-
if (
|
|
24223
|
+
if (timeoutMsRaw !== void 0 && (timeoutMs === void 0 || !Number.isFinite(timeoutMs) || !Number.isInteger(timeoutMs) || timeoutMs <= 0 || timeoutMs > MAX_ACP_PREHEAT_TIMEOUT_MS)) {
|
|
22977
24224
|
res.status(400).json({
|
|
22978
24225
|
error: "`timeoutMs` must be a positive integer no greater than 60000",
|
|
22979
24226
|
code: "invalid_timeout"
|
|
@@ -23203,7 +24450,9 @@ function createServeFeatures(deps) {
|
|
|
23203
24450
|
channelControlAvailable,
|
|
23204
24451
|
sessionShellCommandEnabled,
|
|
23205
24452
|
multiWorkspaceSessionsEnabled,
|
|
24453
|
+
dynamicWorkspaceRegistrationAvailable,
|
|
23206
24454
|
persistentWorkspaceRegistrationAvailable,
|
|
24455
|
+
scratchWorkspaceRegistrationAvailable,
|
|
23207
24456
|
workspaceRuntimeRemovalAvailable
|
|
23208
24457
|
} = deps;
|
|
23209
24458
|
const env = deps.env ?? process.env;
|
|
@@ -23237,7 +24486,9 @@ function createServeFeatures(deps) {
|
|
|
23237
24486
|
channelReloadAvailable: channelReloadAvailable(),
|
|
23238
24487
|
channelControlAvailable,
|
|
23239
24488
|
multiWorkspaceSessionsEnabled: multiWorkspaceSessionsEnabled(),
|
|
24489
|
+
dynamicWorkspaceRegistrationAvailable,
|
|
23240
24490
|
persistentWorkspaceRegistrationAvailable,
|
|
24491
|
+
scratchWorkspaceRegistrationAvailable: scratchWorkspaceRegistrationAvailable(),
|
|
23241
24492
|
workspaceRuntimeRemovalAvailable,
|
|
23242
24493
|
acpHttpEnabled: resolveAcpHttpEnabled(),
|
|
23243
24494
|
clientMcpOverWsEnabled: opts.clientMcpOverWs === true,
|
|
@@ -23307,6 +24558,7 @@ function registerCapabilitiesRoutes(app, deps) {
|
|
|
23307
24558
|
workspaces: runtimes.map((runtime) => ({
|
|
23308
24559
|
id: runtime.workspaceId,
|
|
23309
24560
|
cwd: runtime.workspaceCwd,
|
|
24561
|
+
...runtime.displayName !== void 0 ? { displayName: runtime.displayName } : {},
|
|
23310
24562
|
primary: runtime.primary,
|
|
23311
24563
|
trusted: runtime.trusted,
|
|
23312
24564
|
...runtimeRemoval ? { removable: runtime.removable === true } : {}
|
|
@@ -23979,6 +25231,12 @@ init_esbuild_shims();
|
|
|
23979
25231
|
|
|
23980
25232
|
// packages/cli/src/serve/server/error-response.ts
|
|
23981
25233
|
init_esbuild_shims();
|
|
25234
|
+
var SESSION_WRITER_ERROR_MESSAGES = {
|
|
25235
|
+
session_writer_conflict: "This session is already open in another Qwen process.",
|
|
25236
|
+
session_writer_lost: "Write ownership for this session was lost.",
|
|
25237
|
+
session_transcript_changed: "The session transcript changed outside its active writer.",
|
|
25238
|
+
session_writer_unavailable: "Session write ownership could not be verified."
|
|
25239
|
+
};
|
|
23982
25240
|
function bridgeErrorExtraContext(ctx) {
|
|
23983
25241
|
const extra = {};
|
|
23984
25242
|
for (const [key, value] of Object.entries(ctx ?? {})) {
|
|
@@ -24031,6 +25289,14 @@ function sendPermissionVoteError(res, err, ctx, daemonLog) {
|
|
|
24031
25289
|
}
|
|
24032
25290
|
__name(sendPermissionVoteError, "sendPermissionVoteError");
|
|
24033
25291
|
function sendBridgeError(res, err, ctx, daemonLog) {
|
|
25292
|
+
if (err instanceof SessionWriterError) {
|
|
25293
|
+
res.status(err.httpStatus).json({
|
|
25294
|
+
error: err.message,
|
|
25295
|
+
code: err.errorKind,
|
|
25296
|
+
errorKind: err.errorKind
|
|
25297
|
+
});
|
|
25298
|
+
return;
|
|
25299
|
+
}
|
|
24034
25300
|
if (err instanceof WorkspaceSkillNotFoundError) {
|
|
24035
25301
|
res.status(404).json({
|
|
24036
25302
|
error: err.message,
|
|
@@ -24343,6 +25609,22 @@ function sendBridgeError(res, err, ctx, daemonLog) {
|
|
|
24343
25609
|
const data = err.data;
|
|
24344
25610
|
if (data && typeof data === "object") {
|
|
24345
25611
|
const kind = data.errorKind;
|
|
25612
|
+
if (kind === "session_writer_conflict" || kind === "session_writer_lost" || kind === "session_transcript_changed") {
|
|
25613
|
+
res.status(409).json({
|
|
25614
|
+
error: SESSION_WRITER_ERROR_MESSAGES[kind],
|
|
25615
|
+
code: kind,
|
|
25616
|
+
errorKind: kind
|
|
25617
|
+
});
|
|
25618
|
+
return;
|
|
25619
|
+
}
|
|
25620
|
+
if (kind === "session_writer_unavailable") {
|
|
25621
|
+
res.status(503).json({
|
|
25622
|
+
error: SESSION_WRITER_ERROR_MESSAGES[kind],
|
|
25623
|
+
code: kind,
|
|
25624
|
+
errorKind: kind
|
|
25625
|
+
});
|
|
25626
|
+
return;
|
|
25627
|
+
}
|
|
24346
25628
|
if (kind === "mcp_budget_would_exceed") {
|
|
24347
25629
|
const d = data;
|
|
24348
25630
|
res.status(409).json({
|
|
@@ -24544,7 +25826,7 @@ data: ${dataJson}
|
|
|
24544
25826
|
__name(formatSseFrame, "formatSseFrame");
|
|
24545
25827
|
function registerSseEventsRoutes(app, deps) {
|
|
24546
25828
|
const { workspaceRegistry, daemonLog, sendBridgeError: sendBridgeError2, writerIdleTimeoutMs } = deps;
|
|
24547
|
-
app.get("/session/:id/events", (req, res) => {
|
|
25829
|
+
app.get("/session/:id/events", async (req, res) => {
|
|
24548
25830
|
const sessionId = req.params["id"];
|
|
24549
25831
|
const lastEventId = parseLastEventId(req.headers["last-event-id"]);
|
|
24550
25832
|
const maxQueued = parseMaxQueuedQuery(req.query["maxQueued"], res);
|
|
@@ -24552,8 +25834,9 @@ function registerSseEventsRoutes(app, deps) {
|
|
|
24552
25834
|
let iter;
|
|
24553
25835
|
const abort = new AbortController();
|
|
24554
25836
|
try {
|
|
25837
|
+
const virtualKey = parseVirtualSubagentSessionId(sessionId);
|
|
24555
25838
|
const runtime = requireSessionRuntime({
|
|
24556
|
-
sessionId,
|
|
25839
|
+
sessionId: virtualKey?.parentSessionId ?? sessionId,
|
|
24557
25840
|
route: "GET /session/:id/events",
|
|
24558
25841
|
res,
|
|
24559
25842
|
workspaceRegistry,
|
|
@@ -24561,12 +25844,24 @@ function registerSseEventsRoutes(app, deps) {
|
|
|
24561
25844
|
});
|
|
24562
25845
|
if (!runtime) return;
|
|
24563
25846
|
const snapshot = req.query["snapshot"] === "1";
|
|
24564
|
-
const iterable =
|
|
25847
|
+
const iterable = virtualKey ? await deps.virtualSubagentSessions?.subscribe(runtime, sessionId, {
|
|
25848
|
+
signal: abort.signal,
|
|
25849
|
+
lastEventId,
|
|
25850
|
+
...maxQueued !== void 0 ? { maxQueued } : {}
|
|
25851
|
+
}) : runtime.bridge.subscribeEvents(sessionId, {
|
|
24565
25852
|
signal: abort.signal,
|
|
24566
25853
|
lastEventId,
|
|
24567
25854
|
...maxQueued !== void 0 ? { maxQueued } : {},
|
|
24568
25855
|
...snapshot ? { snapshot: true } : {}
|
|
24569
25856
|
});
|
|
25857
|
+
if (!iterable) {
|
|
25858
|
+
res.status(404).json({
|
|
25859
|
+
error: "Subagent session not found",
|
|
25860
|
+
code: "session_not_found",
|
|
25861
|
+
sessionId
|
|
25862
|
+
});
|
|
25863
|
+
return;
|
|
25864
|
+
}
|
|
24570
25865
|
iter = iterable[Symbol.asyncIterator]();
|
|
24571
25866
|
} catch (err) {
|
|
24572
25867
|
if (err instanceof SubscriberLimitExceededError) {
|
|
@@ -24619,9 +25914,9 @@ function registerSseEventsRoutes(app, deps) {
|
|
|
24619
25914
|
let writeChain = Promise.resolve();
|
|
24620
25915
|
const trackWriterIdle = writerIdleTimeoutMs !== void 0 && writerIdleTimeoutMs > 0;
|
|
24621
25916
|
let lastWriteAt = trackWriterIdle ? Date.now() : 0;
|
|
24622
|
-
const doWrite = /* @__PURE__ */ __name((chunk) => new Promise((
|
|
25917
|
+
const doWrite = /* @__PURE__ */ __name((chunk) => new Promise((resolve6, reject) => {
|
|
24623
25918
|
if (res.writableEnded) {
|
|
24624
|
-
|
|
25919
|
+
resolve6();
|
|
24625
25920
|
return;
|
|
24626
25921
|
}
|
|
24627
25922
|
let ok;
|
|
@@ -24633,19 +25928,19 @@ function registerSseEventsRoutes(app, deps) {
|
|
|
24633
25928
|
}
|
|
24634
25929
|
if (ok) {
|
|
24635
25930
|
if (trackWriterIdle) lastWriteAt = Date.now();
|
|
24636
|
-
|
|
25931
|
+
resolve6();
|
|
24637
25932
|
return;
|
|
24638
25933
|
}
|
|
24639
25934
|
const onDrain = /* @__PURE__ */ __name(() => {
|
|
24640
25935
|
res.off("close", onClose);
|
|
24641
25936
|
res.off("error", onError);
|
|
24642
25937
|
if (trackWriterIdle) lastWriteAt = Date.now();
|
|
24643
|
-
|
|
25938
|
+
resolve6();
|
|
24644
25939
|
}, "onDrain");
|
|
24645
25940
|
const onClose = /* @__PURE__ */ __name(() => {
|
|
24646
25941
|
res.off("drain", onDrain);
|
|
24647
25942
|
res.off("error", onError);
|
|
24648
|
-
|
|
25943
|
+
resolve6();
|
|
24649
25944
|
}, "onClose");
|
|
24650
25945
|
const onError = /* @__PURE__ */ __name((err) => {
|
|
24651
25946
|
res.off("drain", onDrain);
|
|
@@ -24974,7 +26269,7 @@ __name(registerWorkspaceModelsRoutes, "registerWorkspaceModelsRoutes");
|
|
|
24974
26269
|
// packages/cli/src/serve/routes/a2ui-action.ts
|
|
24975
26270
|
init_esbuild_shims();
|
|
24976
26271
|
import * as fsp4 from "node:fs/promises";
|
|
24977
|
-
import * as
|
|
26272
|
+
import * as path12 from "node:path";
|
|
24978
26273
|
var A2UI_MIME = "application/a2ui+json";
|
|
24979
26274
|
var ACTION_TOOL = "action";
|
|
24980
26275
|
var CALL_TIMEOUT_MS = 15e3;
|
|
@@ -24997,7 +26292,7 @@ __name(usableServerConfig, "usableServerConfig");
|
|
|
24997
26292
|
async function findFromSettingsFile(workspaceCwd) {
|
|
24998
26293
|
try {
|
|
24999
26294
|
const raw = await fsp4.readFile(
|
|
25000
|
-
|
|
26295
|
+
path12.join(workspaceCwd, ".qwen", "settings.json"),
|
|
25001
26296
|
"utf8"
|
|
25002
26297
|
);
|
|
25003
26298
|
const settings = JSON.parse(raw);
|
|
@@ -25134,7 +26429,7 @@ __name(registerA2uiActionRoutes, "registerA2uiActionRoutes");
|
|
|
25134
26429
|
|
|
25135
26430
|
// packages/cli/src/serve/server/fs-factory.ts
|
|
25136
26431
|
init_esbuild_shims();
|
|
25137
|
-
import * as
|
|
26432
|
+
import * as path13 from "node:path";
|
|
25138
26433
|
var IDE_WORKSPACE_PATH_ENV_VAR = "QWEN_CODE_IDE_WORKSPACE_PATH";
|
|
25139
26434
|
function createDefaultFsAuditEmit() {
|
|
25140
26435
|
const WARN_EVERY = 100;
|
|
@@ -25208,14 +26503,14 @@ function parseIdeWorkspacePathEnv(value) {
|
|
|
25208
26503
|
const parsed = JSON.parse(value);
|
|
25209
26504
|
if (Array.isArray(parsed) && parsed.every((item) => typeof item === "string")) {
|
|
25210
26505
|
return parsed.filter(
|
|
25211
|
-
(workspace) => workspace.length > 0 &&
|
|
26506
|
+
(workspace) => workspace.length > 0 && path13.isAbsolute(workspace)
|
|
25212
26507
|
);
|
|
25213
26508
|
}
|
|
25214
26509
|
throw new Error("IDE workspace path JSON must be a string array");
|
|
25215
26510
|
} catch {
|
|
25216
26511
|
}
|
|
25217
26512
|
}
|
|
25218
|
-
return value.split(
|
|
26513
|
+
return value.split(path13.delimiter).filter((workspace) => workspace.length > 0 && path13.isAbsolute(workspace));
|
|
25219
26514
|
}
|
|
25220
26515
|
__name(parseIdeWorkspacePathEnv, "parseIdeWorkspacePathEnv");
|
|
25221
26516
|
function dropNestedWorkspacesPreservingPrimary(workspaces) {
|
|
@@ -25714,45 +27009,201 @@ function registerWorkspaceQualifiedLifecycleRoutes(app, deps) {
|
|
|
25714
27009
|
deps.sendBridgeError(res, err, { route });
|
|
25715
27010
|
}
|
|
25716
27011
|
}
|
|
25717
|
-
);
|
|
25718
|
-
}
|
|
25719
|
-
__name(registerWorkspaceQualifiedLifecycleRoutes, "registerWorkspaceQualifiedLifecycleRoutes");
|
|
25720
|
-
|
|
25721
|
-
// packages/cli/src/serve/routes/workspace-management.ts
|
|
25722
|
-
init_esbuild_shims();
|
|
25723
|
-
import { readdir, stat } from "node:fs/promises";
|
|
25724
|
-
import { realpathSync } from "node:fs";
|
|
25725
|
-
import { basename as basename4, dirname as dirname4, isAbsolute as isAbsolute7, join as
|
|
25726
|
-
var MAX_PATH_SUGGESTIONS = 50;
|
|
25727
|
-
function registerWorkspaceManagementRoutes(app, deps) {
|
|
25728
|
-
const {
|
|
25729
|
-
workspaceRegistry,
|
|
25730
|
-
mutate,
|
|
25731
|
-
safeBody: safeBody2,
|
|
25732
|
-
createWorkspaceRuntime,
|
|
25733
|
-
|
|
25734
|
-
|
|
25735
|
-
|
|
25736
|
-
|
|
25737
|
-
|
|
25738
|
-
|
|
25739
|
-
let
|
|
25740
|
-
|
|
25741
|
-
|
|
25742
|
-
|
|
25743
|
-
|
|
25744
|
-
|
|
25745
|
-
|
|
25746
|
-
|
|
25747
|
-
|
|
25748
|
-
|
|
25749
|
-
|
|
25750
|
-
|
|
25751
|
-
|
|
25752
|
-
|
|
25753
|
-
|
|
25754
|
-
|
|
25755
|
-
|
|
27012
|
+
);
|
|
27013
|
+
}
|
|
27014
|
+
__name(registerWorkspaceQualifiedLifecycleRoutes, "registerWorkspaceQualifiedLifecycleRoutes");
|
|
27015
|
+
|
|
27016
|
+
// packages/cli/src/serve/routes/workspace-management.ts
|
|
27017
|
+
init_esbuild_shims();
|
|
27018
|
+
import { readdir as readdir2, stat as stat2 } from "node:fs/promises";
|
|
27019
|
+
import { realpathSync as realpathSync2 } from "node:fs";
|
|
27020
|
+
import { basename as basename4, dirname as dirname4, isAbsolute as isAbsolute7, join as join8, resolve as resolve4, sep as sep3 } from "node:path";
|
|
27021
|
+
var MAX_PATH_SUGGESTIONS = 50;
|
|
27022
|
+
function registerWorkspaceManagementRoutes(app, deps) {
|
|
27023
|
+
const {
|
|
27024
|
+
workspaceRegistry,
|
|
27025
|
+
mutate,
|
|
27026
|
+
safeBody: safeBody2,
|
|
27027
|
+
createWorkspaceRuntime,
|
|
27028
|
+
managedScratchRoot,
|
|
27029
|
+
workspaceRegistrationStore,
|
|
27030
|
+
getAcpHandle,
|
|
27031
|
+
runtimeRemoval
|
|
27032
|
+
} = deps;
|
|
27033
|
+
const inFlight = /* @__PURE__ */ new Map();
|
|
27034
|
+
let sealed = false;
|
|
27035
|
+
let activeOperations = 0;
|
|
27036
|
+
let pendingScratchCreations = 0;
|
|
27037
|
+
const idleWaiters = /* @__PURE__ */ new Set();
|
|
27038
|
+
const operationStarted = /* @__PURE__ */ __name(() => {
|
|
27039
|
+
activeOperations++;
|
|
27040
|
+
}, "operationStarted");
|
|
27041
|
+
const operationFinished = /* @__PURE__ */ __name(() => {
|
|
27042
|
+
activeOperations--;
|
|
27043
|
+
if (activeOperations !== 0) return;
|
|
27044
|
+
for (const resolveIdle of idleWaiters) resolveIdle();
|
|
27045
|
+
idleWaiters.clear();
|
|
27046
|
+
}, "operationFinished");
|
|
27047
|
+
const sendSealed = /* @__PURE__ */ __name((res) => {
|
|
27048
|
+
res.status(503).json({
|
|
27049
|
+
error: "Daemon is shutting down",
|
|
27050
|
+
code: "daemon_shutting_down"
|
|
27051
|
+
});
|
|
27052
|
+
}, "sendSealed");
|
|
27053
|
+
const attachRegistrationIds = /* @__PURE__ */ __name((runtime, registrationIds) => {
|
|
27054
|
+
runtime.registrationIds ??= [];
|
|
27055
|
+
for (const registrationId of registrationIds) {
|
|
27056
|
+
if (!runtime.registrationIds.includes(registrationId)) {
|
|
27057
|
+
runtime.registrationIds.push(registrationId);
|
|
27058
|
+
}
|
|
27059
|
+
}
|
|
27060
|
+
}, "attachRegistrationIds");
|
|
27061
|
+
const restorePersistedDisplayName = /* @__PURE__ */ __name(async (runtime, canonical) => {
|
|
27062
|
+
const snapshot = await workspaceRegistrationStore.read();
|
|
27063
|
+
const storedWorkspace = snapshot.workspaces.find(
|
|
27064
|
+
(stored) => process.platform === "win32" ? stored.toLowerCase() === canonical.toLowerCase() : stored === canonical
|
|
27065
|
+
);
|
|
27066
|
+
const storedDisplayName = storedWorkspace ? snapshot.displayNames?.[workspaceRegistrationId(storedWorkspace)] : void 0;
|
|
27067
|
+
if (storedWorkspace) {
|
|
27068
|
+
attachRegistrationIds(runtime, [
|
|
27069
|
+
workspaceRegistrationId(storedWorkspace)
|
|
27070
|
+
]);
|
|
27071
|
+
}
|
|
27072
|
+
if (storedDisplayName === void 0) {
|
|
27073
|
+
delete runtime.displayName;
|
|
27074
|
+
} else {
|
|
27075
|
+
runtime.displayName = storedDisplayName;
|
|
27076
|
+
}
|
|
27077
|
+
}, "restorePersistedDisplayName");
|
|
27078
|
+
const projectedWorkspaceCount = /* @__PURE__ */ __name(() => {
|
|
27079
|
+
const cwdSet = new Set(
|
|
27080
|
+
workspaceRegistry.listManaged().map((runtime) => runtime.workspaceCwd)
|
|
27081
|
+
);
|
|
27082
|
+
for (const [cwd, operation] of inFlight) {
|
|
27083
|
+
if (operation === "addition") cwdSet.add(cwd);
|
|
27084
|
+
}
|
|
27085
|
+
return cwdSet.size + pendingScratchCreations;
|
|
27086
|
+
}, "projectedWorkspaceCount");
|
|
27087
|
+
const createScratchWorkspace = /* @__PURE__ */ __name(async (res) => {
|
|
27088
|
+
if (!createWorkspaceRuntime || !managedScratchRoot || !runtimeRemoval) {
|
|
27089
|
+
res.status(501).json({
|
|
27090
|
+
error: "Scratch workspace registration is not available",
|
|
27091
|
+
code: "scratch_not_available"
|
|
27092
|
+
});
|
|
27093
|
+
return;
|
|
27094
|
+
}
|
|
27095
|
+
if (sealed) {
|
|
27096
|
+
sendSealed(res);
|
|
27097
|
+
return;
|
|
27098
|
+
}
|
|
27099
|
+
if (workspaceRegistry.listManaged().some(
|
|
27100
|
+
(runtime2) => !isScratchRootCompatible(
|
|
27101
|
+
runtime2.workspaceCwd,
|
|
27102
|
+
managedScratchRoot.canonicalRoot
|
|
27103
|
+
)
|
|
27104
|
+
) || [...inFlight].some(
|
|
27105
|
+
([cwd, operation]) => operation === "addition" && !isScratchRootCompatible(cwd, managedScratchRoot.canonicalRoot)
|
|
27106
|
+
)) {
|
|
27107
|
+
res.status(409).json({
|
|
27108
|
+
error: "Managed scratch root conflicts with a registered workspace",
|
|
27109
|
+
code: "scratch_root_conflict"
|
|
27110
|
+
});
|
|
27111
|
+
return;
|
|
27112
|
+
}
|
|
27113
|
+
if (projectedWorkspaceCount() >= MAX_REGISTERED_WORKSPACES) {
|
|
27114
|
+
res.status(409).json({
|
|
27115
|
+
error: "Workspace registration limit reached",
|
|
27116
|
+
code: "workspace_limit_reached"
|
|
27117
|
+
});
|
|
27118
|
+
return;
|
|
27119
|
+
}
|
|
27120
|
+
pendingScratchCreations++;
|
|
27121
|
+
operationStarted();
|
|
27122
|
+
let reservationHeld = true;
|
|
27123
|
+
let canonical;
|
|
27124
|
+
let runtime;
|
|
27125
|
+
let registered = false;
|
|
27126
|
+
try {
|
|
27127
|
+
canonical = await createManagedScratchDirectory(managedScratchRoot);
|
|
27128
|
+
if (sealed) {
|
|
27129
|
+
sendSealed(res);
|
|
27130
|
+
return;
|
|
27131
|
+
}
|
|
27132
|
+
pendingScratchCreations--;
|
|
27133
|
+
reservationHeld = false;
|
|
27134
|
+
inFlight.set(canonical, "addition");
|
|
27135
|
+
const boundCwds = workspaceRegistry.listManaged().map((entry) => entry.workspaceCwd);
|
|
27136
|
+
for (const [cwd, operation] of inFlight) {
|
|
27137
|
+
if (operation === "addition" && cwd !== canonical) boundCwds.push(cwd);
|
|
27138
|
+
}
|
|
27139
|
+
if (boundCwds.some(
|
|
27140
|
+
(cwd) => !isScratchRootCompatible(cwd, managedScratchRoot.canonicalRoot) || isWithinRoot(canonical, cwd) || isWithinRoot(cwd, canonical)
|
|
27141
|
+
)) {
|
|
27142
|
+
res.status(409).json({
|
|
27143
|
+
error: "Workspace path nests with an existing workspace",
|
|
27144
|
+
code: "workspace_nested"
|
|
27145
|
+
});
|
|
27146
|
+
return;
|
|
27147
|
+
}
|
|
27148
|
+
if (sealed) {
|
|
27149
|
+
sendSealed(res);
|
|
27150
|
+
return;
|
|
27151
|
+
}
|
|
27152
|
+
runtime = await createWorkspaceRuntime(canonical, {
|
|
27153
|
+
provenance: "managed-scratch"
|
|
27154
|
+
});
|
|
27155
|
+
if (runtime.workspaceCwd !== canonical || runtime.primary || !runtime.trusted) {
|
|
27156
|
+
throw new Error(
|
|
27157
|
+
"Scratch runtime violated the managed runtime contract"
|
|
27158
|
+
);
|
|
27159
|
+
}
|
|
27160
|
+
if (sealed) {
|
|
27161
|
+
sendSealed(res);
|
|
27162
|
+
return;
|
|
27163
|
+
}
|
|
27164
|
+
workspaceRegistry.add(runtime);
|
|
27165
|
+
registered = true;
|
|
27166
|
+
try {
|
|
27167
|
+
await runtimeRemoval.runtimeAdded?.(runtime);
|
|
27168
|
+
} catch (err) {
|
|
27169
|
+
try {
|
|
27170
|
+
writeStderrLine(
|
|
27171
|
+
`qwen serve: workspace runtime adapter notification failed after registry add: ${err instanceof Error ? err.message : String(err)}`
|
|
27172
|
+
);
|
|
27173
|
+
} catch {
|
|
27174
|
+
}
|
|
27175
|
+
}
|
|
27176
|
+
res.status(201).json({
|
|
27177
|
+
id: runtime.workspaceId,
|
|
27178
|
+
cwd: runtime.workspaceCwd,
|
|
27179
|
+
primary: false,
|
|
27180
|
+
trusted: true,
|
|
27181
|
+
persisted: false
|
|
27182
|
+
});
|
|
27183
|
+
} catch (err) {
|
|
27184
|
+
writeStderrLine(
|
|
27185
|
+
`qwen serve: scratch workspace registration failed: ${err instanceof Error ? err.message : String(err)}${canonical ? `; retained directory: ${canonical}` : ""}`
|
|
27186
|
+
);
|
|
27187
|
+
if (!res.headersSent) {
|
|
27188
|
+
res.status(500).json({
|
|
27189
|
+
error: "Failed to register scratch workspace",
|
|
27190
|
+
code: "runtime_creation_failed"
|
|
27191
|
+
});
|
|
27192
|
+
}
|
|
27193
|
+
} finally {
|
|
27194
|
+
if (runtime && !registered) {
|
|
27195
|
+
await runtimeRemoval.disposeRuntime(runtime, "workspace_removed").catch(() => {
|
|
27196
|
+
try {
|
|
27197
|
+
runtime?.bridge.killAllSync();
|
|
27198
|
+
} catch {
|
|
27199
|
+
}
|
|
27200
|
+
});
|
|
27201
|
+
}
|
|
27202
|
+
if (reservationHeld) pendingScratchCreations--;
|
|
27203
|
+
if (canonical) inFlight.delete(canonical);
|
|
27204
|
+
operationFinished();
|
|
27205
|
+
}
|
|
27206
|
+
}, "createScratchWorkspace");
|
|
25756
27207
|
app.get(
|
|
25757
27208
|
"/workspace-path-suggestions",
|
|
25758
27209
|
async (req, res) => {
|
|
@@ -25780,13 +27231,13 @@ function registerWorkspaceManagementRoutes(app, deps) {
|
|
|
25780
27231
|
return;
|
|
25781
27232
|
}
|
|
25782
27233
|
const endsWithSep = prefix.endsWith("/") || process.platform === "win32" && prefix.endsWith("\\");
|
|
25783
|
-
const dir = endsWithSep ?
|
|
27234
|
+
const dir = endsWithSep ? join8(prefix, ".") : dirname4(prefix);
|
|
25784
27235
|
const filter = endsWithSep ? "" : basename4(prefix);
|
|
25785
27236
|
const filterLower = filter.toLowerCase();
|
|
25786
27237
|
const suggestions = [];
|
|
25787
27238
|
let truncated = false;
|
|
25788
27239
|
try {
|
|
25789
|
-
const entries = await
|
|
27240
|
+
const entries = await readdir2(dir, { withFileTypes: true });
|
|
25790
27241
|
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
25791
27242
|
for (const entry of entries) {
|
|
25792
27243
|
if (entry.name.startsWith(".") && !filter.startsWith(".")) continue;
|
|
@@ -25796,7 +27247,7 @@ function registerWorkspaceManagementRoutes(app, deps) {
|
|
|
25796
27247
|
let isDir = entry.isDirectory();
|
|
25797
27248
|
if (!isDir && entry.isSymbolicLink()) {
|
|
25798
27249
|
try {
|
|
25799
|
-
isDir = (await
|
|
27250
|
+
isDir = (await stat2(join8(dir, entry.name))).isDirectory();
|
|
25800
27251
|
} catch {
|
|
25801
27252
|
continue;
|
|
25802
27253
|
}
|
|
@@ -25806,7 +27257,7 @@ function registerWorkspaceManagementRoutes(app, deps) {
|
|
|
25806
27257
|
truncated = true;
|
|
25807
27258
|
break;
|
|
25808
27259
|
}
|
|
25809
|
-
suggestions.push({ name: entry.name, path:
|
|
27260
|
+
suggestions.push({ name: entry.name, path: join8(dir, entry.name) });
|
|
25810
27261
|
}
|
|
25811
27262
|
} catch {
|
|
25812
27263
|
}
|
|
@@ -25824,8 +27275,33 @@ function registerWorkspaceManagementRoutes(app, deps) {
|
|
|
25824
27275
|
mutate({ strict: true }),
|
|
25825
27276
|
async (req, res) => {
|
|
25826
27277
|
const body = safeBody2(req);
|
|
27278
|
+
if ("kind" in body) {
|
|
27279
|
+
if (body["kind"] !== "scratch" || "cwd" in body || "persist" in body || Object.keys(body).some((key) => key !== "kind")) {
|
|
27280
|
+
res.status(400).json({
|
|
27281
|
+
error: 'Scratch workspace requests must be exactly { kind: "scratch" }',
|
|
27282
|
+
code: "invalid_workspace_request"
|
|
27283
|
+
});
|
|
27284
|
+
return;
|
|
27285
|
+
}
|
|
27286
|
+
await createScratchWorkspace(res);
|
|
27287
|
+
return;
|
|
27288
|
+
}
|
|
25827
27289
|
const cwd = body["cwd"];
|
|
25828
27290
|
const persist = body["persist"] ?? false;
|
|
27291
|
+
const hasDisplayName = Object.hasOwn(body, "displayName");
|
|
27292
|
+
let displayName;
|
|
27293
|
+
if (hasDisplayName) {
|
|
27294
|
+
try {
|
|
27295
|
+
displayName = normalizeWorkspaceDisplayName(body["displayName"]);
|
|
27296
|
+
} catch (err) {
|
|
27297
|
+
if (!(err instanceof WorkspaceDisplayNameValidationError)) throw err;
|
|
27298
|
+
res.status(400).json({
|
|
27299
|
+
error: err.message,
|
|
27300
|
+
code: "invalid_display_name"
|
|
27301
|
+
});
|
|
27302
|
+
return;
|
|
27303
|
+
}
|
|
27304
|
+
}
|
|
25829
27305
|
if (typeof cwd !== "string" || cwd.trim().length === 0) {
|
|
25830
27306
|
res.status(400).json({
|
|
25831
27307
|
error: "`cwd` must be a non-empty string",
|
|
@@ -25854,23 +27330,24 @@ function registerWorkspaceManagementRoutes(app, deps) {
|
|
|
25854
27330
|
});
|
|
25855
27331
|
return;
|
|
25856
27332
|
}
|
|
25857
|
-
if (
|
|
27333
|
+
if (cwd.length > MAX_WORKSPACE_PATH_LENGTH) {
|
|
25858
27334
|
res.status(400).json({
|
|
25859
|
-
error:
|
|
27335
|
+
error: `\`cwd\` exceeds the ${MAX_WORKSPACE_PATH_LENGTH}-character limit`,
|
|
25860
27336
|
code: "invalid_path"
|
|
25861
27337
|
});
|
|
25862
27338
|
return;
|
|
25863
27339
|
}
|
|
25864
|
-
|
|
27340
|
+
const sandboxCwd = translateAndCheckAbsoluteWorkspacePath(cwd);
|
|
27341
|
+
if (sandboxCwd === null) {
|
|
25865
27342
|
res.status(400).json({
|
|
25866
|
-
error:
|
|
27343
|
+
error: "`cwd` must be an absolute path",
|
|
25867
27344
|
code: "invalid_path"
|
|
25868
27345
|
});
|
|
25869
27346
|
return;
|
|
25870
27347
|
}
|
|
25871
27348
|
let canonical;
|
|
25872
27349
|
try {
|
|
25873
|
-
canonical =
|
|
27350
|
+
canonical = realpathSync2.native(resolve4(sandboxCwd));
|
|
25874
27351
|
} catch {
|
|
25875
27352
|
res.status(400).json({
|
|
25876
27353
|
error: "Path does not exist or is not accessible",
|
|
@@ -25878,12 +27355,19 @@ function registerWorkspaceManagementRoutes(app, deps) {
|
|
|
25878
27355
|
});
|
|
25879
27356
|
return;
|
|
25880
27357
|
}
|
|
27358
|
+
if (managedScratchRoot && !isScratchRootCompatible(canonical, managedScratchRoot.canonicalRoot)) {
|
|
27359
|
+
res.status(409).json({
|
|
27360
|
+
error: "Workspace path conflicts with the managed scratch root",
|
|
27361
|
+
code: "scratch_root_conflict"
|
|
27362
|
+
});
|
|
27363
|
+
return;
|
|
27364
|
+
}
|
|
25881
27365
|
if (sealed) {
|
|
25882
27366
|
sendSealed(res);
|
|
25883
27367
|
return;
|
|
25884
27368
|
}
|
|
25885
27369
|
try {
|
|
25886
|
-
const s = await
|
|
27370
|
+
const s = await stat2(canonical);
|
|
25887
27371
|
if (!s.isDirectory()) {
|
|
25888
27372
|
res.status(400).json({
|
|
25889
27373
|
error: "Path is not a directory",
|
|
@@ -25945,11 +27429,12 @@ function registerWorkspaceManagementRoutes(app, deps) {
|
|
|
25945
27429
|
operationStarted();
|
|
25946
27430
|
try {
|
|
25947
27431
|
const snapshot = await workspaceRegistrationStore.read();
|
|
25948
|
-
const
|
|
27432
|
+
const persistedWorkspaces = snapshot.workspaces.filter(
|
|
25949
27433
|
(stored) => existingRuntime.registrationIds?.includes(
|
|
25950
27434
|
workspaceRegistrationId(stored)
|
|
25951
27435
|
) === true || (process.platform === "win32" ? stored.toLowerCase() === canonical.toLowerCase() : stored === canonical)
|
|
25952
27436
|
);
|
|
27437
|
+
const alreadyPersisted = persistedWorkspaces.length > 0;
|
|
25953
27438
|
if (!alreadyPersisted && snapshot.workspaces.length >= MAX_REGISTERED_WORKSPACES - 1) {
|
|
25954
27439
|
res.status(409).json({
|
|
25955
27440
|
error: "Workspace registration limit reached",
|
|
@@ -25957,22 +27442,56 @@ function registerWorkspaceManagementRoutes(app, deps) {
|
|
|
25957
27442
|
});
|
|
25958
27443
|
return;
|
|
25959
27444
|
}
|
|
25960
|
-
if (
|
|
27445
|
+
if (alreadyPersisted) {
|
|
27446
|
+
attachRegistrationIds(
|
|
27447
|
+
existingRuntime,
|
|
27448
|
+
persistedWorkspaces.map(workspaceRegistrationId)
|
|
27449
|
+
);
|
|
27450
|
+
const storedDisplayName = persistedWorkspaces.map(
|
|
27451
|
+
(stored) => snapshot.displayNames?.[workspaceRegistrationId(stored)]
|
|
27452
|
+
).find((name) => name !== void 0);
|
|
27453
|
+
if (storedDisplayName === void 0) {
|
|
27454
|
+
delete existingRuntime.displayName;
|
|
27455
|
+
} else {
|
|
27456
|
+
existingRuntime.displayName = storedDisplayName;
|
|
27457
|
+
}
|
|
27458
|
+
} else {
|
|
27459
|
+
let added = false;
|
|
25961
27460
|
try {
|
|
25962
|
-
|
|
27461
|
+
const persistedDisplayName = hasDisplayName ? displayName : existingRuntime.displayName;
|
|
27462
|
+
added = persistedDisplayName === void 0 ? await workspaceRegistrationStore.add(canonical) : await workspaceRegistrationStore.add(
|
|
27463
|
+
canonical,
|
|
27464
|
+
persistedDisplayName
|
|
27465
|
+
);
|
|
25963
27466
|
} catch (err) {
|
|
25964
27467
|
if (!(err instanceof WorkspaceRegistrationStoreCommittedError)) {
|
|
25965
27468
|
throw err;
|
|
25966
27469
|
}
|
|
27470
|
+
added = true;
|
|
25967
27471
|
try {
|
|
25968
27472
|
writeStderrLine(`qwen serve: ${err.message}`);
|
|
25969
27473
|
} catch {
|
|
25970
27474
|
}
|
|
25971
27475
|
}
|
|
27476
|
+
if (added) {
|
|
27477
|
+
attachRegistrationIds(existingRuntime, [
|
|
27478
|
+
workspaceRegistrationId(canonical)
|
|
27479
|
+
]);
|
|
27480
|
+
}
|
|
27481
|
+
if (added && hasDisplayName) {
|
|
27482
|
+
if (displayName === void 0) {
|
|
27483
|
+
delete existingRuntime.displayName;
|
|
27484
|
+
} else {
|
|
27485
|
+
existingRuntime.displayName = displayName;
|
|
27486
|
+
}
|
|
27487
|
+
} else if (!added) {
|
|
27488
|
+
await restorePersistedDisplayName(existingRuntime, canonical);
|
|
27489
|
+
}
|
|
25972
27490
|
}
|
|
25973
27491
|
res.status(200).json({
|
|
25974
27492
|
id: existingRuntime.workspaceId,
|
|
25975
27493
|
cwd: existingRuntime.workspaceCwd,
|
|
27494
|
+
...existingRuntime.displayName !== void 0 ? { displayName: existingRuntime.displayName } : {},
|
|
25976
27495
|
primary: existingRuntime.primary,
|
|
25977
27496
|
trusted: existingRuntime.trusted,
|
|
25978
27497
|
persisted: true
|
|
@@ -26027,13 +27546,7 @@ function registerWorkspaceManagementRoutes(app, deps) {
|
|
|
26027
27546
|
return;
|
|
26028
27547
|
}
|
|
26029
27548
|
}
|
|
26030
|
-
|
|
26031
|
-
workspaceRegistry.listManaged().map((runtime) => runtime.workspaceCwd)
|
|
26032
|
-
);
|
|
26033
|
-
for (const [cwd2, operation] of inFlight) {
|
|
26034
|
-
if (operation === "addition") projectedWorkspaceCwds.add(cwd2);
|
|
26035
|
-
}
|
|
26036
|
-
if (projectedWorkspaceCwds.size >= MAX_REGISTERED_WORKSPACES) {
|
|
27549
|
+
if (projectedWorkspaceCount() >= MAX_REGISTERED_WORKSPACES) {
|
|
26037
27550
|
res.status(409).json({
|
|
26038
27551
|
error: "Workspace registration limit reached",
|
|
26039
27552
|
code: "workspace_limit_reached"
|
|
@@ -26044,13 +27557,21 @@ function registerWorkspaceManagementRoutes(app, deps) {
|
|
|
26044
27557
|
operationStarted();
|
|
26045
27558
|
let persistenceFailed = false;
|
|
26046
27559
|
try {
|
|
26047
|
-
const runtime = await createWorkspaceRuntime(canonical
|
|
27560
|
+
const runtime = await createWorkspaceRuntime(canonical, {
|
|
27561
|
+
provenance: "existing"
|
|
27562
|
+
});
|
|
27563
|
+
if (!persist && displayName !== void 0) {
|
|
27564
|
+
runtime.displayName = displayName;
|
|
27565
|
+
}
|
|
26048
27566
|
let persistedRecordAdded = false;
|
|
26049
27567
|
try {
|
|
26050
27568
|
if (persist) {
|
|
26051
27569
|
try {
|
|
26052
27570
|
try {
|
|
26053
|
-
persistedRecordAdded = await workspaceRegistrationStore.add(canonical)
|
|
27571
|
+
persistedRecordAdded = displayName === void 0 ? await workspaceRegistrationStore.add(canonical) : await workspaceRegistrationStore.add(
|
|
27572
|
+
canonical,
|
|
27573
|
+
displayName
|
|
27574
|
+
);
|
|
26054
27575
|
} catch (err) {
|
|
26055
27576
|
if (!(err instanceof WorkspaceRegistrationStoreCommittedError)) {
|
|
26056
27577
|
throw err;
|
|
@@ -26061,6 +27582,16 @@ function registerWorkspaceManagementRoutes(app, deps) {
|
|
|
26061
27582
|
} catch {
|
|
26062
27583
|
}
|
|
26063
27584
|
}
|
|
27585
|
+
if (persistedRecordAdded) {
|
|
27586
|
+
attachRegistrationIds(runtime, [
|
|
27587
|
+
workspaceRegistrationId(canonical)
|
|
27588
|
+
]);
|
|
27589
|
+
if (displayName !== void 0) {
|
|
27590
|
+
runtime.displayName = displayName;
|
|
27591
|
+
}
|
|
27592
|
+
} else {
|
|
27593
|
+
await restorePersistedDisplayName(runtime, canonical);
|
|
27594
|
+
}
|
|
26064
27595
|
} catch (err) {
|
|
26065
27596
|
persistenceFailed = true;
|
|
26066
27597
|
throw err;
|
|
@@ -26104,6 +27635,7 @@ function registerWorkspaceManagementRoutes(app, deps) {
|
|
|
26104
27635
|
res.status(201).json({
|
|
26105
27636
|
id: runtime.workspaceId,
|
|
26106
27637
|
cwd: runtime.workspaceCwd,
|
|
27638
|
+
...runtime.displayName !== void 0 ? { displayName: runtime.displayName } : {},
|
|
26107
27639
|
primary: runtime.primary,
|
|
26108
27640
|
trusted: runtime.trusted,
|
|
26109
27641
|
...persist ? { persisted: true } : {}
|
|
@@ -26171,6 +27703,98 @@ function registerWorkspaceManagementRoutes(app, deps) {
|
|
|
26171
27703
|
});
|
|
26172
27704
|
return void 0;
|
|
26173
27705
|
}, "resolveManagedRuntime");
|
|
27706
|
+
app.patch(
|
|
27707
|
+
"/workspaces/:workspace",
|
|
27708
|
+
mutate({ strict: true }),
|
|
27709
|
+
async (req, res) => {
|
|
27710
|
+
const body = safeBody2(req);
|
|
27711
|
+
const unsupportedField = Object.keys(body).find(
|
|
27712
|
+
(field) => field !== "displayName"
|
|
27713
|
+
);
|
|
27714
|
+
if (unsupportedField) {
|
|
27715
|
+
res.status(400).json({
|
|
27716
|
+
error: `\`${unsupportedField}\` is not an updatable workspace field`,
|
|
27717
|
+
code: "unsupported_field"
|
|
27718
|
+
});
|
|
27719
|
+
return;
|
|
27720
|
+
}
|
|
27721
|
+
if (!Object.hasOwn(body, "displayName")) {
|
|
27722
|
+
res.status(400).json({
|
|
27723
|
+
error: "No updatable fields provided",
|
|
27724
|
+
code: "empty_patch"
|
|
27725
|
+
});
|
|
27726
|
+
return;
|
|
27727
|
+
}
|
|
27728
|
+
let displayName;
|
|
27729
|
+
try {
|
|
27730
|
+
displayName = body["displayName"] === null ? void 0 : normalizeWorkspaceDisplayName(body["displayName"]);
|
|
27731
|
+
} catch (err) {
|
|
27732
|
+
if (!(err instanceof WorkspaceDisplayNameValidationError)) throw err;
|
|
27733
|
+
res.status(400).json({
|
|
27734
|
+
error: err.message,
|
|
27735
|
+
code: "invalid_display_name"
|
|
27736
|
+
});
|
|
27737
|
+
return;
|
|
27738
|
+
}
|
|
27739
|
+
if (sealed) {
|
|
27740
|
+
sendSealed(res);
|
|
27741
|
+
return;
|
|
27742
|
+
}
|
|
27743
|
+
const runtime = resolveManagedRuntime(req, res);
|
|
27744
|
+
if (!runtime) return;
|
|
27745
|
+
if (inFlight.has(runtime.workspaceCwd)) {
|
|
27746
|
+
res.status(409).json({
|
|
27747
|
+
error: "Workspace registration is in progress",
|
|
27748
|
+
code: "workspace_registration_in_progress"
|
|
27749
|
+
});
|
|
27750
|
+
return;
|
|
27751
|
+
}
|
|
27752
|
+
inFlight.set(runtime.workspaceCwd, "update");
|
|
27753
|
+
operationStarted();
|
|
27754
|
+
try {
|
|
27755
|
+
if (workspaceRegistrationStore && runtime.registrationIds !== void 0 && runtime.registrationIds.length > 0) {
|
|
27756
|
+
try {
|
|
27757
|
+
await workspaceRegistrationStore.setDisplayNameByIds(
|
|
27758
|
+
runtime.registrationIds,
|
|
27759
|
+
displayName
|
|
27760
|
+
);
|
|
27761
|
+
} catch (err) {
|
|
27762
|
+
if (!(err instanceof WorkspaceRegistrationStoreCommittedError)) {
|
|
27763
|
+
throw err;
|
|
27764
|
+
}
|
|
27765
|
+
try {
|
|
27766
|
+
writeStderrLine(`qwen serve: ${err.message}`);
|
|
27767
|
+
} catch {
|
|
27768
|
+
}
|
|
27769
|
+
}
|
|
27770
|
+
}
|
|
27771
|
+
if (displayName === void 0) {
|
|
27772
|
+
delete runtime.displayName;
|
|
27773
|
+
} else {
|
|
27774
|
+
runtime.displayName = displayName;
|
|
27775
|
+
}
|
|
27776
|
+
res.status(200).json({
|
|
27777
|
+
id: runtime.workspaceId,
|
|
27778
|
+
cwd: runtime.workspaceCwd,
|
|
27779
|
+
...runtime.displayName !== void 0 ? { displayName: runtime.displayName } : {},
|
|
27780
|
+
primary: runtime.primary,
|
|
27781
|
+
trusted: runtime.trusted,
|
|
27782
|
+
...runtimeRemoval ? { removable: runtime.removable === true } : {}
|
|
27783
|
+
});
|
|
27784
|
+
} catch (err) {
|
|
27785
|
+
writeStderrLine(
|
|
27786
|
+
`qwen serve: failed to persist workspace display name: ${err instanceof Error ? err.message : String(err)}`
|
|
27787
|
+
);
|
|
27788
|
+
res.status(500).json({
|
|
27789
|
+
error: "Failed to persist workspace display name",
|
|
27790
|
+
code: "workspace_registration_store_error"
|
|
27791
|
+
});
|
|
27792
|
+
} finally {
|
|
27793
|
+
inFlight.delete(runtime.workspaceCwd);
|
|
27794
|
+
operationFinished();
|
|
27795
|
+
}
|
|
27796
|
+
}
|
|
27797
|
+
);
|
|
26174
27798
|
app.delete(
|
|
26175
27799
|
"/workspaces/:workspace",
|
|
26176
27800
|
mutate({ strict: true }),
|
|
@@ -26406,11 +28030,13 @@ function registerWorkspaceManagementRoutes(app, deps) {
|
|
|
26406
28030
|
schemaVersion: snapshot.schemaVersion,
|
|
26407
28031
|
primaryWorkspace: snapshot.primaryWorkspace,
|
|
26408
28032
|
entries: snapshot.workspaces.map((cwd) => {
|
|
28033
|
+
const registrationId = workspaceRegistrationId(cwd);
|
|
26409
28034
|
const runtime = workspaceRegistry.getByWorkspaceCwd(cwd);
|
|
26410
28035
|
return {
|
|
26411
|
-
id:
|
|
28036
|
+
id: registrationId,
|
|
26412
28037
|
cwd,
|
|
26413
|
-
|
|
28038
|
+
...snapshot.displayNames?.[registrationId] !== void 0 ? { displayName: snapshot.displayNames[registrationId] } : {},
|
|
28039
|
+
active: runtime !== void 0 || registrationIsActive(registrationId),
|
|
26414
28040
|
persisted: true
|
|
26415
28041
|
};
|
|
26416
28042
|
})
|
|
@@ -26468,7 +28094,7 @@ function registerWorkspaceManagementRoutes(app, deps) {
|
|
|
26468
28094
|
}
|
|
26469
28095
|
if (storedCwd) {
|
|
26470
28096
|
try {
|
|
26471
|
-
operationCwd =
|
|
28097
|
+
operationCwd = realpathSync2.native(resolve4(storedCwd));
|
|
26472
28098
|
} catch {
|
|
26473
28099
|
operationCwd = resolve4(storedCwd);
|
|
26474
28100
|
}
|
|
@@ -26508,6 +28134,11 @@ function registerWorkspaceManagementRoutes(app, deps) {
|
|
|
26508
28134
|
});
|
|
26509
28135
|
return;
|
|
26510
28136
|
}
|
|
28137
|
+
if (runtime?.registrationIds) {
|
|
28138
|
+
runtime.registrationIds = runtime.registrationIds.filter(
|
|
28139
|
+
(id) => id !== registrationId
|
|
28140
|
+
);
|
|
28141
|
+
}
|
|
26511
28142
|
res.json({
|
|
26512
28143
|
removed: true,
|
|
26513
28144
|
active,
|
|
@@ -26539,6 +28170,8 @@ __name(registerWorkspaceManagementRoutes, "registerWorkspaceManagementRoutes");
|
|
|
26539
28170
|
|
|
26540
28171
|
// packages/cli/src/serve/routes/workspace-git.ts
|
|
26541
28172
|
init_esbuild_shims();
|
|
28173
|
+
import * as fs5 from "node:fs";
|
|
28174
|
+
import * as path14 from "node:path";
|
|
26542
28175
|
function registerWorkspaceGitRoutes(app, deps) {
|
|
26543
28176
|
app.get("/workspace/git", async (_req, res) => {
|
|
26544
28177
|
try {
|
|
@@ -26560,10 +28193,43 @@ function registerWorkspaceQualifiedGitRoutes(app, deps) {
|
|
|
26560
28193
|
const runtime = resolveTrustedRuntime2(deps.workspaceRegistry, req, res);
|
|
26561
28194
|
if (!runtime) return;
|
|
26562
28195
|
const route = "GET /workspaces/:workspace/git";
|
|
28196
|
+
const rawCwd = req.query["cwd"];
|
|
28197
|
+
let gitCwd = runtime.workspaceCwd;
|
|
28198
|
+
if (typeof rawCwd === "string" && rawCwd.length > 0) {
|
|
28199
|
+
try {
|
|
28200
|
+
const resolved = fs5.realpathSync(path14.resolve(rawCwd));
|
|
28201
|
+
const root = fs5.realpathSync(runtime.workspaceCwd);
|
|
28202
|
+
const rel = path14.relative(root, resolved);
|
|
28203
|
+
if (!rel.startsWith("..") && !path14.isAbsolute(rel)) {
|
|
28204
|
+
gitCwd = resolved;
|
|
28205
|
+
}
|
|
28206
|
+
} catch {
|
|
28207
|
+
}
|
|
28208
|
+
}
|
|
26563
28209
|
try {
|
|
26564
|
-
|
|
26565
|
-
await
|
|
26566
|
-
|
|
28210
|
+
if (gitCwd !== runtime.workspaceCwd) {
|
|
28211
|
+
const status = await getGitWorkingTreeStatus(gitCwd).catch(() => null);
|
|
28212
|
+
res.status(200).json(
|
|
28213
|
+
status ? {
|
|
28214
|
+
v: 2,
|
|
28215
|
+
workspaceCwd: gitCwd,
|
|
28216
|
+
branch: status.branch ?? null,
|
|
28217
|
+
detached: status.detached,
|
|
28218
|
+
staged: status.staged,
|
|
28219
|
+
unstaged: status.unstaged,
|
|
28220
|
+
untracked: status.untracked,
|
|
28221
|
+
conflicted: status.conflicted,
|
|
28222
|
+
hasUpstream: status.hasUpstream,
|
|
28223
|
+
ahead: status.ahead,
|
|
28224
|
+
behind: status.behind,
|
|
28225
|
+
stashCount: status.stashCount,
|
|
28226
|
+
...status.operation ? { operation: status.operation } : {},
|
|
28227
|
+
computedAt: Date.now()
|
|
28228
|
+
} : { v: 2, workspaceCwd: gitCwd, branch: null }
|
|
28229
|
+
);
|
|
28230
|
+
} else {
|
|
28231
|
+
res.status(200).json(await deps.gitState.getStatus(gitCwd, runtime.bridge));
|
|
28232
|
+
}
|
|
26567
28233
|
} catch (err) {
|
|
26568
28234
|
deps.sendBridgeError(res, err, { route });
|
|
26569
28235
|
}
|
|
@@ -26716,6 +28382,163 @@ function registerWorkspaceQualifiedGitDiffRoutes(app, deps) {
|
|
|
26716
28382
|
}
|
|
26717
28383
|
__name(registerWorkspaceQualifiedGitDiffRoutes, "registerWorkspaceQualifiedGitDiffRoutes");
|
|
26718
28384
|
|
|
28385
|
+
// packages/cli/src/serve/routes/workspace-git-log.ts
|
|
28386
|
+
init_esbuild_shims();
|
|
28387
|
+
function buildLogList(workspaceCwd, result) {
|
|
28388
|
+
if (!result) {
|
|
28389
|
+
return {
|
|
28390
|
+
v: 1,
|
|
28391
|
+
workspaceCwd,
|
|
28392
|
+
available: false,
|
|
28393
|
+
entries: [],
|
|
28394
|
+
hasMore: false
|
|
28395
|
+
};
|
|
28396
|
+
}
|
|
28397
|
+
return {
|
|
28398
|
+
v: 1,
|
|
28399
|
+
workspaceCwd,
|
|
28400
|
+
available: true,
|
|
28401
|
+
entries: result.entries.map((e) => ({
|
|
28402
|
+
sha: e.sha,
|
|
28403
|
+
shortSha: e.shortSha,
|
|
28404
|
+
authorName: e.authorName,
|
|
28405
|
+
authorEmail: e.authorEmail,
|
|
28406
|
+
authorDate: e.authorDate,
|
|
28407
|
+
subject: e.subject,
|
|
28408
|
+
...e.refs ? { refs: e.refs } : {},
|
|
28409
|
+
parents: e.parents
|
|
28410
|
+
})),
|
|
28411
|
+
hasMore: result.hasMore
|
|
28412
|
+
};
|
|
28413
|
+
}
|
|
28414
|
+
__name(buildLogList, "buildLogList");
|
|
28415
|
+
function buildCommitDetail(workspaceCwd, result) {
|
|
28416
|
+
if (!result) {
|
|
28417
|
+
return { v: 1, workspaceCwd, available: false };
|
|
28418
|
+
}
|
|
28419
|
+
return {
|
|
28420
|
+
v: 1,
|
|
28421
|
+
workspaceCwd,
|
|
28422
|
+
available: true,
|
|
28423
|
+
sha: result.sha,
|
|
28424
|
+
shortSha: result.shortSha,
|
|
28425
|
+
authorName: result.authorName,
|
|
28426
|
+
authorEmail: result.authorEmail,
|
|
28427
|
+
authorDate: result.authorDate,
|
|
28428
|
+
subject: result.subject,
|
|
28429
|
+
body: result.body,
|
|
28430
|
+
...result.refs ? { refs: result.refs } : {},
|
|
28431
|
+
parents: result.parents,
|
|
28432
|
+
files: result.files.map((f) => ({
|
|
28433
|
+
path: f.path,
|
|
28434
|
+
added: f.added,
|
|
28435
|
+
removed: f.removed,
|
|
28436
|
+
isBinary: f.isBinary
|
|
28437
|
+
})),
|
|
28438
|
+
filesCount: result.filesCount,
|
|
28439
|
+
linesAdded: result.linesAdded,
|
|
28440
|
+
linesRemoved: result.linesRemoved,
|
|
28441
|
+
hiddenCount: result.hiddenCount
|
|
28442
|
+
};
|
|
28443
|
+
}
|
|
28444
|
+
__name(buildCommitDetail, "buildCommitDetail");
|
|
28445
|
+
function parsePagination(req) {
|
|
28446
|
+
const rawLimit = req.query["limit"];
|
|
28447
|
+
const rawSkip = req.query["skip"];
|
|
28448
|
+
const parsedLimit = typeof rawLimit === "string" ? parseInt(rawLimit, 10) : NaN;
|
|
28449
|
+
const parsedSkip = typeof rawSkip === "string" ? parseInt(rawSkip, 10) : NaN;
|
|
28450
|
+
const limit = Math.min(
|
|
28451
|
+
Math.max(Number.isNaN(parsedLimit) ? DEFAULT_LOG_LIMIT : parsedLimit, 1),
|
|
28452
|
+
MAX_LOG_LIMIT
|
|
28453
|
+
);
|
|
28454
|
+
const skip = Math.max(Number.isNaN(parsedSkip) ? 0 : parsedSkip, 0);
|
|
28455
|
+
return { limit, skip };
|
|
28456
|
+
}
|
|
28457
|
+
__name(parsePagination, "parsePagination");
|
|
28458
|
+
async function handleLogList(req, res, workspaceCwd, sendBridgeError2, route) {
|
|
28459
|
+
try {
|
|
28460
|
+
applyReadHeaders(res);
|
|
28461
|
+
const { limit, skip } = parsePagination(req);
|
|
28462
|
+
const result = await fetchGitLog(workspaceCwd, { limit, skip });
|
|
28463
|
+
res.status(200).json(buildLogList(workspaceCwd, result));
|
|
28464
|
+
} catch (err) {
|
|
28465
|
+
sendBridgeError2(res, err, { route });
|
|
28466
|
+
}
|
|
28467
|
+
}
|
|
28468
|
+
__name(handleLogList, "handleLogList");
|
|
28469
|
+
async function handleCommitDetail(req, res, workspaceCwd, sendBridgeError2, route) {
|
|
28470
|
+
const sha = req.query["sha"];
|
|
28471
|
+
if (typeof sha !== "string" || sha.length === 0 || !/^[0-9a-f]{7,40}$/i.test(sha)) {
|
|
28472
|
+
applyReadHeaders(res);
|
|
28473
|
+
res.status(400).json({
|
|
28474
|
+
errorKind: "parse_error",
|
|
28475
|
+
error: "sha query parameter is required",
|
|
28476
|
+
status: 400
|
|
28477
|
+
});
|
|
28478
|
+
return;
|
|
28479
|
+
}
|
|
28480
|
+
try {
|
|
28481
|
+
applyReadHeaders(res);
|
|
28482
|
+
const result = await fetchGitCommitDetail(workspaceCwd, sha);
|
|
28483
|
+
res.status(200).json(buildCommitDetail(workspaceCwd, result));
|
|
28484
|
+
} catch (err) {
|
|
28485
|
+
sendBridgeError2(res, err, { route });
|
|
28486
|
+
}
|
|
28487
|
+
}
|
|
28488
|
+
__name(handleCommitDetail, "handleCommitDetail");
|
|
28489
|
+
function registerWorkspaceGitLogRoutes(app, deps) {
|
|
28490
|
+
app.get("/workspace/git/log", (req, res) => {
|
|
28491
|
+
void handleLogList(
|
|
28492
|
+
req,
|
|
28493
|
+
res,
|
|
28494
|
+
deps.boundWorkspace,
|
|
28495
|
+
deps.sendBridgeError,
|
|
28496
|
+
"GET /workspace/git/log"
|
|
28497
|
+
);
|
|
28498
|
+
});
|
|
28499
|
+
app.get("/workspace/git/log/commit", (req, res) => {
|
|
28500
|
+
void handleCommitDetail(
|
|
28501
|
+
req,
|
|
28502
|
+
res,
|
|
28503
|
+
deps.boundWorkspace,
|
|
28504
|
+
deps.sendBridgeError,
|
|
28505
|
+
"GET /workspace/git/log/commit"
|
|
28506
|
+
);
|
|
28507
|
+
});
|
|
28508
|
+
}
|
|
28509
|
+
__name(registerWorkspaceGitLogRoutes, "registerWorkspaceGitLogRoutes");
|
|
28510
|
+
function resolveTrustedRuntime4(registry, req, res) {
|
|
28511
|
+
const runtime = resolveWorkspaceRuntimeFromParam(registry, req, res);
|
|
28512
|
+
if (!runtime) return null;
|
|
28513
|
+
return requireTrustedWorkspaceRuntime(runtime, res) ? runtime : null;
|
|
28514
|
+
}
|
|
28515
|
+
__name(resolveTrustedRuntime4, "resolveTrustedRuntime");
|
|
28516
|
+
function registerWorkspaceQualifiedGitLogRoutes(app, deps) {
|
|
28517
|
+
app.get("/workspaces/:workspace/git/log", (req, res) => {
|
|
28518
|
+
const runtime = resolveTrustedRuntime4(deps.workspaceRegistry, req, res);
|
|
28519
|
+
if (!runtime) return;
|
|
28520
|
+
void handleLogList(
|
|
28521
|
+
req,
|
|
28522
|
+
res,
|
|
28523
|
+
runtime.workspaceCwd,
|
|
28524
|
+
deps.sendBridgeError,
|
|
28525
|
+
"GET /workspaces/:workspace/git/log"
|
|
28526
|
+
);
|
|
28527
|
+
});
|
|
28528
|
+
app.get("/workspaces/:workspace/git/log/commit", (req, res) => {
|
|
28529
|
+
const runtime = resolveTrustedRuntime4(deps.workspaceRegistry, req, res);
|
|
28530
|
+
if (!runtime) return;
|
|
28531
|
+
void handleCommitDetail(
|
|
28532
|
+
req,
|
|
28533
|
+
res,
|
|
28534
|
+
runtime.workspaceCwd,
|
|
28535
|
+
deps.sendBridgeError,
|
|
28536
|
+
"GET /workspaces/:workspace/git/log/commit"
|
|
28537
|
+
);
|
|
28538
|
+
});
|
|
28539
|
+
}
|
|
28540
|
+
__name(registerWorkspaceQualifiedGitLogRoutes, "registerWorkspaceQualifiedGitLogRoutes");
|
|
28541
|
+
|
|
26719
28542
|
// packages/cli/src/serve/workspace-git-state.ts
|
|
26720
28543
|
init_esbuild_shims();
|
|
26721
28544
|
var WorkspaceGitState = class {
|
|
@@ -28423,7 +30246,16 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
28423
30246
|
}, "channelReloadAvailable"),
|
|
28424
30247
|
sessionShellCommandEnabled,
|
|
28425
30248
|
multiWorkspaceSessionsEnabled: /* @__PURE__ */ __name(() => workspaceRegistry.list().length > 1, "multiWorkspaceSessionsEnabled"),
|
|
30249
|
+
dynamicWorkspaceRegistrationAvailable: deps.createWorkspaceRuntime !== void 0,
|
|
28426
30250
|
persistentWorkspaceRegistrationAvailable: deps.workspaceRegistrationStore !== void 0,
|
|
30251
|
+
// Scratch creation is advertised only while every managed runtime still
|
|
30252
|
+
// respects the root boundary and a complete disposal owner is present.
|
|
30253
|
+
scratchWorkspaceRegistrationAvailable: /* @__PURE__ */ __name(() => deps.createWorkspaceRuntime !== void 0 && deps.managedScratchRoot !== void 0 && deps.workspaceRuntimeRemoval !== void 0 && workspaceRegistry.listManaged().every(
|
|
30254
|
+
(runtime) => isScratchRootCompatible(
|
|
30255
|
+
runtime.workspaceCwd,
|
|
30256
|
+
deps.managedScratchRoot.canonicalRoot
|
|
30257
|
+
)
|
|
30258
|
+
), "scratchWorkspaceRegistrationAvailable"),
|
|
28427
30259
|
workspaceRuntimeRemovalAvailable: deps.workspaceRuntimeRemoval !== void 0,
|
|
28428
30260
|
...primaryEffectiveEnv ? { env: primaryEffectiveEnv } : {}
|
|
28429
30261
|
});
|
|
@@ -28446,6 +30278,7 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
28446
30278
|
maxPendingPromptsPerSession: opts.maxPendingPromptsPerSession,
|
|
28447
30279
|
eventRingSize: opts.eventRingSize,
|
|
28448
30280
|
compactedReplayMaxBytes: opts.compactedReplayMaxBytes,
|
|
30281
|
+
initializeTimeoutMs: opts.initializeTimeoutMs,
|
|
28449
30282
|
permissionResponseTimeoutMs: opts.permissionResponseTimeoutMs,
|
|
28450
30283
|
boundWorkspace,
|
|
28451
30284
|
sessionShellCommandEnabled,
|
|
@@ -28722,6 +30555,14 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
28722
30555
|
workspaceRegistry,
|
|
28723
30556
|
sendBridgeError: sendBridgeError2
|
|
28724
30557
|
});
|
|
30558
|
+
registerWorkspaceGitLogRoutes(app, {
|
|
30559
|
+
boundWorkspace: primaryBoundWorkspace,
|
|
30560
|
+
sendBridgeError: sendBridgeError2
|
|
30561
|
+
});
|
|
30562
|
+
registerWorkspaceQualifiedGitLogRoutes(app, {
|
|
30563
|
+
workspaceRegistry,
|
|
30564
|
+
sendBridgeError: sendBridgeError2
|
|
30565
|
+
});
|
|
28725
30566
|
mountWorkspaceMemoryRoutes(app, {
|
|
28726
30567
|
bridge: primaryBridge,
|
|
28727
30568
|
boundWorkspace: primaryBoundWorkspace,
|
|
@@ -28821,6 +30662,7 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
28821
30662
|
mutate,
|
|
28822
30663
|
safeBody,
|
|
28823
30664
|
createWorkspaceRuntime: deps.createWorkspaceRuntime,
|
|
30665
|
+
managedScratchRoot: deps.managedScratchRoot,
|
|
28824
30666
|
workspaceRegistrationStore: deps.workspaceRegistrationStore,
|
|
28825
30667
|
getAcpHandle: /* @__PURE__ */ __name(() => acpHandleRef.current, "getAcpHandle"),
|
|
28826
30668
|
runtimeRemoval: deps.workspaceRuntimeRemoval
|
|
@@ -28924,6 +30766,7 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
28924
30766
|
allowPrivateAuthBaseUrl: opts.allowPrivateAuthBaseUrl === true,
|
|
28925
30767
|
installAuthProvider: deps.installAuthProvider
|
|
28926
30768
|
});
|
|
30769
|
+
const virtualSubagentSessions = new VirtualSubagentSessions();
|
|
28927
30770
|
registerSessionRoutes(app, {
|
|
28928
30771
|
boundWorkspace: primaryBoundWorkspace,
|
|
28929
30772
|
bridge: primaryBridge,
|
|
@@ -28934,7 +30777,8 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
28934
30777
|
daemonLog,
|
|
28935
30778
|
promptDeadlineMs: opts.promptDeadlineMs,
|
|
28936
30779
|
sessionShellCommandEnabled,
|
|
28937
|
-
languageCodes
|
|
30780
|
+
languageCodes,
|
|
30781
|
+
virtualSubagentSessions
|
|
28938
30782
|
});
|
|
28939
30783
|
registerWorkspaceMcpControlRoutes(app, {
|
|
28940
30784
|
boundWorkspace: primaryBoundWorkspace,
|
|
@@ -29100,7 +30944,8 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
29100
30944
|
workspaceRegistry,
|
|
29101
30945
|
daemonLog,
|
|
29102
30946
|
writerIdleTimeoutMs: opts.writerIdleTimeoutMs,
|
|
29103
|
-
sendBridgeError: sendBridgeError2
|
|
30947
|
+
sendBridgeError: sendBridgeError2,
|
|
30948
|
+
virtualSubagentSessions
|
|
29104
30949
|
});
|
|
29105
30950
|
acpHandleRef.current = mountAcpHttp(app, primaryBridge, {
|
|
29106
30951
|
boundWorkspace: primaryBoundWorkspace,
|