@qwen-code/qwen-code 0.19.10 → 0.19.11-nightly.20260718.767a32484
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/model-providers.md +11 -0
- package/bundled/qc-helper/docs/configuration/settings.md +15 -14
- package/bundled/qc-helper/docs/features/approval-mode.md +2 -2
- package/bundled/qc-helper/docs/features/channels/dingtalk.md +30 -0
- package/bundled/qc-helper/docs/features/channels/overview.md +66 -17
- package/bundled/qc-helper/docs/features/channels/wecom.md +8 -7
- package/bundled/qc-helper/docs/features/sandbox.md +2 -0
- package/bundled/qc-helper/docs/qwen-serve-deploy-local.md +42 -7
- package/bundled/qc-helper/docs/qwen-serve.md +77 -46
- package/bundled/qc-helper/docs/reference/keyboard-shortcuts.md +1 -1
- package/bundled/review/SKILL.md +163 -403
- package/chunks/{MaxSizedBox-67ODZ4SZ.js → MaxSizedBox-ZFHA4QEQ.js} +30 -30
- package/chunks/{StandaloneSessionPicker-SIPBQT5Z.js → StandaloneSessionPicker-YRWOQVQA.js} +44 -44
- package/chunks/{acpAgent-VPZJXLFX.js → acpAgent-U2P2IESZ.js} +1423 -487
- package/chunks/{agent-Z7NWL6XL.js → agent-GQXX6X5Y.js} +26 -26
- package/chunks/{agent-headless-73HZ6ROQ.js → agent-headless-3572NBCK.js} +26 -26
- package/chunks/{anthropicContentGenerator-56U3YCP2.js → anthropicContentGenerator-Y65DMM64.js} +103 -18
- package/chunks/{artifact-tool-BWZZJ42H.js → artifact-tool-WR7I2XON.js} +2 -2
- package/chunks/{askUserQuestion-WU3S5A5T.js → askUserQuestion-B4FUTPHD.js} +2 -44
- package/chunks/{bridge-XFKW6S7Q.js → bridge-N5RMGD7G.js} +31 -33
- package/chunks/{ca-C2JTT2N5.js → ca-M3GQQ26D.js} +7 -2
- package/chunks/channel-worker-group-HZVJKLGX.js +21 -0
- package/chunks/{channel-worker-manager-5RWKSGEU.js → channel-worker-manager-3WDK4HNS.js} +34 -10
- package/chunks/{channel-worker-supervisor-PCDAZN4D.js → channel-worker-supervisor-U2W6Q5F7.js} +6 -4
- package/chunks/{chunk-YYPXHMWO.js → chunk-2XRGFF5K.js} +6 -6
- package/chunks/{chunk-ZKMGAFYV.js → chunk-2YSZE74N.js} +2 -2
- package/chunks/{chunk-L5U3ELZX.js → chunk-335ECZTA.js} +1 -1
- package/chunks/{chunk-5EBKKSBX.js → chunk-336KPNNV.js} +2 -2
- package/chunks/{chunk-Q5GLXH5Q.js → chunk-3CL5SEDT.js} +6 -6
- package/chunks/{chunk-2FO5GFKZ.js → chunk-3DJY4IFO.js} +1 -1
- package/chunks/{chunk-CJFNEBYB.js → chunk-3NWYQ7FX.js} +2 -2
- package/chunks/{chunk-WIASPMLX.js → chunk-3X2CFOUM.js} +358 -298
- package/chunks/{chunk-K7CRWKOE.js → chunk-3YJZ6WNY.js} +5812 -4520
- package/chunks/{chunk-Y66VOBRP.js → chunk-4CA4WUMS.js} +2 -2
- package/chunks/{chunk-LQIDP6K5.js → chunk-4CHDYDG3.js} +1 -1
- package/chunks/{chunk-TISZXPAX.js → chunk-4HCYNDMG.js} +1 -1
- package/chunks/chunk-4JBTZBCW.js +140 -0
- package/chunks/{chunk-TV6K2FB4.js → chunk-4RPARQ5D.js} +2 -2
- package/chunks/{chunk-RCEEXIOO.js → chunk-4XCVGEEX.js} +3 -3
- package/chunks/{chunk-N6FXRR6P.js → chunk-57RWF6R7.js} +1 -1
- package/chunks/chunk-5O34IMY5.js +59 -0
- package/chunks/{chunk-5LROA5W4.js → chunk-5QRK2VZG.js} +8 -8
- package/chunks/{chunk-7L4XBYVW.js → chunk-632KROVU.js} +10 -3
- package/chunks/{chunk-65N2J6V2.js → chunk-64XGKNSI.js} +3 -3
- package/chunks/{chunk-P6LART6G.js → chunk-66IT3EY2.js} +1059 -129
- package/chunks/{chunk-FXMC7SL2.js → chunk-6ITLKEOZ.js} +3 -3
- package/chunks/{chunk-F7NXQH4Y.js → chunk-6YIRYY3P.js} +1 -1
- package/chunks/{chunk-GGJII3FM.js → chunk-6Z5NRZVU.js} +92 -3
- package/chunks/{chunk-DPFBNG72.js → chunk-AEKYFMYE.js} +1 -1
- package/chunks/{chunk-2UUAIFQO.js → chunk-ANRANWVE.js} +9 -1
- package/chunks/{chunk-SXU3KKNI.js → chunk-ATJ7H5AS.js} +419 -76
- package/chunks/{chunk-6GETGQWP.js → chunk-C5NSOSF4.js} +64 -18
- package/chunks/{chunk-TQBODCFD.js → chunk-CMVFTMRD.js} +251 -3
- package/chunks/{chunk-DK33QJ3V.js → chunk-CZSAIBUB.js} +733 -14
- package/chunks/{chunk-3MX7D6QN.js → chunk-DASWPKXR.js} +32 -4
- package/chunks/{chunk-JSJFKYWT.js → chunk-DPSHAB47.js} +2 -2
- package/chunks/{chunk-7MJAZMXK.js → chunk-ECZFTRTP.js} +29 -78
- package/chunks/{chunk-H3FQOPPS.js → chunk-EKG3BHQY.js} +4 -4
- package/chunks/{chunk-FSA7ERJ2.js → chunk-F2RR4HO2.js} +1 -1
- package/chunks/{chunk-EQY6POVO.js → chunk-F5XYN5VF.js} +2 -2
- package/chunks/chunk-FEOZBUMT.js +77 -0
- package/chunks/{chunk-L62SEJWY.js → chunk-FHUXCRAF.js} +4 -4
- package/chunks/{chunk-OFEVHGVU.js → chunk-FSJGBUQI.js} +818 -31
- package/chunks/{chunk-FBU7WRZI.js → chunk-FUTHTZVV.js} +1 -1
- package/chunks/{chunk-ZRKBI3DP.js → chunk-FZRES4GK.js} +1 -1
- package/chunks/{chunk-OKAIGAYW.js → chunk-G274ETR6.js} +3 -3
- package/chunks/{chunk-6GKMJPOC.js → chunk-GA3WUOO7.js} +5 -5
- package/chunks/{chunk-X362TMXZ.js → chunk-GAQOQMHY.js} +8 -6
- package/chunks/{chunk-WLXYAKV7.js → chunk-GG6RSNWS.js} +9 -4
- package/chunks/{chunk-CEW4HDPK.js → chunk-GUNTLALV.js} +2484 -362
- package/chunks/{chunk-LXLTBIDP.js → chunk-HCCR43AY.js} +1 -1
- package/chunks/{chunk-RDRVMDWV.js → chunk-HIMIG6PI.js} +11 -11
- package/chunks/{chunk-MO7O5722.js → chunk-HQXQCIT2.js} +45 -5
- package/chunks/{chunk-LTNI523B.js → chunk-HT7L5FCZ.js} +28 -5
- package/chunks/{chunk-7NAWTFVY.js → chunk-IENO2YAT.js} +3 -3
- package/chunks/{chunk-3XJFUTNM.js → chunk-IK5TYYVR.js} +59 -12
- package/chunks/{chunk-AAR5SGMD.js → chunk-IVKLDHU6.js} +7 -5
- package/chunks/{chunk-6W6DI34P.js → chunk-IX7O5WI3.js} +180 -8
- package/chunks/{chunk-SPJQO2CE.js → chunk-J2MKYJKZ.js} +2 -2
- package/chunks/{chunk-SPUYQB4T.js → chunk-JBAQ5BYX.js} +1 -1
- package/chunks/{chunk-TYLOFD2U.js → chunk-JCJPZMJV.js} +1 -1
- package/chunks/chunk-JDIUK2Y3.js +226 -0
- package/chunks/{chunk-L37RC7MQ.js → chunk-JUVTV4NF.js} +1 -1
- package/chunks/{chunk-WDWJ4OQJ.js → chunk-K2GBHL73.js} +4 -4
- package/chunks/{chunk-HHEFI4RP.js → chunk-KEVDWH3U.js} +857 -137
- package/chunks/{chunk-YU56QGXX.js → chunk-KTKETHMY.js} +1 -1
- package/chunks/{chunk-WDW64OW3.js → chunk-LGY7PG7Q.js} +5 -5
- package/chunks/{chunk-E67NFMF4.js → chunk-LKR7QQ63.js} +37 -3
- package/chunks/{chunk-4YWLED2A.js → chunk-LSFVUGXT.js} +9 -6
- package/chunks/{chunk-W34A5MJH.js → chunk-LTD3CHGS.js} +1 -1
- package/chunks/chunk-LXXMOYPL.js +22 -0
- package/chunks/{chunk-BBNVFRGD.js → chunk-MI2V6IWU.js} +1 -1
- package/chunks/{chunk-UFOKA4PR.js → chunk-O2K6BLPZ.js} +114 -4
- package/chunks/{chunk-B5I2IIWY.js → chunk-OBYAX5QZ.js} +6 -6
- package/chunks/{chunk-V7EQTZYR.js → chunk-OCQ2QTFJ.js} +203 -47
- package/chunks/{chunk-VBRRNQB7.js → chunk-OPVIKLKK.js} +112 -25
- package/chunks/{chunk-2Z5UX4KI.js → chunk-OSSDHJDU.js} +1 -1
- package/chunks/{chunk-TTUO4DNG.js → chunk-OXOEOOQU.js} +126 -734
- package/chunks/{chunk-4FMG7EDJ.js → chunk-PWYLF7SS.js} +79 -16
- package/chunks/chunk-QFEY6OXH.js +45 -0
- package/chunks/{chunk-YX4LLZ3D.js → chunk-QPRDXJIC.js} +115 -40
- package/chunks/{chunk-7R4DPSRA.js → chunk-R3VWUU2E.js} +1 -1
- package/chunks/{chunk-XLIRF7IK.js → chunk-S4N3G4BB.js} +1 -1
- package/chunks/{chunk-ARKANCNX.js → chunk-SGPFJMRP.js} +1 -1
- package/chunks/{chunk-WTSXKLG5.js → chunk-SUARMD4Q.js} +1 -1
- package/chunks/{chunk-PZL23GTM.js → chunk-T3W4SDRB.js} +2 -0
- package/chunks/chunk-T4TZQJ7W.js +48 -0
- package/chunks/{chunk-K4PZ5F5T.js → chunk-TVYM3Q3J.js} +101 -8
- package/chunks/{chunk-4LD5APFL.js → chunk-TYQMGACW.js} +1 -0
- package/chunks/{chunk-6OATMEYN.js → chunk-U2LNTX56.js} +12 -4
- package/chunks/{chunk-422XAKCK.js → chunk-U2XBPBO3.js} +4 -3
- package/chunks/{chunk-LNUXFLLJ.js → chunk-U4FJ26D2.js} +54 -6
- package/chunks/{chunk-ZQTZXVHP.js → chunk-U6OPT4H2.js} +4 -18
- package/chunks/{chunk-7NFB7LBQ.js → chunk-UE5TZ55T.js} +8 -0
- package/chunks/{chunk-CUUXANEQ.js → chunk-URP6O2PP.js} +6 -1
- package/chunks/{chunk-GDQQRV43.js → chunk-V2FRLYHN.js} +3 -3
- package/chunks/{chunk-WIEO4CWB.js → chunk-VAJS2E2D.js} +1 -1
- package/chunks/{chunk-TXY2C3D2.js → chunk-VNN3JNYT.js} +1 -1
- package/chunks/{chunk-YHN5SUIJ.js → chunk-W7H223ZZ.js} +1 -1
- package/chunks/{chunk-WX6SD4IQ.js → chunk-WEPXQKGP.js} +1 -1
- package/chunks/{chunk-KSO42X3Z.js → chunk-X6YQWCIJ.js} +21 -2
- package/chunks/{chunk-URU5UEK6.js → chunk-XA7OKDWM.js} +135 -68
- package/chunks/{chunk-Q6TUALBE.js → chunk-XAAEDML2.js} +1 -1
- package/chunks/{chunk-KKRTYONM.js → chunk-XSPFQQRE.js} +3 -3
- package/chunks/{chunk-OATTJGPJ.js → chunk-Y72B36CP.js} +7 -7
- package/chunks/{chunk-ZPAHLFZU.js → chunk-Z2LBNX3R.js} +2 -2
- package/chunks/{chunk-XXJKGHZV.js → chunk-ZTSDZQZO.js} +131 -4
- package/chunks/{computer-use-IYTX45WA.js → computer-use-UIFBH25Y.js} +26 -26
- package/chunks/{config-utils-CFT33LTP.js → config-utils-2LHI7JXU.js} +3 -3
- package/chunks/{contextCommand-272V77WU.js → contextCommand-VGZHKEH2.js} +28 -28
- package/chunks/{create-sub-session-WNX2OQVX.js → create-sub-session-DIJOV6HV.js} +2 -2
- package/chunks/{create-sub-session-CBJMQLYP.js → create-sub-session-OFVI4H6I.js} +26 -26
- package/chunks/{cron-create-36TIFKRT.js → cron-create-34GVLSW5.js} +4 -4
- package/chunks/{cron-delete-OQD3WULU.js → cron-delete-NMVKUL45.js} +4 -4
- package/chunks/{cron-list-4533T2FH.js → cron-list-277ZOR7L.js} +4 -4
- package/chunks/{daemon-RNGFPMAB.js → daemon-72MEV3TY.js} +361 -84
- package/chunks/daemon-status-provider-ZJJ6AOG2.js +75 -0
- package/chunks/{de-2VCDRDGU.js → de-56TMDIKS.js} +7 -2
- package/chunks/{dist-3V3ZV6ML.js → dist-4W3UGU2A.js} +1 -1
- package/chunks/{dist-HNN7DR2L.js → dist-G6QCGO2K.js} +58 -30
- package/chunks/{dist-ERCPDVA6.js → dist-ILVRL322.js} +4 -51
- package/chunks/{dist-PHEPJLXD.js → dist-KEZ5JWH4.js} +2 -2
- package/chunks/{dist-JZE7F6YR.js → dist-LQHDHBPP.js} +1 -1
- package/chunks/{dist-MOEC47TR.js → dist-SVHAGOLN.js} +1 -1
- package/chunks/{earlyInputCapture-EN4BRREQ.js → earlyInputCapture-NPF4PVUE.js} +27 -27
- package/chunks/{edit-OMAF2QDR.js → edit-F7CT6NZH.js} +27 -27
- package/chunks/{en-NJCA3TAA.js → en-AXS2N62H.js} +12 -3
- package/chunks/{enter-worktree-BBZX52HG.js → enter-worktree-Z4ET3MZL.js} +26 -26
- package/chunks/{enterPlanMode-5NNFMBUY.js → enterPlanMode-VYR7T5NX.js} +27 -29
- package/chunks/{environment-7TEWMJYN.js → environment-MBTXL57Q.js} +28 -28
- package/chunks/{errors-I4VKVX3F.js → errors-HN36J4FR.js} +28 -28
- package/chunks/{exit-worktree-FUWRJI33.js → exit-worktree-RU7JYFMF.js} +26 -26
- package/chunks/exitPlanMode-LUBAWMZQ.js +390 -0
- package/chunks/{fast-path-ZA57TOH4.js → fast-path-RFT3CDNZ.js} +2 -2
- package/chunks/{fr-5F3E7WKD.js → fr-ZJPE5OVN.js} +7 -2
- package/chunks/{gemini-UOAKVXBG.js → gemini-37NTNKZF.js} +215 -231
- package/chunks/{geminiContentGenerator-G6UCE6MW.js → geminiContentGenerator-76HNOYNQ.js} +5 -5
- package/chunks/{glob-4GJQ2UFF.js → glob-DWD7JCZE.js} +32 -27
- package/chunks/{grep-5QSYXF2E.js → grep-NJRXFV5C.js} +32 -27
- package/chunks/{handleAutoUpdate-ULHNWL6R.js → handleAutoUpdate-7GBDXW6U.js} +30 -30
- package/chunks/{i18n-CYDUTF6F.js → i18n-MYD5VGED.js} +27 -27
- package/chunks/{initializer-NRFKUGIO.js → initializer-4DHPNAZG.js} +32 -32
- package/chunks/{installationInfo-WELKRHHE.js → installationInfo-RWOW6BZO.js} +27 -27
- package/chunks/{ja-66J6B53L.js → ja-57GG4QSL.js} +7 -2
- package/chunks/{keychain-token-storage-AU22CQI6.js → keychain-token-storage-K23CFKGN.js} +2 -2
- package/chunks/{list-JVDXEG2E.js → list-MMCNNHE7.js} +34 -34
- package/chunks/{loadedSettingsAdapter-WAM4VUTG.js → loadedSettingsAdapter-UK4JWPYU.js} +31 -31
- package/chunks/{loop-wakeup-MVUKDVCP.js → loop-wakeup-KCLY4XQM.js} +5 -5
- package/chunks/{ls-RXNIAQDE.js → ls-UNI4LAJ3.js} +4 -4
- package/chunks/{lsp-HB5LM5IL.js → lsp-HPACPJAN.js} +2 -2
- package/chunks/{mcp-YHOZN3ZM.js → mcp-AFCVA4UV.js} +31 -31
- package/chunks/{monitor-R7XZPJHQ.js → monitor-RK637BNO.js} +28 -27
- package/chunks/nonInteractiveCli-OUGWLHNV.js +129 -0
- package/chunks/{notebook-edit-6RNKE2L2.js → notebook-edit-LY2X3CMF.js} +27 -27
- package/chunks/{openaiContentGenerator-XNS5S64I.js → openaiContentGenerator-MDYDW7IA.js} +14 -14
- package/chunks/{pidfile-XE4RRR2P.js → pidfile-2NUYRLKB.js} +27 -27
- package/chunks/processUtils-7QH3VBVN.js +29 -0
- package/chunks/{pt-TFZO5Y6T.js → pt-MCGZ3RZ4.js} +7 -2
- package/chunks/{qwenContentGenerator-APDPJ3VN.js → qwenContentGenerator-3HT4TVDL.js} +28 -28
- package/chunks/{qwenOAuth2-LEYOU7RU.js → qwenOAuth2-3A4TJVZT.js} +5 -5
- package/chunks/{read-file-XSUWXSR7.js → read-file-NE4FREFR.js} +10 -10
- package/chunks/{read-mcp-resource-6LRTZKXI.js → read-mcp-resource-C6NT52T6.js} +2 -2
- package/chunks/{record-artifact-PMDTY4OS.js → record-artifact-ENCU7QCL.js} +2 -2
- package/chunks/{ripGrep-APB3CDMU.js → ripGrep-DBLXWQCJ.js} +26 -26
- package/chunks/{ru-4L4LFHIT.js → ru-GA3NZW5Q.js} +7 -2
- package/chunks/{run-qwen-serve-NWTGPERT.js → run-qwen-serve-3NOCI6IL.js} +63 -39
- package/chunks/{runtime-EIO3NQKR.js → runtime-ZI7DSZSS.js} +35 -35
- package/chunks/{scheduler-JJDZBDRN.js → scheduler-SOVEP5K7.js} +26 -26
- package/chunks/{send-message-SR4WSXP2.js → send-message-5IFPZTPE.js} +3 -3
- package/chunks/{serve-WTIPB3EI.js → serve-DB6OCXIA.js} +31 -31
- package/chunks/{server-NJPHQHLH.js → server-LDY4YVU4.js} +2257 -648
- package/chunks/{session-O4AO7FTS.js → session-D6OG5SKX.js} +99 -72
- package/chunks/{settings-HQNDK7TG.js → settings-L52ZV5LO.js} +30 -30
- package/chunks/{shell-UIXM6PWG.js → shell-IU27OY3Q.js} +28 -26
- package/chunks/{skill-3XMB4ULV.js → skill-BSOJT7LE.js} +12 -12
- package/chunks/{spawnChannel-3R632QRM.js → spawnChannel-HQAM25DD.js} +28 -29
- package/chunks/{src-USZKPUOC.js → src-7ZBIMTJZ.js} +130 -51
- package/chunks/{standalone-update-L5XW3D7K.js → standalone-update-77457VVK.js} +28 -28
- package/chunks/{startInteractiveUI-CPZOL2WB.js → startInteractiveUI-S7WC6EZG.js} +2310 -1835
- package/chunks/{syntheticOutput-YKFNUQZD.js → syntheticOutput-ULOVVLY4.js} +3 -3
- package/chunks/{task-create-NUFOHU53.js → task-create-V2DCDSET.js} +7 -7
- package/chunks/{task-list-Z2IKQY3S.js → task-list-DPL5ZN55.js} +5 -5
- package/chunks/{task-stop-KQFIVQTJ.js → task-stop-CPEQWOT6.js} +2 -2
- package/chunks/{task-update-HKADXSTD.js → task-update-ZR45M5Q7.js} +7 -7
- package/chunks/{team-create-XXPRF3IQ.js → team-create-CO7HSUON.js} +26 -26
- package/chunks/{team-delete-SDNTGZLG.js → team-delete-HIWXCWJU.js} +5 -5
- package/chunks/{team-plan-approval-EOTTKHDW.js → team-plan-approval-QDZF5YZY.js} +26 -26
- package/chunks/{theme-manager-P6UITO2L.js → theme-manager-UTUT3I4P.js} +27 -27
- package/chunks/todoWrite-HK6B3RHJ.js +358 -0
- package/chunks/{tool-search-DDNGK2LR.js → tool-search-2UUORA35.js} +11 -11
- package/chunks/{total-session-admission-PL5N7DNY.js → total-session-admission-NTWG6G3F.js} +32 -34
- package/chunks/{trustedFolders-C5LMF3UR.js → trustedFolders-YF37ZCN5.js} +27 -27
- package/chunks/update-relaunch-QFNHPMZZ.js +87 -0
- package/chunks/{updateCheck-QTVVISH7.js → updateCheck-B6O42VMD.js} +30 -28
- package/chunks/{validateNonInterActiveAuth-RY4RKBQG.js → validateNonInterActiveAuth-SCIWJ4CX.js} +65 -65
- package/chunks/{version-U45RYOSD.js → version-7DA6LAI3.js} +1 -1
- package/chunks/{web-fetch-ZSPR3PRR.js → web-fetch-B62SJXM2.js} +5 -6
- package/chunks/{workflow-TCIAQYOA.js → workflow-Q5WG4THP.js} +27 -27
- package/chunks/{workspace-providers-status-I3G2HYLY.js → workspace-providers-status-WWLAGWQW.js} +34 -34
- package/chunks/{workspace-registration-store-IH5GLZ6Y.js → workspace-registration-store-BVYQVY2H.js} +1 -1
- package/chunks/{workspace-registry-QEKBELIX.js → workspace-registry-OD7ACADD.js} +32 -34
- package/chunks/{workspace-service-ORKHGLP3.js → workspace-service-4LYJWS63.js} +37 -38
- package/chunks/{workspace-skills-status-D7QCNDYY.js → workspace-skills-status-P2AQLZZS.js} +32 -32
- package/chunks/{write-file-JGRQR5VM.js → write-file-TEPGXNM3.js} +60 -27
- package/chunks/{zh-FSAH32JB.js → zh-E34DZ2S3.js} +12 -3
- package/chunks/{zh-TW-D2YIE2LO.js → zh-TW-PEI2ZWUR.js} +12 -3
- package/cli-entry.js +92 -8
- package/cli.js +11 -11
- package/locales/ca.js +12 -2
- package/locales/de.js +12 -2
- package/locales/en.js +20 -5
- package/locales/fr.js +12 -2
- package/locales/ja.js +12 -2
- package/locales/pt.js +12 -2
- package/locales/ru.js +12 -2
- package/locales/zh-TW.js +19 -3
- package/locales/zh.js +19 -3
- package/package.json +3 -3
- package/web-shell/assets/{arc-CUeDlxvE.js → arc-Dh-N5oEG.js} +1 -1
- package/web-shell/assets/{architectureDiagram-3BPJPVTR-PiUszkQA.js → architectureDiagram-3BPJPVTR-DBOQgtfF.js} +1 -1
- package/web-shell/assets/{blockDiagram-GPEHLZMM-s2wYSO7e.js → blockDiagram-GPEHLZMM-Dyxbuyju.js} +1 -1
- package/web-shell/assets/{c4Diagram-AAUBKEIU-DyLxZoz9.js → c4Diagram-AAUBKEIU-DCJR5HPT.js} +1 -1
- package/web-shell/assets/channel-DY0fkcKT.js +1 -0
- package/web-shell/assets/{chunk-2J33WTMH-Dsdai7Tk.js → chunk-2J33WTMH-BkMUcy3O.js} +1 -1
- package/web-shell/assets/{chunk-4BX2VUAB-DEosOjV7.js → chunk-4BX2VUAB-BSm4pLQk.js} +1 -1
- package/web-shell/assets/{chunk-55IACEB6-sNsRLTXf.js → chunk-55IACEB6-CuRr-XgW.js} +1 -1
- package/web-shell/assets/{chunk-727SXJPM-DkRNZzmh.js → chunk-727SXJPM-CLv7-w3t.js} +1 -1
- package/web-shell/assets/{chunk-AQP2D5EJ-BrsRNpzd.js → chunk-AQP2D5EJ-Cz_n3-JW.js} +1 -1
- package/web-shell/assets/{chunk-FMBD7UC4-CI039lpl.js → chunk-FMBD7UC4-CFT_62Hq.js} +1 -1
- package/web-shell/assets/{chunk-ND2GUHAM-M-pkeIfu.js → chunk-ND2GUHAM-DWz6DOZ6.js} +1 -1
- package/web-shell/assets/{chunk-QZHKN3VN-C4ckGNbH.js → chunk-QZHKN3VN-C-mRhUzw.js} +1 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-DBvJ6PZo.js +1 -0
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-DBvJ6PZo.js +1 -0
- package/web-shell/assets/{cose-bilkent-S5V4N54A-BciKUAFq.js → cose-bilkent-S5V4N54A-BqCZS3i1.js} +1 -1
- package/web-shell/assets/{dagre-BM42HDAG-C1nTSgU6.js → dagre-BM42HDAG-BGasdP8i.js} +1 -1
- package/web-shell/assets/{diagram-2AECGRRQ-BDPNWr1m.js → diagram-2AECGRRQ-BSyLDkMy.js} +1 -1
- package/web-shell/assets/{diagram-5GNKFQAL-CNFhTszL.js → diagram-5GNKFQAL-CM-ZJxWC.js} +1 -1
- package/web-shell/assets/{diagram-KO2AKTUF-CjPa4p5a.js → diagram-KO2AKTUF-wJdzt_C5.js} +1 -1
- package/web-shell/assets/{diagram-LMA3HP47-ZzPykSyG.js → diagram-LMA3HP47-DiH2fhpL.js} +1 -1
- package/web-shell/assets/{diagram-OG6HWLK6-0UVtZ9A4.js → diagram-OG6HWLK6-BZ9z1ZBl.js} +1 -1
- package/web-shell/assets/{erDiagram-TEJ5UH35-CajDZCat.js → erDiagram-TEJ5UH35-BsyWDziR.js} +1 -1
- package/web-shell/assets/{flowDiagram-I6XJVG4X-BRuFBIvL.js → flowDiagram-I6XJVG4X-CzdkxIrq.js} +1 -1
- package/web-shell/assets/{ganttDiagram-6RSMTGT7-BevGmJqG.js → ganttDiagram-6RSMTGT7-javIv2r2.js} +1 -1
- package/web-shell/assets/{gitGraphDiagram-PVQCEYII-DvPMpBMb.js → gitGraphDiagram-PVQCEYII-CjHstylC.js} +1 -1
- package/web-shell/assets/{index-DzHwQkQq.js → index-BnJGxpah.js} +1 -1
- package/web-shell/assets/index-DhXB9nTa.js +1161 -0
- package/web-shell/assets/index-vYHgZ7bL.css +5 -0
- package/web-shell/assets/{infoDiagram-5YYISTIA-Oixn7tA9.js → infoDiagram-5YYISTIA-yXuQsomo.js} +1 -1
- package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-BgKpeg-j.js → ishikawaDiagram-YF4QCWOH-a85JhE6F.js} +1 -1
- package/web-shell/assets/{journeyDiagram-JHISSGLW-74mwxIaA.js → journeyDiagram-JHISSGLW-Dak_4BVj.js} +1 -1
- package/web-shell/assets/{kanban-definition-UN3LZRKU-D4D6cEqA.js → kanban-definition-UN3LZRKU-COA-LuCV.js} +1 -1
- package/web-shell/assets/{linear-atZRE_L2.js → linear-DNAAAQWq.js} +1 -1
- package/web-shell/assets/{mermaid.core-KKudX-JC.js → mermaid.core-7Ff3aIUD.js} +5 -5
- package/web-shell/assets/{mindmap-definition-RKZ34NQL-CMCej9yG.js → mindmap-definition-RKZ34NQL-_rCOIODU.js} +1 -1
- package/web-shell/assets/{pieDiagram-4H26LBE5-nhx40X7q.js → pieDiagram-4H26LBE5-C9QCQ8EW.js} +1 -1
- package/web-shell/assets/{quadrantDiagram-W4KKPZXB-CUmVcN3M.js → quadrantDiagram-W4KKPZXB-CsaE4FA8.js} +1 -1
- package/web-shell/assets/{requirementDiagram-4Y6WPE33-C_vyEwyy.js → requirementDiagram-4Y6WPE33-tV78naTg.js} +1 -1
- package/web-shell/assets/{sankeyDiagram-5OEKKPKP-DU6G4VWR.js → sankeyDiagram-5OEKKPKP-Dk3Rw7BZ.js} +1 -1
- package/web-shell/assets/{sequenceDiagram-3UESZ5HK-DdeRR_KJ.js → sequenceDiagram-3UESZ5HK-BGsAWcMX.js} +1 -1
- package/web-shell/assets/{stateDiagram-AJRCARHV-C6iCI8ps.js → stateDiagram-AJRCARHV-zSxdtdoB.js} +1 -1
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-vLEEtDpO.js +1 -0
- package/web-shell/assets/{timeline-definition-PNZ67QCA-B_Ea8Cb7.js → timeline-definition-PNZ67QCA-j0BQh9Go.js} +1 -1
- package/web-shell/assets/{vennDiagram-CIIHVFJN-BPUVZEJA.js → vennDiagram-CIIHVFJN-CRaUFFIu.js} +1 -1
- package/web-shell/assets/{wardley-L42UT6IY-BWEj0lKY.js → wardley-L42UT6IY-D7Py_ofm.js} +1 -1
- package/web-shell/assets/{wardleyDiagram-YWT4CUSO-BvDsdIQw.js → wardleyDiagram-YWT4CUSO-BrDIAZcp.js} +1 -1
- package/web-shell/assets/{xychartDiagram-2RQKCTM6-crz0QhF_.js → xychartDiagram-2RQKCTM6-Cecdw-w2.js} +1 -1
- package/web-shell/index.html +2 -2
- package/chunks/channel-worker-group-K7QKH6IG.js +0 -13
- package/chunks/chunk-2HRYPZT5.js +0 -25
- package/chunks/chunk-B7NUUEXC.js +0 -311
- package/chunks/chunk-CARU2RR2.js +0 -24
- package/chunks/chunk-GYTKQYDB.js +0 -23
- package/chunks/chunk-LQU7EVFA.js +0 -30
- package/chunks/chunk-OCPBI7J5.js +0 -18
- package/chunks/chunk-OJAMDVF5.js +0 -66
- package/chunks/chunk-QAW7PIHT.js +0 -168
- package/chunks/chunk-TEGEBB2I.js +0 -122
- package/chunks/daemon-status-provider-L4STG5VO.js +0 -76
- package/chunks/exitPlanMode-IHCJ5EEI.js +0 -909
- package/chunks/nonInteractiveCli-NSOB6D74.js +0 -129
- package/chunks/todoWrite-YNXB27GB.js +0 -531
- package/web-shell/assets/channel-DkuJJ0qd.js +0 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-CwqHc0TB.js +0 -1
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-CwqHc0TB.js +0 -1
- package/web-shell/assets/index-Cnvv4VcI.css +0 -5
- package/web-shell/assets/index-D1Uyklxa.js +0 -1088
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-C0_6nR6C.js +0 -1
|
@@ -1,22 +1,25 @@
|
|
|
1
1
|
// Force strict mode and setup for ESM
|
|
2
2
|
"use strict";
|
|
3
3
|
import {
|
|
4
|
-
|
|
5
|
-
openVoiceStream,
|
|
6
|
-
openVoiceStreamWithRetry
|
|
7
|
-
} from "./chunk-JSJFKYWT.js";
|
|
8
|
-
import {
|
|
4
|
+
GENERATION_MAX_PROMPT_BYTES,
|
|
9
5
|
MAX_REMEMBER_CONTENT_BYTES,
|
|
10
6
|
createWorkspaceMemoryExtractionErrorLogger,
|
|
11
7
|
extractRememberErrorCode,
|
|
12
8
|
formatWorkspaceMemoryDreamSummary,
|
|
13
9
|
formatWorkspaceMemoryForgetSummary,
|
|
14
10
|
isValidServerName,
|
|
11
|
+
redactMcpServersSetting,
|
|
15
12
|
replayTranscriptRecordPage,
|
|
13
|
+
restoreRedactedMcpServersSetting,
|
|
16
14
|
shouldSuppressRememberErrorDetails,
|
|
17
15
|
workspaceMemoryFailureCode,
|
|
18
16
|
workspaceMemoryFailureDiagnostics
|
|
19
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-IX7O5WI3.js";
|
|
18
|
+
import {
|
|
19
|
+
openQwenAsrRealtimeStream,
|
|
20
|
+
openVoiceStream,
|
|
21
|
+
openVoiceStreamWithRetry
|
|
22
|
+
} from "./chunk-DPSHAB47.js";
|
|
20
23
|
import {
|
|
21
24
|
SetupGithubError,
|
|
22
25
|
collectSessionData,
|
|
@@ -27,9 +30,9 @@ import {
|
|
|
27
30
|
toJson,
|
|
28
31
|
toJsonl,
|
|
29
32
|
toMarkdown
|
|
30
|
-
} from "./chunk-
|
|
31
|
-
import "./chunk-
|
|
32
|
-
import "./chunk-
|
|
33
|
+
} from "./chunk-PWYLF7SS.js";
|
|
34
|
+
import "./chunk-JBAQ5BYX.js";
|
|
35
|
+
import "./chunk-SUARMD4Q.js";
|
|
33
36
|
import "./chunk-QHTIBUWB.js";
|
|
34
37
|
import "./chunk-L573Z2QZ.js";
|
|
35
38
|
import {
|
|
@@ -41,7 +44,6 @@ import {
|
|
|
41
44
|
MAX_CLIENT_ID_LENGTH,
|
|
42
45
|
MAX_CONCURRENT_VOICE_SESSIONS,
|
|
43
46
|
MAX_SERVER_NAME_LENGTH,
|
|
44
|
-
MAX_SKILL_NAME_LENGTH,
|
|
45
47
|
MAX_TOOL_NAME_LENGTH,
|
|
46
48
|
PathMutexRegistry,
|
|
47
49
|
QWEN_CDP_MCP_COMMAND_ENV,
|
|
@@ -62,9 +64,11 @@ import {
|
|
|
62
64
|
denyBrowserOriginCors,
|
|
63
65
|
detectFromLoopback,
|
|
64
66
|
getAdvertisedServeFeatures,
|
|
67
|
+
getDeferredRuntimeRequestTiming,
|
|
65
68
|
getServeProtocolVersions,
|
|
66
69
|
hostAllowlist,
|
|
67
70
|
isBrowserAutomationMcpAvailable,
|
|
71
|
+
isDeepHealthQuery,
|
|
68
72
|
parseAllowOriginPatterns,
|
|
69
73
|
parseAndValidateWorkspaceClientId,
|
|
70
74
|
parseClientIdHeader,
|
|
@@ -85,47 +89,51 @@ import {
|
|
|
85
89
|
setRateLimiter,
|
|
86
90
|
unsafeRevealSecret,
|
|
87
91
|
validateMcpRuntimeServerName
|
|
88
|
-
} from "./chunk-
|
|
92
|
+
} from "./chunk-HQXQCIT2.js";
|
|
89
93
|
import {
|
|
90
94
|
isLoopbackBind
|
|
91
95
|
} from "./chunk-RXFQM6FQ.js";
|
|
92
96
|
import {
|
|
93
97
|
createDaemonStatusProvider
|
|
94
|
-
} from "./chunk-
|
|
95
|
-
import "./chunk-
|
|
98
|
+
} from "./chunk-U6OPT4H2.js";
|
|
99
|
+
import "./chunk-LXXMOYPL.js";
|
|
100
|
+
import "./chunk-K2GBHL73.js";
|
|
96
101
|
import "./chunk-E5Z2AVNV.js";
|
|
97
102
|
import {
|
|
98
103
|
createWorkspaceProvidersStatusProvider
|
|
99
|
-
} from "./chunk-
|
|
104
|
+
} from "./chunk-ECZFTRTP.js";
|
|
100
105
|
import {
|
|
101
106
|
getAuthTypeFromEnv,
|
|
102
107
|
resolveCliGenerationConfig
|
|
103
|
-
} from "./chunk-
|
|
108
|
+
} from "./chunk-6Z5NRZVU.js";
|
|
104
109
|
import {
|
|
105
110
|
snapshotProcessEnv
|
|
106
|
-
} from "./chunk-
|
|
111
|
+
} from "./chunk-2YSZE74N.js";
|
|
107
112
|
import {
|
|
108
113
|
createWorkspaceSkillsStatusProvider
|
|
109
|
-
} from "./chunk-
|
|
114
|
+
} from "./chunk-GG6RSNWS.js";
|
|
110
115
|
import "./chunk-2W3OOD4W.js";
|
|
111
116
|
import {
|
|
112
117
|
EMPTY_WORKSPACE_VOICE_UPDATE_ERROR,
|
|
118
|
+
MAX_WORKSPACE_SKILL_NAME_LENGTH,
|
|
119
|
+
WorkspaceSkillManagementError,
|
|
113
120
|
WorkspaceVoiceError,
|
|
114
121
|
buildWorkspaceVoiceSettingsWrites,
|
|
115
122
|
buildWorkspaceVoiceStatus,
|
|
116
123
|
createDaemonWorkspaceService,
|
|
117
124
|
hasConfiguredBatchVoiceTranscriptionModel,
|
|
118
125
|
transcribeWorkspaceVoiceAudio,
|
|
126
|
+
validateWorkspaceSkillName,
|
|
119
127
|
validateWorkspaceVoiceState,
|
|
120
128
|
voiceSettingsScopeToWire
|
|
121
|
-
} from "./chunk-
|
|
129
|
+
} from "./chunk-FSJGBUQI.js";
|
|
122
130
|
import {
|
|
123
131
|
PermissionRulesValidationError,
|
|
124
132
|
buildPermissionSettings,
|
|
125
133
|
isPermissionRuleType,
|
|
126
134
|
normalizePermissionRules,
|
|
127
135
|
readPermissionRuleSet
|
|
128
|
-
} from "./chunk-
|
|
136
|
+
} from "./chunk-57RWF6R7.js";
|
|
129
137
|
import {
|
|
130
138
|
assertVoiceBaseUrlNetworkAllowed,
|
|
131
139
|
isStreamingVoiceModel,
|
|
@@ -133,13 +141,13 @@ import {
|
|
|
133
141
|
resolveVoiceTranscriptionConfig,
|
|
134
142
|
sanitizeVoiceErrorMessage,
|
|
135
143
|
transcribeVoiceAudio
|
|
136
|
-
} from "./chunk-
|
|
144
|
+
} from "./chunk-6ITLKEOZ.js";
|
|
137
145
|
import {
|
|
138
146
|
isVoiceEnabled,
|
|
139
147
|
isVoiceMode,
|
|
140
148
|
readVoiceModel
|
|
141
|
-
} from "./chunk-
|
|
142
|
-
import "./chunk-
|
|
149
|
+
} from "./chunk-AEKYFMYE.js";
|
|
150
|
+
import "./chunk-F2RR4HO2.js";
|
|
143
151
|
import {
|
|
144
152
|
WorkspacePermissionRulesSessionRequiredError,
|
|
145
153
|
WorkspaceSettingsPartialPersistError,
|
|
@@ -148,24 +156,24 @@ import {
|
|
|
148
156
|
} from "./chunk-OA4JVLSA.js";
|
|
149
157
|
import {
|
|
150
158
|
createTotalSessionAdmissionController
|
|
151
|
-
} from "./chunk-
|
|
159
|
+
} from "./chunk-R3VWUU2E.js";
|
|
152
160
|
import {
|
|
153
161
|
createSingleWorkspaceRegistry,
|
|
154
162
|
createWorkspaceSessionOwnerIndex
|
|
155
|
-
} from "./chunk-
|
|
163
|
+
} from "./chunk-W7H223ZZ.js";
|
|
156
164
|
import "./chunk-GRC5HGPI.js";
|
|
157
165
|
import {
|
|
158
166
|
SessionArtifactAuthorizationError,
|
|
159
167
|
SessionArtifactValidationError,
|
|
160
|
-
createAcpSessionBridge
|
|
161
|
-
|
|
162
|
-
|
|
168
|
+
createAcpSessionBridge,
|
|
169
|
+
parseSessionSource
|
|
170
|
+
} from "./chunk-KEVDWH3U.js";
|
|
171
|
+
import "./chunk-T3W4SDRB.js";
|
|
163
172
|
import {
|
|
164
173
|
EVENT_SCHEMA_VERSION,
|
|
165
174
|
SubscriberLimitExceededError
|
|
166
175
|
} from "./chunk-6RLROE6G.js";
|
|
167
176
|
import "./chunk-COH43MRJ.js";
|
|
168
|
-
import "./chunk-OCPBI7J5.js";
|
|
169
177
|
import {
|
|
170
178
|
BranchWhilePromptActiveError,
|
|
171
179
|
CancelSentinelCollisionError,
|
|
@@ -186,6 +194,7 @@ import {
|
|
|
186
194
|
SessionBusyError,
|
|
187
195
|
SessionConflictError,
|
|
188
196
|
SessionLimitExceededError,
|
|
197
|
+
SessionNotArchivedError,
|
|
189
198
|
SessionNotFoundError,
|
|
190
199
|
SessionShellClientRequiredError,
|
|
191
200
|
SessionShellDisabledError,
|
|
@@ -196,39 +205,44 @@ import {
|
|
|
196
205
|
WorkspaceInitRaceError,
|
|
197
206
|
WorkspaceInitSymlinkError,
|
|
198
207
|
WorkspaceMismatchError
|
|
199
|
-
} from "./chunk-
|
|
208
|
+
} from "./chunk-X6YQWCIJ.js";
|
|
200
209
|
import "./chunk-WBL3FJEU.js";
|
|
201
210
|
import {
|
|
202
211
|
loadChannelsConfig
|
|
203
|
-
} from "./chunk-
|
|
204
|
-
import "./chunk-
|
|
212
|
+
} from "./chunk-3CL5SEDT.js";
|
|
213
|
+
import "./chunk-IVKLDHU6.js";
|
|
205
214
|
import "./chunk-57OAHC2Y.js";
|
|
206
215
|
import {
|
|
207
216
|
parseChannelWebhookConfigLenient
|
|
208
|
-
} from "./chunk-
|
|
209
|
-
import "./chunk-
|
|
217
|
+
} from "./chunk-Y72B36CP.js";
|
|
218
|
+
import "./chunk-FZRES4GK.js";
|
|
210
219
|
import "./chunk-V6WHFGST.js";
|
|
211
|
-
import "./chunk-
|
|
212
|
-
import "./chunk-TEGEBB2I.js";
|
|
220
|
+
import "./chunk-O2K6BLPZ.js";
|
|
213
221
|
import {
|
|
214
222
|
STATUS_SCHEMA_VERSION,
|
|
215
223
|
createIdleWorkspaceMemoryStatus,
|
|
216
224
|
mapDomainErrorToErrorKind
|
|
217
|
-
} from "./chunk-
|
|
225
|
+
} from "./chunk-URP6O2PP.js";
|
|
218
226
|
import {
|
|
219
227
|
MAX_REGISTERED_WORKSPACES,
|
|
220
228
|
WorkspaceRegistrationStoreCommittedError,
|
|
221
229
|
WorkspaceRegistrationStoreLimitError,
|
|
222
230
|
workspaceRegistrationId
|
|
223
|
-
} from "./chunk-
|
|
231
|
+
} from "./chunk-JUVTV4NF.js";
|
|
224
232
|
import {
|
|
225
233
|
MAX_WORKSPACE_PATH_LENGTH,
|
|
226
234
|
canonicalizeWorkspace,
|
|
227
235
|
canonicalizeWorkspaces
|
|
228
236
|
} from "./chunk-W7FJ3N32.js";
|
|
229
237
|
import {
|
|
230
|
-
|
|
231
|
-
|
|
238
|
+
MAX_CHANNEL_STARTUP_FAILURES,
|
|
239
|
+
MAX_CHANNEL_STARTUP_FAILURE_CHANNEL_LENGTH,
|
|
240
|
+
MAX_CHANNEL_STARTUP_FAILURE_CODE_LENGTH,
|
|
241
|
+
MAX_CHANNEL_STARTUP_FAILURE_MESSAGE_LENGTH,
|
|
242
|
+
QWEN_SERVER_TOKEN_ENV,
|
|
243
|
+
isChannelWebhookEnqueueError,
|
|
244
|
+
normalizeWorkerDiagnostic
|
|
245
|
+
} from "./chunk-JDIUK2Y3.js";
|
|
232
246
|
import {
|
|
233
247
|
normalizeServeChannelSelection
|
|
234
248
|
} from "./chunk-TJTKSVIV.js";
|
|
@@ -236,11 +250,10 @@ import {
|
|
|
236
250
|
redactLogCredentials
|
|
237
251
|
} from "./chunk-M5GB774H.js";
|
|
238
252
|
import "./chunk-5HBA2Z7V.js";
|
|
239
|
-
import {
|
|
240
|
-
isChannelWebhookEnqueueError
|
|
241
|
-
} from "./chunk-OJAMDVF5.js";
|
|
242
253
|
import "./chunk-T2NCM2ET.js";
|
|
243
|
-
import
|
|
254
|
+
import {
|
|
255
|
+
sanitizeLogText
|
|
256
|
+
} from "./chunk-ATJ7H5AS.js";
|
|
244
257
|
import "./chunk-UDXSXLER.js";
|
|
245
258
|
import {
|
|
246
259
|
getDialogSettingKeys,
|
|
@@ -251,18 +264,18 @@ import {
|
|
|
251
264
|
getWritableScopes,
|
|
252
265
|
loadSettings,
|
|
253
266
|
validateSettingValue
|
|
254
|
-
} from "./chunk-
|
|
267
|
+
} from "./chunk-C5NSOSF4.js";
|
|
255
268
|
import "./chunk-RKUWKYED.js";
|
|
256
269
|
import {
|
|
257
270
|
SUPPORTED_LANGUAGES
|
|
258
|
-
} from "./chunk-
|
|
259
|
-
import "./chunk-
|
|
271
|
+
} from "./chunk-HIMIG6PI.js";
|
|
272
|
+
import "./chunk-336KPNNV.js";
|
|
260
273
|
import "./chunk-GOXKNSDZ.js";
|
|
261
274
|
import "./chunk-IDS7MSUP.js";
|
|
262
275
|
import "./chunk-QRUIS3DN.js";
|
|
263
276
|
import {
|
|
264
277
|
getWorkspaceTrustStatus
|
|
265
|
-
} from "./chunk-
|
|
278
|
+
} from "./chunk-LSFVUGXT.js";
|
|
266
279
|
import "./chunk-ALGGS7UH.js";
|
|
267
280
|
import {
|
|
268
281
|
isWithinRoot as isWithinRoot2
|
|
@@ -270,7 +283,7 @@ import {
|
|
|
270
283
|
import {
|
|
271
284
|
writeStderrLine
|
|
272
285
|
} from "./chunk-YUZI3WAC.js";
|
|
273
|
-
import "./chunk-
|
|
286
|
+
import "./chunk-KTKETHMY.js";
|
|
274
287
|
import "./chunk-VJNBRRZG.js";
|
|
275
288
|
import {
|
|
276
289
|
ALL_PROVIDERS,
|
|
@@ -284,7 +297,9 @@ import {
|
|
|
284
297
|
InvalidSessionTranscriptCursorError,
|
|
285
298
|
ModelsConfig,
|
|
286
299
|
RUNTIME_MCP_IF_ABSENT_CONFIG_FLAG,
|
|
300
|
+
SESSION_TRANSCRIPT_MAX_INDEX_BYTES,
|
|
287
301
|
SESSION_TRANSCRIPT_MAX_LIMIT,
|
|
302
|
+
SESSION_TRANSCRIPT_MAX_PAGE_BYTES,
|
|
288
303
|
SessionOrganizationError,
|
|
289
304
|
SessionOrganizationService,
|
|
290
305
|
SessionService,
|
|
@@ -315,18 +330,18 @@ import {
|
|
|
315
330
|
stripTerminalControlSequences,
|
|
316
331
|
watchRepoBranch,
|
|
317
332
|
writeWorkspaceContextFile
|
|
318
|
-
} from "./chunk-
|
|
333
|
+
} from "./chunk-3YJZ6WNY.js";
|
|
334
|
+
import "./chunk-T4TZQJ7W.js";
|
|
319
335
|
import "./chunk-H6XPXXMH.js";
|
|
320
336
|
import "./chunk-5M6IDOMF.js";
|
|
321
337
|
import {
|
|
322
338
|
MAX_JOBS,
|
|
323
339
|
nextDurableFireMs
|
|
324
|
-
} from "./chunk-
|
|
325
|
-
import "./chunk-
|
|
326
|
-
import "./chunk-
|
|
327
|
-
import "./chunk-
|
|
340
|
+
} from "./chunk-LKR7QQ63.js";
|
|
341
|
+
import "./chunk-4XCVGEEX.js";
|
|
342
|
+
import "./chunk-XSPFQQRE.js";
|
|
343
|
+
import "./chunk-4RPARQ5D.js";
|
|
328
344
|
import "./chunk-E2UVIFI2.js";
|
|
329
|
-
import "./chunk-6OATMEYN.js";
|
|
330
345
|
import {
|
|
331
346
|
nextFireTime,
|
|
332
347
|
parseCron
|
|
@@ -339,7 +354,7 @@ import {
|
|
|
339
354
|
readCronTasks,
|
|
340
355
|
taskHasLegacyCondition,
|
|
341
356
|
updateCronTasks
|
|
342
|
-
} from "./chunk-
|
|
357
|
+
} from "./chunk-J2MKYJKZ.js";
|
|
343
358
|
import "./chunk-SZRN75WQ.js";
|
|
344
359
|
import "./chunk-HTO4JFDZ.js";
|
|
345
360
|
import "./chunk-CPBF7KYF.js";
|
|
@@ -347,12 +362,12 @@ import {
|
|
|
347
362
|
APPROVAL_MODES,
|
|
348
363
|
SubagentError,
|
|
349
364
|
SubagentErrorCode
|
|
350
|
-
} from "./chunk-
|
|
365
|
+
} from "./chunk-VNN3JNYT.js";
|
|
351
366
|
import "./chunk-6AM5D4ME.js";
|
|
352
|
-
import "./chunk-
|
|
353
|
-
import "./chunk-
|
|
354
|
-
import "./chunk-
|
|
355
|
-
import "./chunk-
|
|
367
|
+
import "./chunk-OSSDHJDU.js";
|
|
368
|
+
import "./chunk-SGPFJMRP.js";
|
|
369
|
+
import "./chunk-335ECZTA.js";
|
|
370
|
+
import "./chunk-JCJPZMJV.js";
|
|
356
371
|
import {
|
|
357
372
|
addDaemonRequestAttribute,
|
|
358
373
|
decodeBufferWithEncodingInfo,
|
|
@@ -366,15 +381,15 @@ import {
|
|
|
366
381
|
recordDaemonHttpRequest,
|
|
367
382
|
recordDaemonHttpResponse,
|
|
368
383
|
withDaemonRequestSpan
|
|
369
|
-
} from "./chunk-
|
|
384
|
+
} from "./chunk-66IT3EY2.js";
|
|
370
385
|
import "./chunk-4WKAA4KS.js";
|
|
371
386
|
import "./chunk-CR3C7WXL.js";
|
|
372
|
-
import "./chunk-
|
|
387
|
+
import "./chunk-U2LNTX56.js";
|
|
373
388
|
import "./chunk-VGC4I5JJ.js";
|
|
374
|
-
import "./chunk-
|
|
375
|
-
import "./chunk-
|
|
376
|
-
import "./chunk-
|
|
377
|
-
import "./chunk-
|
|
389
|
+
import "./chunk-FUTHTZVV.js";
|
|
390
|
+
import "./chunk-4CA4WUMS.js";
|
|
391
|
+
import "./chunk-WEPXQKGP.js";
|
|
392
|
+
import "./chunk-ANRANWVE.js";
|
|
378
393
|
import {
|
|
379
394
|
QwenOAuth2Client,
|
|
380
395
|
QwenOAuthPollError,
|
|
@@ -383,28 +398,28 @@ import {
|
|
|
383
398
|
isDeviceAuthorizationSuccess,
|
|
384
399
|
isDeviceTokenPending,
|
|
385
400
|
isDeviceTokenSuccess
|
|
386
|
-
} from "./chunk-
|
|
387
|
-
import "./chunk-
|
|
401
|
+
} from "./chunk-G274ETR6.js";
|
|
402
|
+
import "./chunk-Z2LBNX3R.js";
|
|
388
403
|
import "./chunk-JESCGQM3.js";
|
|
389
|
-
import "./chunk-
|
|
404
|
+
import "./chunk-VAJS2E2D.js";
|
|
390
405
|
import "./chunk-XVNQMZ2I.js";
|
|
391
|
-
import "./chunk-
|
|
392
|
-
import "./chunk-
|
|
406
|
+
import "./chunk-FEOZBUMT.js";
|
|
407
|
+
import "./chunk-CMVFTMRD.js";
|
|
393
408
|
import "./chunk-A4UCTEB5.js";
|
|
394
409
|
import "./chunk-XWRJCPHC.js";
|
|
395
|
-
import "./chunk-
|
|
410
|
+
import "./chunk-TYQMGACW.js";
|
|
396
411
|
import {
|
|
397
412
|
import_websocket_server
|
|
398
413
|
} from "./chunk-TYAMGABM.js";
|
|
399
414
|
import "./chunk-FCMNKVXT.js";
|
|
400
415
|
import "./chunk-DJ2GSRLV.js";
|
|
401
|
-
import "./chunk-
|
|
416
|
+
import "./chunk-4CHDYDG3.js";
|
|
402
417
|
import {
|
|
403
418
|
FatalConfigError,
|
|
404
419
|
Storage,
|
|
405
420
|
createDebugLogger,
|
|
406
421
|
runWithoutDebugLogSession
|
|
407
|
-
} from "./chunk-
|
|
422
|
+
} from "./chunk-UE5TZ55T.js";
|
|
408
423
|
import "./chunk-75DOP5OR.js";
|
|
409
424
|
import "./chunk-DMTGGOSA.js";
|
|
410
425
|
import "./chunk-YQ3U5MUC.js";
|
|
@@ -2900,7 +2915,7 @@ async function handleSetupGithub(req, res, deps) {
|
|
|
2900
2915
|
const result = await setupGithub({
|
|
2901
2916
|
cwd: deps.boundWorkspace,
|
|
2902
2917
|
workspaceRoot: deps.boundWorkspace,
|
|
2903
|
-
proxy: resolveSetupGithubProxy(deps.boundWorkspace),
|
|
2918
|
+
proxy: resolveSetupGithubProxy(deps.boundWorkspace, deps.env),
|
|
2904
2919
|
abortSignal: requestAbortSignal(req, res),
|
|
2905
2920
|
fileOps: createSetupGithubFileOps(factory, ROUTE, originatorClientId)
|
|
2906
2921
|
});
|
|
@@ -3118,14 +3133,14 @@ function setupGithubEventData(result) {
|
|
|
3118
3133
|
};
|
|
3119
3134
|
}
|
|
3120
3135
|
__name(setupGithubEventData, "setupGithubEventData");
|
|
3121
|
-
function resolveSetupGithubProxy(boundWorkspace) {
|
|
3136
|
+
function resolveSetupGithubProxy(boundWorkspace, env) {
|
|
3122
3137
|
const settings = loadSettings(boundWorkspace, { skipLoadEnvironment: true });
|
|
3123
3138
|
const trustState = getWorkspaceTrustStatus(
|
|
3124
3139
|
settingsForSetupGithubTrust(settings),
|
|
3125
3140
|
boundWorkspace
|
|
3126
3141
|
).effective.state;
|
|
3127
3142
|
const settingsProxy = trustState === "trusted" ? settings.merged.proxy : settings.user.settings.proxy || settings.system.settings.proxy || settings.systemDefaults.settings.proxy;
|
|
3128
|
-
return settingsProxy ||
|
|
3143
|
+
return settingsProxy || env["HTTPS_PROXY"] || env["https_proxy"] || env["HTTP_PROXY"] || env["http_proxy"];
|
|
3129
3144
|
}
|
|
3130
3145
|
__name(resolveSetupGithubProxy, "resolveSetupGithubProxy");
|
|
3131
3146
|
function settingsForSetupGithubTrust(settings) {
|
|
@@ -6226,6 +6241,21 @@ async function assertSessionLoadable(workspaceCwd, sessionId) {
|
|
|
6226
6241
|
return location;
|
|
6227
6242
|
}
|
|
6228
6243
|
__name(assertSessionLoadable, "assertSessionLoadable");
|
|
6244
|
+
async function assertSessionArchived(workspaceCwd, sessionId) {
|
|
6245
|
+
const location = await new SessionService(workspaceCwd).getSessionLocation(
|
|
6246
|
+
sessionId
|
|
6247
|
+
);
|
|
6248
|
+
if (location === "active") {
|
|
6249
|
+
throw new SessionNotArchivedError(sessionId);
|
|
6250
|
+
}
|
|
6251
|
+
if (location === "conflict") {
|
|
6252
|
+
throw new SessionConflictError(sessionId);
|
|
6253
|
+
}
|
|
6254
|
+
if (location === void 0) {
|
|
6255
|
+
throw new SessionNotFoundError(sessionId);
|
|
6256
|
+
}
|
|
6257
|
+
}
|
|
6258
|
+
__name(assertSessionArchived, "assertSessionArchived");
|
|
6229
6259
|
function isSessionNotFoundError(err) {
|
|
6230
6260
|
return err instanceof SessionNotFoundError || err instanceof Error && err.name === "SessionNotFoundError";
|
|
6231
6261
|
}
|
|
@@ -6928,9 +6958,10 @@ function rpcErrorFrame(id, err) {
|
|
|
6928
6958
|
__name(rpcErrorFrame, "rpcErrorFrame");
|
|
6929
6959
|
var ACP_PROTOCOL_VERSION = 1;
|
|
6930
6960
|
var AcpDispatcher = class {
|
|
6931
|
-
constructor(bridge, boundWorkspace, workspace, workspaceRememberLane, fsFactory, deviceFlowRegistry, sessionShellCommandEnabled = false, registry, archiveCoordinator = new SessionArchiveCoordinator()) {
|
|
6961
|
+
constructor(bridge, boundWorkspace, env, workspace, workspaceRememberLane, fsFactory, deviceFlowRegistry, sessionShellCommandEnabled = false, registry, archiveCoordinator = new SessionArchiveCoordinator()) {
|
|
6932
6962
|
this.bridge = bridge;
|
|
6933
6963
|
this.boundWorkspace = boundWorkspace;
|
|
6964
|
+
this.env = env;
|
|
6934
6965
|
this.workspace = workspace;
|
|
6935
6966
|
this.workspaceRememberLane = workspaceRememberLane;
|
|
6936
6967
|
this.fsFactory = fsFactory;
|
|
@@ -6944,8 +6975,14 @@ var AcpDispatcher = class {
|
|
|
6944
6975
|
__name(this, "AcpDispatcher");
|
|
6945
6976
|
}
|
|
6946
6977
|
agentManager;
|
|
6947
|
-
killOrphanSession(sessionId) {
|
|
6948
|
-
void this.bridge.killSession(sessionId, { requireZeroAttaches: true }).
|
|
6978
|
+
killOrphanSession(sessionId, removePersistedSession = false) {
|
|
6979
|
+
void this.bridge.killSession(sessionId, { requireZeroAttaches: true }).then(async (killed) => {
|
|
6980
|
+
if (killed && removePersistedSession) {
|
|
6981
|
+
await new SessionService(this.boundWorkspace).removeSession(
|
|
6982
|
+
sessionId
|
|
6983
|
+
);
|
|
6984
|
+
}
|
|
6985
|
+
}).catch(
|
|
6949
6986
|
(err) => writeStderrLine(
|
|
6950
6987
|
`qwen serve: /acp orphan killSession(${logSafe(sessionId)}) failed: ${logSafe(errMsg(err))}`
|
|
6951
6988
|
)
|
|
@@ -7229,26 +7266,40 @@ var AcpDispatcher = class {
|
|
|
7229
7266
|
return;
|
|
7230
7267
|
case "session/new": {
|
|
7231
7268
|
const cwd = parseOptionalWorkspaceCwd2(params, this.boundWorkspace);
|
|
7269
|
+
const source = parseSessionSource(
|
|
7270
|
+
params["sourceType"],
|
|
7271
|
+
params["sourceId"]
|
|
7272
|
+
);
|
|
7273
|
+
if ("error" in source) {
|
|
7274
|
+
if (id !== void 0) {
|
|
7275
|
+
conn.sendConn(error(id, RPC.INVALID_PARAMS, source.error));
|
|
7276
|
+
}
|
|
7277
|
+
return;
|
|
7278
|
+
}
|
|
7232
7279
|
const session = await this.bridge.spawnOrAttach({
|
|
7233
7280
|
workspaceCwd: cwd,
|
|
7234
7281
|
clientId: conn.clientId,
|
|
7235
|
-
sessionScope: "thread"
|
|
7282
|
+
sessionScope: "thread",
|
|
7283
|
+
...source
|
|
7236
7284
|
});
|
|
7237
7285
|
if (conn.destroyed) {
|
|
7238
|
-
this.killOrphanSession(session.sessionId);
|
|
7286
|
+
this.killOrphanSession(session.sessionId, true);
|
|
7239
7287
|
return;
|
|
7240
7288
|
}
|
|
7241
7289
|
conn.getOrCreateSession(session.sessionId).clientId = session.clientId;
|
|
7242
7290
|
conn.ownSession(session.sessionId);
|
|
7243
7291
|
const configOptions = await this.configOptionsFor(session.sessionId);
|
|
7244
7292
|
if (conn.destroyed) {
|
|
7245
|
-
this.killOrphanSession(session.sessionId);
|
|
7293
|
+
this.killOrphanSession(session.sessionId, true);
|
|
7246
7294
|
return;
|
|
7247
7295
|
}
|
|
7248
7296
|
const models = this.extractModelState(configOptions);
|
|
7249
7297
|
const modes = this.extractModeState(configOptions);
|
|
7250
7298
|
this.replyConn(conn, id, {
|
|
7251
7299
|
sessionId: session.sessionId,
|
|
7300
|
+
...session.sourceType ? { sourceType: session.sourceType } : {},
|
|
7301
|
+
...session.sourceId !== void 0 ? { sourceId: session.sourceId } : {},
|
|
7302
|
+
...session.sourcePersisted !== void 0 ? { sourcePersisted: session.sourcePersisted } : {},
|
|
7252
7303
|
...configOptions ? { configOptions } : {},
|
|
7253
7304
|
...models ? { models } : {},
|
|
7254
7305
|
...modes ? { modes } : {}
|
|
@@ -7283,20 +7334,20 @@ var AcpDispatcher = class {
|
|
|
7283
7334
|
[sessionId],
|
|
7284
7335
|
async () => {
|
|
7285
7336
|
await assertSessionLoadable(cwd, sessionId);
|
|
7286
|
-
const
|
|
7337
|
+
const metadata = await new SessionService(
|
|
7287
7338
|
cwd
|
|
7288
|
-
).
|
|
7339
|
+
).readCreationMetadata(sessionId);
|
|
7289
7340
|
return method === "session/load" ? await this.bridge.loadSession({
|
|
7290
7341
|
sessionId,
|
|
7291
7342
|
workspaceCwd: cwd,
|
|
7292
7343
|
clientId: conn.clientId,
|
|
7293
7344
|
historyReplay: "response",
|
|
7294
|
-
...
|
|
7345
|
+
...metadata
|
|
7295
7346
|
}) : await this.bridge.resumeSession({
|
|
7296
7347
|
sessionId,
|
|
7297
7348
|
workspaceCwd: cwd,
|
|
7298
7349
|
clientId: conn.clientId,
|
|
7299
|
-
...
|
|
7350
|
+
...metadata
|
|
7300
7351
|
});
|
|
7301
7352
|
}
|
|
7302
7353
|
);
|
|
@@ -7395,6 +7446,13 @@ var AcpDispatcher = class {
|
|
|
7395
7446
|
);
|
|
7396
7447
|
}
|
|
7397
7448
|
}
|
|
7449
|
+
const parsedSource = parseSessionSource(
|
|
7450
|
+
params["sourceType"],
|
|
7451
|
+
params["sourceId"]
|
|
7452
|
+
);
|
|
7453
|
+
if ("error" in parsedSource) {
|
|
7454
|
+
throw new AcpParamError(parsedSource.error);
|
|
7455
|
+
}
|
|
7398
7456
|
const result = await listWorkspaceSessionsForResponse(
|
|
7399
7457
|
this.bridge,
|
|
7400
7458
|
workspaceCwd,
|
|
@@ -7404,7 +7462,8 @@ var AcpDispatcher = class {
|
|
|
7404
7462
|
archiveState,
|
|
7405
7463
|
view,
|
|
7406
7464
|
group,
|
|
7407
|
-
parentSessionId
|
|
7465
|
+
parentSessionId,
|
|
7466
|
+
...parsedSource
|
|
7408
7467
|
}
|
|
7409
7468
|
);
|
|
7410
7469
|
this.replyConn(conn, id, {
|
|
@@ -7417,6 +7476,8 @@ var AcpDispatcher = class {
|
|
|
7417
7476
|
displayName: s.displayName,
|
|
7418
7477
|
title: s.displayName,
|
|
7419
7478
|
...s.parentSessionId !== void 0 ? { parentSessionId: s.parentSessionId } : {},
|
|
7479
|
+
...s.sourceType !== void 0 ? { sourceType: s.sourceType } : {},
|
|
7480
|
+
...s.sourceId !== void 0 ? { sourceId: s.sourceId } : {},
|
|
7420
7481
|
clientCount: s.clientCount,
|
|
7421
7482
|
hasActivePrompt: s.hasActivePrompt,
|
|
7422
7483
|
isArchived: s.isArchived === true,
|
|
@@ -8277,7 +8338,7 @@ var AcpDispatcher = class {
|
|
|
8277
8338
|
const result = await setupGithub({
|
|
8278
8339
|
cwd: this.boundWorkspace,
|
|
8279
8340
|
workspaceRoot: this.boundWorkspace,
|
|
8280
|
-
proxy: resolveSetupGithubProxy(this.boundWorkspace),
|
|
8341
|
+
proxy: resolveSetupGithubProxy(this.boundWorkspace, this.env),
|
|
8281
8342
|
abortSignal: conn.abortSignal,
|
|
8282
8343
|
fileOps: createSetupGithubFileOps(
|
|
8283
8344
|
this.fsFactory,
|
|
@@ -11748,11 +11809,11 @@ function delay(ms) {
|
|
|
11748
11809
|
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
11749
11810
|
}
|
|
11750
11811
|
__name(delay, "delay");
|
|
11751
|
-
function buildChromeDevToolsMcpRuntimeConfig(localPort, hostname) {
|
|
11812
|
+
function buildChromeDevToolsMcpRuntimeConfig(localPort, hostname, env) {
|
|
11752
11813
|
if (localPort === void 0 || !Number.isInteger(localPort) || localPort <= 0) {
|
|
11753
11814
|
return void 0;
|
|
11754
11815
|
}
|
|
11755
|
-
const command = resolveCdpMcpCommand(
|
|
11816
|
+
const command = resolveCdpMcpCommand(env);
|
|
11756
11817
|
if (!command) {
|
|
11757
11818
|
writeStderrLine(
|
|
11758
11819
|
`qwen serve: set ${QWEN_CDP_MCP_COMMAND_ENV} to enable browser automation MCP (no adapter is bundled)`
|
|
@@ -11858,9 +11919,18 @@ function workspaceRateLimitKey(mount, clientKey) {
|
|
|
11858
11919
|
return JSON.stringify([clientKey, mount.rateLimitScope]);
|
|
11859
11920
|
}
|
|
11860
11921
|
__name(workspaceRateLimitKey, "workspaceRateLimitKey");
|
|
11922
|
+
function runtimeEffectiveEnv(runtime, daemonEnv) {
|
|
11923
|
+
if (runtime.env.mode === "runtime-overlay") {
|
|
11924
|
+
return runtime.env.effectiveEnv ?? {};
|
|
11925
|
+
}
|
|
11926
|
+
return runtime.env.effectiveEnv ?? daemonEnv;
|
|
11927
|
+
}
|
|
11928
|
+
__name(runtimeEffectiveEnv, "runtimeEffectiveEnv");
|
|
11861
11929
|
function mountAcpHttp(app, bridge, opts) {
|
|
11862
11930
|
const enabled = opts.enabled ?? resolveAcpHttpEnabled();
|
|
11863
11931
|
if (!enabled) return void 0;
|
|
11932
|
+
const daemonEnv = opts.daemonEnv ?? process.env;
|
|
11933
|
+
const primaryEnv = opts.workspaceRegistry ? runtimeEffectiveEnv(opts.workspaceRegistry.primary, daemonEnv) : daemonEnv;
|
|
11864
11934
|
const path15 = opts.path ?? "/acp";
|
|
11865
11935
|
const dispatcherRef = {};
|
|
11866
11936
|
let disposed = false;
|
|
@@ -11950,7 +12020,8 @@ function mountAcpHttp(app, bridge, opts) {
|
|
|
11950
12020
|
}
|
|
11951
12021
|
const runtimeConfig = buildChromeDevToolsMcpRuntimeConfig(
|
|
11952
12022
|
localPort,
|
|
11953
|
-
opts.hostname
|
|
12023
|
+
opts.hostname,
|
|
12024
|
+
daemonEnv
|
|
11954
12025
|
);
|
|
11955
12026
|
if (!runtimeConfig) {
|
|
11956
12027
|
cdpMcpTerminalSkipLogged = true;
|
|
@@ -12009,6 +12080,7 @@ function mountAcpHttp(app, bridge, opts) {
|
|
|
12009
12080
|
const dispatcher = new AcpDispatcher(
|
|
12010
12081
|
bridge,
|
|
12011
12082
|
opts.boundWorkspace,
|
|
12083
|
+
primaryEnv,
|
|
12012
12084
|
opts.workspace,
|
|
12013
12085
|
opts.workspaceRememberLane,
|
|
12014
12086
|
opts.fsFactory,
|
|
@@ -12297,6 +12369,7 @@ function mountAcpHttp(app, bridge, opts) {
|
|
|
12297
12369
|
const secondaryDispatcher = new AcpDispatcher(
|
|
12298
12370
|
rt.bridge,
|
|
12299
12371
|
rt.workspaceCwd,
|
|
12372
|
+
runtimeEffectiveEnv(rt, daemonEnv),
|
|
12300
12373
|
rt.workspaceService,
|
|
12301
12374
|
workspaceRememberLane,
|
|
12302
12375
|
rt.routeFileSystemFactory,
|
|
@@ -14402,7 +14475,13 @@ __name(getDemoHtml, "getDemoHtml");
|
|
|
14402
14475
|
|
|
14403
14476
|
// packages/cli/src/serve/routes/health-demo.ts
|
|
14404
14477
|
function createHealthDemoRoutes(deps) {
|
|
14405
|
-
const {
|
|
14478
|
+
const {
|
|
14479
|
+
opts,
|
|
14480
|
+
getPort,
|
|
14481
|
+
workspaceRegistry,
|
|
14482
|
+
getActiveSseCount: getActiveSseCount2,
|
|
14483
|
+
getRateLimiter
|
|
14484
|
+
} = deps;
|
|
14406
14485
|
const demoHandler = /* @__PURE__ */ __name((_req, res) => {
|
|
14407
14486
|
try {
|
|
14408
14487
|
res.type("html").set("X-Frame-Options", "DENY").set(
|
|
@@ -14417,32 +14496,55 @@ function createHealthDemoRoutes(deps) {
|
|
|
14417
14496
|
}
|
|
14418
14497
|
}, "demoHandler");
|
|
14419
14498
|
const healthHandler = /* @__PURE__ */ __name((req, res) => {
|
|
14420
|
-
|
|
14421
|
-
const deep = deepQuery === "1" || deepQuery === "true" || deepQuery === "";
|
|
14422
|
-
if (!deep) {
|
|
14499
|
+
if (!isDeepHealthQuery(req.query["deep"])) {
|
|
14423
14500
|
res.status(200).json({ status: "ok" });
|
|
14424
14501
|
return;
|
|
14425
14502
|
}
|
|
14503
|
+
let failedWorkspaceId;
|
|
14426
14504
|
try {
|
|
14427
|
-
const
|
|
14505
|
+
const runtimes = workspaceRegistry.listManaged();
|
|
14506
|
+
let sessions = 0;
|
|
14507
|
+
let pendingPermissions = 0;
|
|
14508
|
+
let activePrompts = 0;
|
|
14509
|
+
let channelAlive = false;
|
|
14510
|
+
let lastActivity = null;
|
|
14511
|
+
for (const runtime of runtimes) {
|
|
14512
|
+
failedWorkspaceId = runtime.workspaceId;
|
|
14513
|
+
const bridge = runtime.bridge;
|
|
14514
|
+
const runtimeSessions = bridge.sessionCount;
|
|
14515
|
+
const runtimePendingPermissions = bridge.pendingPermissionCount;
|
|
14516
|
+
const runtimeActivePrompts = bridge.activePromptCount;
|
|
14517
|
+
const runtimeChannelAlive = bridge.isChannelLive();
|
|
14518
|
+
const runtimeLastActivity = bridge.lastActivityAt;
|
|
14519
|
+
sessions += runtimeSessions;
|
|
14520
|
+
pendingPermissions += runtimePendingPermissions;
|
|
14521
|
+
activePrompts += runtimeActivePrompts;
|
|
14522
|
+
channelAlive = channelAlive || runtimeChannelAlive;
|
|
14523
|
+
if (runtimeLastActivity !== null && (lastActivity === null || runtimeLastActivity > lastActivity)) {
|
|
14524
|
+
lastActivity = runtimeLastActivity;
|
|
14525
|
+
}
|
|
14526
|
+
failedWorkspaceId = void 0;
|
|
14527
|
+
}
|
|
14428
14528
|
const now = Date.now();
|
|
14429
14529
|
const rateLimiter = getRateLimiter();
|
|
14430
14530
|
res.status(200).json({
|
|
14431
14531
|
status: "ok",
|
|
14432
|
-
|
|
14433
|
-
|
|
14434
|
-
|
|
14532
|
+
workspaceCount: runtimes.length,
|
|
14533
|
+
sessions,
|
|
14534
|
+
pendingPermissions,
|
|
14535
|
+
activePrompts,
|
|
14435
14536
|
connectedClients: getActiveSseCount2(),
|
|
14436
|
-
channelAlive
|
|
14537
|
+
channelAlive,
|
|
14437
14538
|
lastActivityAt: lastActivity !== null ? new Date(lastActivity).toISOString() : null,
|
|
14438
14539
|
idleSinceMs: lastActivity !== null ? now - lastActivity : null,
|
|
14439
14540
|
...rateLimiter ? { rateLimitHits: rateLimiter.getHitCounts() } : {}
|
|
14440
14541
|
});
|
|
14441
14542
|
} catch (err) {
|
|
14543
|
+
const workspaceContext = failedWorkspaceId !== void 0 ? ` for workspace ${JSON.stringify(failedWorkspaceId)}` : "";
|
|
14442
14544
|
writeStderrLine(
|
|
14443
|
-
`qwen serve: /health deep probe failed: ${err instanceof Error ? err.message : String(err)}`
|
|
14545
|
+
`qwen serve: /health deep probe failed${workspaceContext}: ${err instanceof Error ? err.message : String(err)}`
|
|
14444
14546
|
);
|
|
14445
|
-
res.status(503).json({ status: "degraded" });
|
|
14547
|
+
res.status(503).json({ status: "degraded", reason: "aggregation_failed" });
|
|
14446
14548
|
}
|
|
14447
14549
|
}, "healthHandler");
|
|
14448
14550
|
const loopback = isLoopbackBind(opts.hostname);
|
|
@@ -14950,6 +15052,7 @@ __name(registerWorkspaceAuthRoutes, "registerWorkspaceAuthRoutes");
|
|
|
14950
15052
|
|
|
14951
15053
|
// packages/cli/src/serve/routes/workspace-extensions.ts
|
|
14952
15054
|
init_esbuild_shims();
|
|
15055
|
+
import * as crypto2 from "node:crypto";
|
|
14953
15056
|
|
|
14954
15057
|
// packages/cli/src/serve/extension-operation-scheduler.ts
|
|
14955
15058
|
init_esbuild_shims();
|
|
@@ -15029,6 +15132,18 @@ init_esbuild_shims();
|
|
|
15029
15132
|
import * as crypto from "node:crypto";
|
|
15030
15133
|
var MAX_UNFINISHED_EXTENSION_OPERATIONS = 10;
|
|
15031
15134
|
var sanitizeDaemonMessage = /* @__PURE__ */ __name((message) => redactUrlCredentials(stripAnsiAndControl(message)), "sanitizeDaemonMessage");
|
|
15135
|
+
var redactExtensionDisplaySource = /* @__PURE__ */ __name((source) => {
|
|
15136
|
+
const redacted = redactUrlCredentials(source);
|
|
15137
|
+
if (/^[A-Za-z]:[\\/]/.test(redacted)) return redacted;
|
|
15138
|
+
try {
|
|
15139
|
+
const url = new URL(redacted);
|
|
15140
|
+
url.search = "";
|
|
15141
|
+
url.hash = "";
|
|
15142
|
+
return url.toString();
|
|
15143
|
+
} catch {
|
|
15144
|
+
return redacted;
|
|
15145
|
+
}
|
|
15146
|
+
}, "redactExtensionDisplaySource");
|
|
15032
15147
|
var EXTENSION_PREPARATION_CONCURRENCY = 2;
|
|
15033
15148
|
var EXTENSION_REFRESH_TIMEOUT_MS = 3e4;
|
|
15034
15149
|
var RECONCILE_SLOW_MS = 3e4;
|
|
@@ -15057,21 +15172,21 @@ function createExtensionsController(deps) {
|
|
|
15057
15172
|
unfinishedOperationCount -= 1;
|
|
15058
15173
|
};
|
|
15059
15174
|
}, "acquireOperationSlot");
|
|
15060
|
-
const createExtensionManager = /* @__PURE__ */ __name((workspaceDir = boundWorkspace, trustedOverride) => new ExtensionManager({
|
|
15175
|
+
const createExtensionManager = /* @__PURE__ */ __name((workspaceDir = boundWorkspace, trustedOverride, interactions) => new ExtensionManager({
|
|
15061
15176
|
workspaceDir,
|
|
15062
15177
|
isWorkspaceTrusted: trustedOverride ?? getWorkspaceTrustStatus(loadSettings(workspaceDir).merged, workspaceDir).effective.state === "trusted",
|
|
15063
15178
|
requestConsent: /* @__PURE__ */ __name(() => Promise.resolve(), "requestConsent"),
|
|
15064
15179
|
networkPolicy: "public",
|
|
15065
|
-
requestSetting:
|
|
15180
|
+
requestSetting: interactions?.requestSetting ?? (async (setting) => {
|
|
15066
15181
|
throw new Error(
|
|
15067
15182
|
`Extension setting "${setting.envVar}" requires interactive configuration and is not supported over the daemon install endpoint.`
|
|
15068
15183
|
);
|
|
15069
|
-
}
|
|
15070
|
-
requestChoicePlugin:
|
|
15184
|
+
}),
|
|
15185
|
+
requestChoicePlugin: interactions?.requestChoicePlugin ?? (async () => {
|
|
15071
15186
|
throw new Error(
|
|
15072
15187
|
"Marketplace plugin selection is not supported over the daemon install endpoint. Specify a plugin name in the source."
|
|
15073
15188
|
);
|
|
15074
|
-
}
|
|
15189
|
+
})
|
|
15075
15190
|
}), "createExtensionManager");
|
|
15076
15191
|
const validateExtensionMutationClient = /* @__PURE__ */ __name((req, res, opts = {}) => {
|
|
15077
15192
|
const clientId = parseAndValidateWorkspaceClientId(
|
|
@@ -15090,10 +15205,10 @@ function createExtensionsController(deps) {
|
|
|
15090
15205
|
return true;
|
|
15091
15206
|
}, "validateExtensionMutationClient");
|
|
15092
15207
|
const extensionOperations = /* @__PURE__ */ new Map();
|
|
15093
|
-
const isTerminalExtensionOperation = /* @__PURE__ */ __name((operation) => operation.status !== "queued" && operation.status !== "running", "isTerminalExtensionOperation");
|
|
15208
|
+
const isTerminalExtensionOperation = /* @__PURE__ */ __name((operation) => operation.status !== "queued" && operation.status !== "running" && operation.status !== "waiting_for_input", "isTerminalExtensionOperation");
|
|
15094
15209
|
const redactExtensionOperationResult = /* @__PURE__ */ __name((event) => ({
|
|
15095
15210
|
...event,
|
|
15096
|
-
...event.source ? { source:
|
|
15211
|
+
...event.source ? { source: redactExtensionDisplaySource(event.source) } : {}
|
|
15097
15212
|
}), "redactExtensionOperationResult");
|
|
15098
15213
|
const bridgeMutationEvent = /* @__PURE__ */ __name((event) => {
|
|
15099
15214
|
const redacted = redactExtensionOperationResult(event);
|
|
@@ -15174,7 +15289,7 @@ function createExtensionsController(deps) {
|
|
|
15174
15289
|
status: "queued",
|
|
15175
15290
|
createdAt: now,
|
|
15176
15291
|
updatedAt: now,
|
|
15177
|
-
...failureContext.source ? { source:
|
|
15292
|
+
...failureContext.source ? { source: redactExtensionDisplaySource(failureContext.source) } : {},
|
|
15178
15293
|
...failureContext.name ? { name: failureContext.name } : {}
|
|
15179
15294
|
});
|
|
15180
15295
|
const operationBasePath = options.operationBasePath ?? "/workspace/extensions/operations";
|
|
@@ -15201,7 +15316,7 @@ function createExtensionsController(deps) {
|
|
|
15201
15316
|
status: "running",
|
|
15202
15317
|
phase: "preparing"
|
|
15203
15318
|
});
|
|
15204
|
-
const extensionManager = options.manager ?? createExtensionManager();
|
|
15319
|
+
const extensionManager = options.manager ?? options.createManager?.(operationId) ?? createExtensionManager();
|
|
15205
15320
|
const deadlineController = new AbortController();
|
|
15206
15321
|
let deadlineStarted = false;
|
|
15207
15322
|
const startDeadline = /* @__PURE__ */ __name(() => {
|
|
@@ -15302,7 +15417,8 @@ function createExtensionsController(deps) {
|
|
|
15302
15417
|
const event = await run(
|
|
15303
15418
|
extensionManager,
|
|
15304
15419
|
deadlineController.signal,
|
|
15305
|
-
context
|
|
15420
|
+
context,
|
|
15421
|
+
operationId
|
|
15306
15422
|
);
|
|
15307
15423
|
mutationEvent = event;
|
|
15308
15424
|
if (deadline) clearTimeout(deadline);
|
|
@@ -15527,7 +15643,9 @@ function createExtensionsController(deps) {
|
|
|
15527
15643
|
bridge.broadcastExtensionsChanged({
|
|
15528
15644
|
...mutationEvent ? bridgeMutationEvent(mutationEvent) : {
|
|
15529
15645
|
...failureContext.source ? {
|
|
15530
|
-
source:
|
|
15646
|
+
source: redactExtensionDisplaySource(
|
|
15647
|
+
failureContext.source
|
|
15648
|
+
)
|
|
15531
15649
|
} : {},
|
|
15532
15650
|
...failureContext.name ? { name: failureContext.name } : {}
|
|
15533
15651
|
},
|
|
@@ -15548,13 +15666,14 @@ function createExtensionsController(deps) {
|
|
|
15548
15666
|
updateExtensionOperation(operationId, {
|
|
15549
15667
|
status: "failed",
|
|
15550
15668
|
phase: void 0,
|
|
15669
|
+
interaction: void 0,
|
|
15551
15670
|
error: message.slice(0, 500),
|
|
15552
15671
|
...code ? { code } : {}
|
|
15553
15672
|
});
|
|
15554
15673
|
try {
|
|
15555
15674
|
bridge.broadcastExtensionsChanged({
|
|
15556
15675
|
status: "failed",
|
|
15557
|
-
...failureContext.source ? { source:
|
|
15676
|
+
...failureContext.source ? { source: redactExtensionDisplaySource(failureContext.source) } : {},
|
|
15558
15677
|
...failureContext.name ? { name: failureContext.name } : {},
|
|
15559
15678
|
refreshed: 0,
|
|
15560
15679
|
failed: 0,
|
|
@@ -15576,6 +15695,7 @@ function createExtensionsController(deps) {
|
|
|
15576
15695
|
} finally {
|
|
15577
15696
|
if (deadline) clearTimeout(deadline);
|
|
15578
15697
|
reconciliationReservation?.release();
|
|
15698
|
+
options.onSettled?.(operationId);
|
|
15579
15699
|
releaseOperationSlot();
|
|
15580
15700
|
}
|
|
15581
15701
|
})();
|
|
@@ -15610,7 +15730,11 @@ function createExtensionsController(deps) {
|
|
|
15610
15730
|
version: ext.version,
|
|
15611
15731
|
isActive: ext.isActive,
|
|
15612
15732
|
path: ext.path,
|
|
15613
|
-
...ext.installMetadata?.source ? {
|
|
15733
|
+
...ext.installMetadata?.source ? {
|
|
15734
|
+
source: redactExtensionDisplaySource(
|
|
15735
|
+
ext.installMetadata.source
|
|
15736
|
+
)
|
|
15737
|
+
} : {},
|
|
15614
15738
|
...ext.installMetadata?.type ? { installType: ext.installMetadata.type } : {},
|
|
15615
15739
|
...ext.installMetadata?.originSource ? { originSource: ext.installMetadata.originSource } : {},
|
|
15616
15740
|
...ext.installMetadata?.ref ? { ref: ext.installMetadata.ref } : {},
|
|
@@ -15646,6 +15770,10 @@ function createExtensionsController(deps) {
|
|
|
15646
15770
|
buildLocalExtensionsStatus,
|
|
15647
15771
|
refreshExtensionsForAllSessions,
|
|
15648
15772
|
getOperation: /* @__PURE__ */ __name((operationId) => extensionOperations.get(operationId), "getOperation"),
|
|
15773
|
+
getActiveOperations: /* @__PURE__ */ __name(() => [...extensionOperations.values()].filter(
|
|
15774
|
+
(operation) => !isTerminalExtensionOperation(operation)
|
|
15775
|
+
), "getActiveOperations"),
|
|
15776
|
+
updateOperation: updateExtensionOperation,
|
|
15649
15777
|
preparationQueue,
|
|
15650
15778
|
acquireOperationSlot,
|
|
15651
15779
|
validateExtensionMutationClient,
|
|
@@ -15656,6 +15784,8 @@ __name(createExtensionsController, "createExtensionsController");
|
|
|
15656
15784
|
|
|
15657
15785
|
// packages/cli/src/serve/routes/workspace-extensions.ts
|
|
15658
15786
|
var EXTENSION_PREPARE_DEADLINE_MS = 10 * 6e4;
|
|
15787
|
+
var EXTENSION_INTERACTION_DEADLINE_MS = 10 * 6e4;
|
|
15788
|
+
var EXTENSION_INTERACTIVE_PREPARE_DEADLINE_MS = EXTENSION_PREPARE_DEADLINE_MS + EXTENSION_INTERACTION_DEADLINE_MS;
|
|
15659
15789
|
var EXTENSION_UPDATE_CHECK_DEADLINE_MS = 2 * 6e4;
|
|
15660
15790
|
var parseExtensionScope = /* @__PURE__ */ __name((body, res) => {
|
|
15661
15791
|
const scope = body["scope"];
|
|
@@ -15761,6 +15891,96 @@ function registerWorkspaceExtensionRoutes(app, deps) {
|
|
|
15761
15891
|
const primaryController = createExtensionsController(
|
|
15762
15892
|
controllerDeps(boundWorkspace, bridge, workspace)
|
|
15763
15893
|
);
|
|
15894
|
+
const pendingExtensionInteractions = /* @__PURE__ */ new Map();
|
|
15895
|
+
const supersededInstallOperations = /* @__PURE__ */ new Set();
|
|
15896
|
+
const cancelPendingExtensionInteraction = /* @__PURE__ */ __name((operationId, reason) => {
|
|
15897
|
+
const pending = pendingExtensionInteractions.get(operationId);
|
|
15898
|
+
if (!pending) return;
|
|
15899
|
+
clearTimeout(pending.timeout);
|
|
15900
|
+
pendingExtensionInteractions.delete(operationId);
|
|
15901
|
+
pending.reject(new Error(reason));
|
|
15902
|
+
}, "cancelPendingExtensionInteraction");
|
|
15903
|
+
const supersedeActiveInstallOperations = /* @__PURE__ */ __name((controller, currentOperationId) => {
|
|
15904
|
+
for (const operation of controller.getActiveOperations()) {
|
|
15905
|
+
if (operation.operation !== "install" || operation.operationId === currentOperationId) {
|
|
15906
|
+
continue;
|
|
15907
|
+
}
|
|
15908
|
+
supersededInstallOperations.add(operation.operationId);
|
|
15909
|
+
cancelPendingExtensionInteraction(
|
|
15910
|
+
operation.operationId,
|
|
15911
|
+
"Extension installation cancelled by a new install request"
|
|
15912
|
+
);
|
|
15913
|
+
}
|
|
15914
|
+
}, "supersedeActiveInstallOperations");
|
|
15915
|
+
const waitForExtensionInteraction = /* @__PURE__ */ __name((controller, operationId, interaction) => {
|
|
15916
|
+
if (supersededInstallOperations.delete(operationId)) {
|
|
15917
|
+
return Promise.reject(
|
|
15918
|
+
new Error("Extension installation superseded by a new install request")
|
|
15919
|
+
);
|
|
15920
|
+
}
|
|
15921
|
+
const operation = controller.getOperation(operationId);
|
|
15922
|
+
if (operation && operation.status !== "queued" && operation.status !== "running" && operation.status !== "waiting_for_input") {
|
|
15923
|
+
return Promise.reject(new Error("Extension operation already completed"));
|
|
15924
|
+
}
|
|
15925
|
+
const pendingInteraction = {
|
|
15926
|
+
...interaction,
|
|
15927
|
+
id: crypto2.randomUUID()
|
|
15928
|
+
};
|
|
15929
|
+
return new Promise((resolve5, reject) => {
|
|
15930
|
+
const timeout = setTimeout(() => {
|
|
15931
|
+
pendingExtensionInteractions.delete(operationId);
|
|
15932
|
+
controller.updateOperation(operationId, {
|
|
15933
|
+
status: "failed",
|
|
15934
|
+
phase: void 0,
|
|
15935
|
+
interaction: void 0,
|
|
15936
|
+
error: "Extension interaction timed out"
|
|
15937
|
+
});
|
|
15938
|
+
reject(new Error("Extension interaction timed out"));
|
|
15939
|
+
}, EXTENSION_INTERACTION_DEADLINE_MS);
|
|
15940
|
+
timeout.unref?.();
|
|
15941
|
+
pendingExtensionInteractions.set(operationId, {
|
|
15942
|
+
interaction: pendingInteraction,
|
|
15943
|
+
resolve: resolve5,
|
|
15944
|
+
reject,
|
|
15945
|
+
timeout
|
|
15946
|
+
});
|
|
15947
|
+
controller.updateOperation(operationId, {
|
|
15948
|
+
status: "waiting_for_input",
|
|
15949
|
+
phase: void 0,
|
|
15950
|
+
interaction: pendingInteraction
|
|
15951
|
+
});
|
|
15952
|
+
});
|
|
15953
|
+
}, "waitForExtensionInteraction");
|
|
15954
|
+
const extensionInteractionHandlers = /* @__PURE__ */ __name((controller, operationId) => ({
|
|
15955
|
+
requestSetting: /* @__PURE__ */ __name((setting) => waitForExtensionInteraction(controller, operationId, {
|
|
15956
|
+
kind: "setting",
|
|
15957
|
+
setting: {
|
|
15958
|
+
name: setting.name,
|
|
15959
|
+
description: setting.description,
|
|
15960
|
+
sensitive: setting.sensitive === true
|
|
15961
|
+
}
|
|
15962
|
+
}), "requestSetting"),
|
|
15963
|
+
requestChoicePlugin: /* @__PURE__ */ __name((marketplace) => {
|
|
15964
|
+
if (marketplace.plugins.length === 0) {
|
|
15965
|
+
return Promise.reject(
|
|
15966
|
+
new Error(`Marketplace "${marketplace.name}" has no plugins`)
|
|
15967
|
+
);
|
|
15968
|
+
}
|
|
15969
|
+
return waitForExtensionInteraction(controller, operationId, {
|
|
15970
|
+
kind: "marketplace_plugin",
|
|
15971
|
+
marketplace: { name: marketplace.name },
|
|
15972
|
+
plugins: marketplace.plugins.map((plugin) => ({
|
|
15973
|
+
name: plugin.name,
|
|
15974
|
+
...plugin.description ? { description: plugin.description } : {},
|
|
15975
|
+
source: redactExtensionDisplaySource(
|
|
15976
|
+
typeof plugin.source === "string" ? plugin.source : plugin.source.source === "github" ? plugin.source.repo : plugin.source.url
|
|
15977
|
+
),
|
|
15978
|
+
...plugin.category ? { category: plugin.category } : {},
|
|
15979
|
+
...plugin.tags ? { tags: plugin.tags } : {}
|
|
15980
|
+
}))
|
|
15981
|
+
});
|
|
15982
|
+
}, "requestChoicePlugin")
|
|
15983
|
+
}), "extensionInteractionHandlers");
|
|
15764
15984
|
const runtimeReconciliationQueue = createFifoTaskQueue(1);
|
|
15765
15985
|
const reserveRuntimeReconciliation = /* @__PURE__ */ __name(() => {
|
|
15766
15986
|
let provideTask;
|
|
@@ -15877,6 +16097,11 @@ function registerWorkspaceExtensionRoutes(app, deps) {
|
|
|
15877
16097
|
sendBridgeError2(res, err, { route: `GET ${base}` });
|
|
15878
16098
|
}
|
|
15879
16099
|
});
|
|
16100
|
+
app.get(`${base}/operations`, async (req, res) => {
|
|
16101
|
+
const ctrl = resolve5(req, res, false);
|
|
16102
|
+
if (!ctrl) return;
|
|
16103
|
+
res.status(200).json({ v: 1, operations: ctrl.getActiveOperations() });
|
|
16104
|
+
});
|
|
15880
16105
|
app.get(`${base}/operations/:operationId`, async (req, res) => {
|
|
15881
16106
|
const ctrl = resolve5(req, res, false);
|
|
15882
16107
|
if (!ctrl) return;
|
|
@@ -15918,11 +16143,85 @@ function registerWorkspaceExtensionRoutes(app, deps) {
|
|
|
15918
16143
|
});
|
|
15919
16144
|
}
|
|
15920
16145
|
});
|
|
16146
|
+
app.post(
|
|
16147
|
+
`${base}/operations/:operationId/interactions/:interactionId`,
|
|
16148
|
+
mutate({ strict: true }),
|
|
16149
|
+
async (req, res) => {
|
|
16150
|
+
const ctrl = resolve5(req, res, false);
|
|
16151
|
+
if (!ctrl) return;
|
|
16152
|
+
try {
|
|
16153
|
+
if (!ctrl.validateExtensionMutationClient(req, res, {
|
|
16154
|
+
requireClientId: false
|
|
16155
|
+
})) {
|
|
16156
|
+
return;
|
|
16157
|
+
}
|
|
16158
|
+
const operationId = req.params["operationId"];
|
|
16159
|
+
const interactionId = req.params["interactionId"];
|
|
16160
|
+
const pending = operationId ? pendingExtensionInteractions.get(operationId) : void 0;
|
|
16161
|
+
if (!operationId || !interactionId || !pending) {
|
|
16162
|
+
res.status(404).json({ error: "Extension interaction not found" });
|
|
16163
|
+
return;
|
|
16164
|
+
}
|
|
16165
|
+
if (pending.interaction.id !== interactionId) {
|
|
16166
|
+
res.status(404).json({ error: "Extension interaction not found" });
|
|
16167
|
+
return;
|
|
16168
|
+
}
|
|
16169
|
+
const body = safeBody2(req);
|
|
16170
|
+
let value;
|
|
16171
|
+
if (body["cancelled"] === true) {
|
|
16172
|
+
clearTimeout(pending.timeout);
|
|
16173
|
+
pendingExtensionInteractions.delete(operationId);
|
|
16174
|
+
ctrl.updateOperation(operationId, {
|
|
16175
|
+
status: "failed",
|
|
16176
|
+
phase: void 0,
|
|
16177
|
+
interaction: void 0,
|
|
16178
|
+
error: "Extension operation cancelled"
|
|
16179
|
+
});
|
|
16180
|
+
pending.reject(new Error("Extension operation cancelled"));
|
|
16181
|
+
res.status(200).json({ accepted: true });
|
|
16182
|
+
return;
|
|
16183
|
+
}
|
|
16184
|
+
if (pending.interaction.kind === "marketplace_plugin") {
|
|
16185
|
+
const pluginName = body["pluginName"];
|
|
16186
|
+
if (typeof pluginName !== "string" || !pending.interaction.plugins.some(
|
|
16187
|
+
(plugin) => plugin.name === pluginName
|
|
16188
|
+
)) {
|
|
16189
|
+
res.status(400).json({ error: "Invalid marketplace plugin name" });
|
|
16190
|
+
return;
|
|
16191
|
+
}
|
|
16192
|
+
value = pluginName;
|
|
16193
|
+
} else {
|
|
16194
|
+
const settingValue = body["value"];
|
|
16195
|
+
if (typeof settingValue !== "string") {
|
|
16196
|
+
res.status(400).json({ error: "Extension setting value must be a string" });
|
|
16197
|
+
return;
|
|
16198
|
+
}
|
|
16199
|
+
value = settingValue;
|
|
16200
|
+
}
|
|
16201
|
+
clearTimeout(pending.timeout);
|
|
16202
|
+
pendingExtensionInteractions.delete(operationId);
|
|
16203
|
+
ctrl.updateOperation(operationId, {
|
|
16204
|
+
status: "running",
|
|
16205
|
+
phase: "preparing",
|
|
16206
|
+
interaction: void 0,
|
|
16207
|
+
error: void 0
|
|
16208
|
+
});
|
|
16209
|
+
pending.resolve(value);
|
|
16210
|
+
res.status(200).json({ accepted: true });
|
|
16211
|
+
} catch (err) {
|
|
16212
|
+
sendBridgeError2(res, err, {
|
|
16213
|
+
route: `POST ${base}/operations/:operationId/interactions/:interactionId`
|
|
16214
|
+
});
|
|
16215
|
+
}
|
|
16216
|
+
}
|
|
16217
|
+
);
|
|
15921
16218
|
app.post(`${base}/install`, mutate({ strict: true }), async (req, res) => {
|
|
15922
16219
|
const ctrl = resolve5(req, res, true);
|
|
15923
16220
|
if (!ctrl) return;
|
|
15924
16221
|
try {
|
|
15925
|
-
if (!ctrl.validateExtensionMutationClient(req, res
|
|
16222
|
+
if (!ctrl.validateExtensionMutationClient(req, res, {
|
|
16223
|
+
requireClientId: false
|
|
16224
|
+
})) {
|
|
15926
16225
|
return;
|
|
15927
16226
|
}
|
|
15928
16227
|
const body = safeBody2(req);
|
|
@@ -15972,11 +16271,56 @@ function registerWorkspaceExtensionRoutes(app, deps) {
|
|
|
15972
16271
|
if (!validateExtensionSourceHost(sourceValue, res)) {
|
|
15973
16272
|
return;
|
|
15974
16273
|
}
|
|
16274
|
+
const localSource = /^[A-Za-z]:[\\/]/.test(sourceValue) || sourceValue.startsWith("/") || sourceValue.startsWith(".");
|
|
16275
|
+
if (localSource) {
|
|
16276
|
+
try {
|
|
16277
|
+
const metadata = await parseInstallSource(sourceValue, {
|
|
16278
|
+
networkPolicy: "public"
|
|
16279
|
+
});
|
|
16280
|
+
if (metadata.type !== "git" && metadata.type !== "github-release" && metadata.type !== "npm") {
|
|
16281
|
+
res.status(400).json({
|
|
16282
|
+
error: "Only GitHub, Git, and npm extension installs are supported over the daemon endpoint."
|
|
16283
|
+
});
|
|
16284
|
+
return;
|
|
16285
|
+
}
|
|
16286
|
+
} catch (error2) {
|
|
16287
|
+
const message = error2 instanceof Error ? error2.message : "Invalid install source";
|
|
16288
|
+
res.status(400).json({
|
|
16289
|
+
error: redactUrlCredentials(
|
|
16290
|
+
message.replaceAll(
|
|
16291
|
+
sourceValue,
|
|
16292
|
+
redactExtensionDisplaySource(sourceValue)
|
|
16293
|
+
)
|
|
16294
|
+
)
|
|
16295
|
+
});
|
|
16296
|
+
return;
|
|
16297
|
+
}
|
|
16298
|
+
}
|
|
16299
|
+
const npmSource = sourceValue.startsWith("@");
|
|
16300
|
+
const remoteSource = npmSource || sourceValue.startsWith("https://") || /^[^/\s]+\/[^/\s]+/.test(sourceValue);
|
|
16301
|
+
if (!localSource && !remoteSource) {
|
|
16302
|
+
res.status(400).json({
|
|
16303
|
+
error: `Install source not found: ${redactExtensionDisplaySource(
|
|
16304
|
+
sourceValue
|
|
16305
|
+
)}`
|
|
16306
|
+
});
|
|
16307
|
+
return;
|
|
16308
|
+
}
|
|
16309
|
+
if (npmSource && refValue) {
|
|
16310
|
+
res.status(400).json({ error: "--ref is not applicable for npm extensions." });
|
|
16311
|
+
return;
|
|
16312
|
+
}
|
|
16313
|
+
if (!npmSource && registryValue) {
|
|
16314
|
+
res.status(400).json({
|
|
16315
|
+
error: "--registry is only applicable for npm extensions."
|
|
16316
|
+
});
|
|
16317
|
+
return;
|
|
16318
|
+
}
|
|
15975
16319
|
ctrl.runQueuedExtensionMutation(
|
|
15976
16320
|
"install",
|
|
15977
16321
|
{ source: sourceValue },
|
|
15978
16322
|
res,
|
|
15979
|
-
async (extensionManager, _signal, context) => {
|
|
16323
|
+
async (extensionManager, _signal, context, operationId) => {
|
|
15980
16324
|
const prepared = await context.prepare(async (signal) => {
|
|
15981
16325
|
const installMetadata = await parseInstallSource(sourceValue, {
|
|
15982
16326
|
networkPolicy: "public"
|
|
@@ -16000,6 +16344,7 @@ function registerWorkspaceExtensionRoutes(app, deps) {
|
|
|
16000
16344
|
if (installMetadata.type === "npm" && registryUrl) {
|
|
16001
16345
|
installMetadata.registryUrl = registryUrl;
|
|
16002
16346
|
}
|
|
16347
|
+
supersedeActiveInstallOperations(ctrl, operationId);
|
|
16003
16348
|
return await extensionManager.prepareExtensionInstall({
|
|
16004
16349
|
installMetadata: {
|
|
16005
16350
|
...installMetadata,
|
|
@@ -16030,7 +16375,19 @@ function registerWorkspaceExtensionRoutes(app, deps) {
|
|
|
16030
16375
|
}
|
|
16031
16376
|
},
|
|
16032
16377
|
{
|
|
16033
|
-
|
|
16378
|
+
createManager: /* @__PURE__ */ __name((operationId) => ctrl.createExtensionManager(
|
|
16379
|
+
void 0,
|
|
16380
|
+
void 0,
|
|
16381
|
+
extensionInteractionHandlers(ctrl, operationId)
|
|
16382
|
+
), "createManager"),
|
|
16383
|
+
onSettled: /* @__PURE__ */ __name((operationId) => {
|
|
16384
|
+
supersededInstallOperations.delete(operationId);
|
|
16385
|
+
cancelPendingExtensionInteraction(
|
|
16386
|
+
operationId,
|
|
16387
|
+
"Extension operation ended"
|
|
16388
|
+
);
|
|
16389
|
+
}, "onSettled"),
|
|
16390
|
+
deadlineMs: EXTENSION_INTERACTIVE_PREPARE_DEADLINE_MS,
|
|
16034
16391
|
...globalReconciliationOptions()
|
|
16035
16392
|
}
|
|
16036
16393
|
);
|
|
@@ -16047,7 +16404,9 @@ function registerWorkspaceExtensionRoutes(app, deps) {
|
|
|
16047
16404
|
let timer;
|
|
16048
16405
|
let releaseOperationSlot;
|
|
16049
16406
|
try {
|
|
16050
|
-
if (!ctrl.validateExtensionMutationClient(req, res
|
|
16407
|
+
if (!ctrl.validateExtensionMutationClient(req, res, {
|
|
16408
|
+
requireClientId: false
|
|
16409
|
+
})) {
|
|
16051
16410
|
return;
|
|
16052
16411
|
}
|
|
16053
16412
|
releaseOperationSlot = ctrl.acquireOperationSlot(res);
|
|
@@ -16107,7 +16466,9 @@ function registerWorkspaceExtensionRoutes(app, deps) {
|
|
|
16107
16466
|
const ctrl = resolve5(req, res, true);
|
|
16108
16467
|
if (!ctrl) return;
|
|
16109
16468
|
try {
|
|
16110
|
-
if (!ctrl.validateExtensionMutationClient(req, res
|
|
16469
|
+
if (!ctrl.validateExtensionMutationClient(req, res, {
|
|
16470
|
+
requireClientId: false
|
|
16471
|
+
})) {
|
|
16111
16472
|
return;
|
|
16112
16473
|
}
|
|
16113
16474
|
const releaseOperationSlot = ctrl.acquireOperationSlot(res);
|
|
@@ -16223,7 +16584,9 @@ function registerWorkspaceExtensionRoutes(app, deps) {
|
|
|
16223
16584
|
const ctrl = resolve5(req, res, true);
|
|
16224
16585
|
if (!ctrl) return;
|
|
16225
16586
|
try {
|
|
16226
|
-
if (!ctrl.validateExtensionMutationClient(req, res
|
|
16587
|
+
if (!ctrl.validateExtensionMutationClient(req, res, {
|
|
16588
|
+
requireClientId: false
|
|
16589
|
+
})) {
|
|
16227
16590
|
return;
|
|
16228
16591
|
}
|
|
16229
16592
|
const name = req.params["name"];
|
|
@@ -16280,7 +16643,18 @@ function registerWorkspaceExtensionRoutes(app, deps) {
|
|
|
16280
16643
|
}
|
|
16281
16644
|
},
|
|
16282
16645
|
{
|
|
16283
|
-
|
|
16646
|
+
createManager: /* @__PURE__ */ __name((operationId) => ctrl.createExtensionManager(
|
|
16647
|
+
void 0,
|
|
16648
|
+
void 0,
|
|
16649
|
+
extensionInteractionHandlers(ctrl, operationId)
|
|
16650
|
+
), "createManager"),
|
|
16651
|
+
onSettled: /* @__PURE__ */ __name((operationId) => {
|
|
16652
|
+
cancelPendingExtensionInteraction(
|
|
16653
|
+
operationId,
|
|
16654
|
+
"Extension operation ended"
|
|
16655
|
+
);
|
|
16656
|
+
}, "onSettled"),
|
|
16657
|
+
deadlineMs: EXTENSION_INTERACTIVE_PREPARE_DEADLINE_MS,
|
|
16284
16658
|
...globalReconciliationOptions()
|
|
16285
16659
|
}
|
|
16286
16660
|
);
|
|
@@ -16293,7 +16667,9 @@ function registerWorkspaceExtensionRoutes(app, deps) {
|
|
|
16293
16667
|
const ctrl = resolve5(req, res, true);
|
|
16294
16668
|
if (!ctrl) return;
|
|
16295
16669
|
try {
|
|
16296
|
-
if (!ctrl.validateExtensionMutationClient(req, res
|
|
16670
|
+
if (!ctrl.validateExtensionMutationClient(req, res, {
|
|
16671
|
+
requireClientId: false
|
|
16672
|
+
})) {
|
|
16297
16673
|
return;
|
|
16298
16674
|
}
|
|
16299
16675
|
const name = req.params["name"];
|
|
@@ -17355,67 +17731,682 @@ init_esbuild_shims();
|
|
|
17355
17731
|
|
|
17356
17732
|
// packages/cli/src/serve/routes/session-runtime.ts
|
|
17357
17733
|
init_esbuild_shims();
|
|
17358
|
-
|
|
17359
|
-
|
|
17360
|
-
|
|
17361
|
-
|
|
17362
|
-
|
|
17363
|
-
|
|
17364
|
-
|
|
17365
|
-
|
|
17366
|
-
|
|
17367
|
-
|
|
17368
|
-
|
|
17734
|
+
|
|
17735
|
+
// packages/cli/src/serve/server/telemetry.ts
|
|
17736
|
+
init_esbuild_shims();
|
|
17737
|
+
var legacySessionTelemetryRoutes = [
|
|
17738
|
+
{
|
|
17739
|
+
method: "POST",
|
|
17740
|
+
path: "/session",
|
|
17741
|
+
attribution: "handler_resolved",
|
|
17742
|
+
route: "POST /session"
|
|
17743
|
+
},
|
|
17744
|
+
{
|
|
17745
|
+
method: "POST",
|
|
17746
|
+
path: "/session/:id/load",
|
|
17747
|
+
attribution: "handler_resolved",
|
|
17748
|
+
route: "POST /session/:id/load"
|
|
17749
|
+
},
|
|
17750
|
+
{
|
|
17751
|
+
method: "POST",
|
|
17752
|
+
path: "/session/:id/resume",
|
|
17753
|
+
attribution: "handler_resolved",
|
|
17754
|
+
route: "POST /session/:id/resume"
|
|
17755
|
+
},
|
|
17756
|
+
{
|
|
17757
|
+
method: "POST",
|
|
17758
|
+
path: "/session/:id/branch",
|
|
17759
|
+
attribution: "handler_resolved",
|
|
17760
|
+
route: "POST /session/:id/branch"
|
|
17761
|
+
},
|
|
17762
|
+
{
|
|
17763
|
+
method: "POST",
|
|
17764
|
+
path: "/session/:id/fork",
|
|
17765
|
+
attribution: "handler_resolved",
|
|
17766
|
+
route: "POST /session/:id/fork"
|
|
17767
|
+
},
|
|
17768
|
+
{
|
|
17769
|
+
method: "POST",
|
|
17770
|
+
path: "/session/:id/cd",
|
|
17771
|
+
attribution: "handler_resolved",
|
|
17772
|
+
route: "POST /session/:id/cd"
|
|
17773
|
+
},
|
|
17774
|
+
{
|
|
17775
|
+
method: "GET",
|
|
17776
|
+
path: "/session/:id/status",
|
|
17777
|
+
attribution: "handler_resolved",
|
|
17778
|
+
route: "GET /session/:id/status"
|
|
17779
|
+
},
|
|
17780
|
+
{
|
|
17781
|
+
method: "GET",
|
|
17782
|
+
path: "/session/:id/export",
|
|
17783
|
+
attribution: "pre_resolved",
|
|
17784
|
+
route: "GET /session/:id/export"
|
|
17785
|
+
},
|
|
17786
|
+
{
|
|
17787
|
+
method: "GET",
|
|
17788
|
+
path: "/session/:id/transcript",
|
|
17789
|
+
attribution: "handler_resolved",
|
|
17790
|
+
route: "GET /session/:id/transcript"
|
|
17791
|
+
},
|
|
17792
|
+
{
|
|
17793
|
+
method: "GET",
|
|
17794
|
+
path: "/session/:id/context",
|
|
17795
|
+
attribution: "handler_resolved",
|
|
17796
|
+
route: "GET /session/:id/context"
|
|
17797
|
+
},
|
|
17798
|
+
{
|
|
17799
|
+
method: "GET",
|
|
17800
|
+
path: "/session/:id/context-usage",
|
|
17801
|
+
attribution: "handler_resolved",
|
|
17802
|
+
route: "GET /session/:id/context-usage"
|
|
17803
|
+
},
|
|
17804
|
+
{
|
|
17805
|
+
method: "GET",
|
|
17806
|
+
path: "/session/:id/stats",
|
|
17807
|
+
attribution: "handler_resolved",
|
|
17808
|
+
route: "GET /session/:id/stats"
|
|
17809
|
+
},
|
|
17810
|
+
{
|
|
17811
|
+
method: "GET",
|
|
17812
|
+
path: "/session/:id/supported-commands",
|
|
17813
|
+
attribution: "handler_resolved",
|
|
17814
|
+
route: "GET /session/:id/supported-commands"
|
|
17815
|
+
},
|
|
17816
|
+
{
|
|
17817
|
+
method: "GET",
|
|
17818
|
+
path: "/session/:id/tasks",
|
|
17819
|
+
attribution: "handler_resolved",
|
|
17820
|
+
route: "GET /session/:id/tasks"
|
|
17821
|
+
},
|
|
17822
|
+
{
|
|
17823
|
+
method: "GET",
|
|
17824
|
+
path: "/session/:id/lsp",
|
|
17825
|
+
attribution: "handler_resolved",
|
|
17826
|
+
route: "GET /session/:id/lsp"
|
|
17827
|
+
},
|
|
17828
|
+
{
|
|
17829
|
+
method: "GET",
|
|
17830
|
+
path: "/session/:id/hooks",
|
|
17831
|
+
attribution: "handler_resolved",
|
|
17832
|
+
route: "GET /session/:id/hooks"
|
|
17833
|
+
},
|
|
17834
|
+
{
|
|
17835
|
+
method: "GET",
|
|
17836
|
+
path: "/session/:id/artifacts",
|
|
17837
|
+
attribution: "handler_resolved",
|
|
17838
|
+
route: "GET /session/:id/artifacts"
|
|
17839
|
+
},
|
|
17840
|
+
{
|
|
17841
|
+
method: "POST",
|
|
17842
|
+
path: "/session/:id/artifacts",
|
|
17843
|
+
attribution: "handler_resolved",
|
|
17844
|
+
route: "POST /session/:id/artifacts"
|
|
17845
|
+
},
|
|
17846
|
+
{
|
|
17847
|
+
method: "DELETE",
|
|
17848
|
+
path: "/session/:id/artifacts/:artifactId",
|
|
17849
|
+
attribution: "handler_resolved",
|
|
17850
|
+
route: "DELETE /session/:id/artifacts/:artifactId"
|
|
17851
|
+
},
|
|
17852
|
+
{
|
|
17853
|
+
method: "POST",
|
|
17854
|
+
path: "/session/:id/tasks/:taskId/cancel",
|
|
17855
|
+
attribution: "handler_resolved",
|
|
17856
|
+
route: "POST /session/:id/tasks/:taskId/cancel"
|
|
17857
|
+
},
|
|
17858
|
+
{
|
|
17859
|
+
method: "POST",
|
|
17860
|
+
path: "/session/:id/goal/clear",
|
|
17861
|
+
attribution: "handler_resolved",
|
|
17862
|
+
route: "POST /session/:id/goal/clear"
|
|
17863
|
+
},
|
|
17864
|
+
{
|
|
17865
|
+
method: "POST",
|
|
17866
|
+
path: "/session/:id/continue",
|
|
17867
|
+
attribution: "handler_resolved",
|
|
17868
|
+
route: "POST /session/:id/continue"
|
|
17869
|
+
},
|
|
17870
|
+
{
|
|
17871
|
+
method: "POST",
|
|
17872
|
+
path: "/session/:id/prompt",
|
|
17873
|
+
attribution: "handler_resolved",
|
|
17874
|
+
route: "POST /session/:id/prompt"
|
|
17875
|
+
},
|
|
17876
|
+
{
|
|
17877
|
+
method: "POST",
|
|
17878
|
+
path: "/session/:id/generate",
|
|
17879
|
+
attribution: "handler_resolved",
|
|
17880
|
+
route: "POST /session/:id/generate"
|
|
17881
|
+
},
|
|
17882
|
+
{
|
|
17883
|
+
method: "POST",
|
|
17884
|
+
path: "/session/:id/heartbeat",
|
|
17885
|
+
attribution: "handler_resolved",
|
|
17886
|
+
route: "POST /session/:id/heartbeat"
|
|
17887
|
+
},
|
|
17888
|
+
{
|
|
17889
|
+
method: "POST",
|
|
17890
|
+
path: "/session/:id/detach",
|
|
17891
|
+
attribution: "handler_resolved",
|
|
17892
|
+
route: "POST /session/:id/detach"
|
|
17893
|
+
},
|
|
17894
|
+
{
|
|
17895
|
+
method: "POST",
|
|
17896
|
+
path: "/session/:id/cancel",
|
|
17897
|
+
attribution: "handler_resolved",
|
|
17898
|
+
route: "POST /session/:id/cancel"
|
|
17899
|
+
},
|
|
17900
|
+
{
|
|
17901
|
+
method: "DELETE",
|
|
17902
|
+
path: "/session/:id",
|
|
17903
|
+
attribution: "handler_resolved",
|
|
17904
|
+
route: "DELETE /session/:id"
|
|
17905
|
+
},
|
|
17906
|
+
{
|
|
17907
|
+
method: "POST",
|
|
17908
|
+
path: "/sessions/delete",
|
|
17909
|
+
attribution: "pre_resolved",
|
|
17910
|
+
route: "POST /sessions/delete"
|
|
17911
|
+
},
|
|
17912
|
+
{
|
|
17913
|
+
method: "POST",
|
|
17914
|
+
path: "/sessions/archive",
|
|
17915
|
+
attribution: "pre_resolved",
|
|
17916
|
+
route: "POST /sessions/archive"
|
|
17917
|
+
},
|
|
17918
|
+
{
|
|
17919
|
+
method: "POST",
|
|
17920
|
+
path: "/sessions/unarchive",
|
|
17921
|
+
attribution: "pre_resolved",
|
|
17922
|
+
route: "POST /sessions/unarchive"
|
|
17923
|
+
},
|
|
17924
|
+
{
|
|
17925
|
+
method: "PATCH",
|
|
17926
|
+
path: "/session/:id/metadata",
|
|
17927
|
+
attribution: "handler_resolved",
|
|
17928
|
+
route: "PATCH /session/:id/metadata"
|
|
17929
|
+
},
|
|
17930
|
+
{
|
|
17931
|
+
method: "PATCH",
|
|
17932
|
+
path: "/session/:id/organization",
|
|
17933
|
+
attribution: "pre_resolved",
|
|
17934
|
+
route: "PATCH /session/:id/organization"
|
|
17935
|
+
},
|
|
17936
|
+
{
|
|
17937
|
+
method: "POST",
|
|
17938
|
+
path: "/session/:id/model",
|
|
17939
|
+
attribution: "handler_resolved",
|
|
17940
|
+
route: "POST /session/:id/model"
|
|
17941
|
+
},
|
|
17942
|
+
{
|
|
17943
|
+
method: "POST",
|
|
17944
|
+
path: "/session/:id/recap",
|
|
17945
|
+
attribution: "handler_resolved",
|
|
17946
|
+
route: "POST /session/:id/recap"
|
|
17947
|
+
},
|
|
17948
|
+
{
|
|
17949
|
+
method: "POST",
|
|
17950
|
+
path: "/session/:id/btw",
|
|
17951
|
+
attribution: "handler_resolved",
|
|
17952
|
+
route: "POST /session/:id/btw"
|
|
17953
|
+
},
|
|
17954
|
+
{
|
|
17955
|
+
method: "POST",
|
|
17956
|
+
path: "/session/:id/mid-turn-message",
|
|
17957
|
+
attribution: "handler_resolved",
|
|
17958
|
+
route: "POST /session/:id/mid-turn-message"
|
|
17959
|
+
},
|
|
17960
|
+
{
|
|
17961
|
+
method: "GET",
|
|
17962
|
+
path: "/session/:id/pending-prompts",
|
|
17963
|
+
attribution: "handler_resolved",
|
|
17964
|
+
route: "GET /session/:id/pending-prompts"
|
|
17965
|
+
},
|
|
17966
|
+
{
|
|
17967
|
+
method: "DELETE",
|
|
17968
|
+
path: "/session/:id/pending-prompts/:promptId",
|
|
17969
|
+
attribution: "handler_resolved",
|
|
17970
|
+
route: "DELETE /session/:id/pending-prompts/:promptId"
|
|
17971
|
+
},
|
|
17972
|
+
{
|
|
17973
|
+
method: "POST",
|
|
17974
|
+
path: "/session/:id/shell",
|
|
17975
|
+
attribution: "handler_resolved",
|
|
17976
|
+
route: "POST /session/:id/shell"
|
|
17977
|
+
},
|
|
17978
|
+
{
|
|
17979
|
+
method: "GET",
|
|
17980
|
+
path: "/session/:id/rewind/snapshots",
|
|
17981
|
+
attribution: "handler_resolved",
|
|
17982
|
+
route: "GET /session/:id/rewind/snapshots"
|
|
17983
|
+
},
|
|
17984
|
+
{
|
|
17985
|
+
method: "POST",
|
|
17986
|
+
path: "/session/:id/rewind",
|
|
17987
|
+
attribution: "handler_resolved",
|
|
17988
|
+
route: "POST /session/:id/rewind"
|
|
17989
|
+
},
|
|
17990
|
+
{
|
|
17991
|
+
method: "POST",
|
|
17992
|
+
path: "/session/:id/approval-mode",
|
|
17993
|
+
attribution: "handler_resolved",
|
|
17994
|
+
route: "POST /session/:id/approval-mode"
|
|
17995
|
+
},
|
|
17996
|
+
{
|
|
17997
|
+
method: "POST",
|
|
17998
|
+
path: "/session/:id/language",
|
|
17999
|
+
attribution: "handler_resolved",
|
|
18000
|
+
route: "POST /session/:id/language"
|
|
18001
|
+
},
|
|
18002
|
+
{
|
|
18003
|
+
method: "POST",
|
|
18004
|
+
path: "/session/:id/permission/:requestId",
|
|
18005
|
+
attribution: "handler_resolved",
|
|
18006
|
+
route: "POST /session/:id/permission/:requestId"
|
|
18007
|
+
},
|
|
18008
|
+
{
|
|
18009
|
+
method: "POST",
|
|
18010
|
+
path: "/permission/:requestId",
|
|
18011
|
+
attribution: "pre_resolved",
|
|
18012
|
+
route: "POST /permission/:requestId"
|
|
18013
|
+
},
|
|
18014
|
+
{
|
|
18015
|
+
method: "GET",
|
|
18016
|
+
path: "/session/:id/events",
|
|
18017
|
+
attribution: "handler_resolved",
|
|
18018
|
+
route: "GET /session/:id/events"
|
|
18019
|
+
},
|
|
18020
|
+
{
|
|
18021
|
+
method: "POST",
|
|
18022
|
+
path: "/session/:id/a2ui-action",
|
|
18023
|
+
attribution: "pre_resolved",
|
|
18024
|
+
route: "POST /session/:id/a2ui-action"
|
|
17369
18025
|
}
|
|
17370
|
-
|
|
17371
|
-
|
|
17372
|
-
|
|
17373
|
-
|
|
17374
|
-
|
|
17375
|
-
|
|
17376
|
-
|
|
17377
|
-
sessionId,
|
|
17378
|
-
workspaceId: runtime.workspaceId,
|
|
17379
|
-
workspaceCwd: runtime.workspaceCwd,
|
|
17380
|
-
...details
|
|
17381
|
-
});
|
|
17382
|
-
sendUntrustedWorkspaceResponse(res, {
|
|
17383
|
-
sessionId,
|
|
17384
|
-
workspaceCwd: runtime.workspaceCwd,
|
|
17385
|
-
workspaceId: runtime.workspaceId
|
|
17386
|
-
});
|
|
17387
|
-
return void 0;
|
|
17388
|
-
}
|
|
17389
|
-
return runtime;
|
|
18026
|
+
];
|
|
18027
|
+
var daemonTelemetryResponseContext = Symbol("daemonTelemetryResponseContext");
|
|
18028
|
+
function decodePathSegment(value) {
|
|
18029
|
+
try {
|
|
18030
|
+
return decodeURIComponent(value);
|
|
18031
|
+
} catch {
|
|
18032
|
+
return value;
|
|
17390
18033
|
}
|
|
17391
|
-
|
|
17392
|
-
|
|
17393
|
-
|
|
17394
|
-
|
|
17395
|
-
|
|
17396
|
-
|
|
17397
|
-
|
|
17398
|
-
res.status(404).json({
|
|
17399
|
-
error: `No session with id "${sessionId}"`,
|
|
17400
|
-
code: "session_not_found",
|
|
17401
|
-
sessionId
|
|
17402
|
-
});
|
|
18034
|
+
}
|
|
18035
|
+
__name(decodePathSegment, "decodePathSegment");
|
|
18036
|
+
function matchLegacySessionTelemetryRoute(method, requestPath) {
|
|
18037
|
+
const path15 = requestPath.length > 1 && requestPath.endsWith("/") ? requestPath.slice(0, -1) : requestPath;
|
|
18038
|
+
const requestSegments = path15.split("/").slice(1);
|
|
18039
|
+
const prefix = requestSegments[0]?.toLowerCase();
|
|
18040
|
+
if (prefix !== "session" && prefix !== "sessions" && prefix !== "permission") {
|
|
17403
18041
|
return void 0;
|
|
17404
18042
|
}
|
|
17405
|
-
const
|
|
17406
|
-
(
|
|
17407
|
-
|
|
17408
|
-
|
|
17409
|
-
|
|
17410
|
-
|
|
17411
|
-
|
|
17412
|
-
|
|
17413
|
-
|
|
17414
|
-
|
|
17415
|
-
|
|
17416
|
-
|
|
17417
|
-
|
|
17418
|
-
|
|
18043
|
+
for (const entry of legacySessionTelemetryRoutes) {
|
|
18044
|
+
if (entry.method !== method) continue;
|
|
18045
|
+
const templateSegments = entry.path.split("/").slice(1);
|
|
18046
|
+
if (templateSegments.length !== requestSegments.length) continue;
|
|
18047
|
+
const params = /* @__PURE__ */ new Map();
|
|
18048
|
+
let matched = true;
|
|
18049
|
+
for (let index = 0; index < templateSegments.length; index += 1) {
|
|
18050
|
+
const templateSegment = templateSegments[index];
|
|
18051
|
+
const requestSegment = requestSegments[index];
|
|
18052
|
+
if (templateSegment.startsWith(":")) {
|
|
18053
|
+
if (requestSegment === "") {
|
|
18054
|
+
matched = false;
|
|
18055
|
+
break;
|
|
18056
|
+
}
|
|
18057
|
+
params.set(templateSegment.slice(1), requestSegment);
|
|
18058
|
+
} else if (templateSegment.toLowerCase() !== requestSegment.toLowerCase()) {
|
|
18059
|
+
matched = false;
|
|
18060
|
+
break;
|
|
18061
|
+
}
|
|
18062
|
+
}
|
|
18063
|
+
if (!matched) continue;
|
|
18064
|
+
const rawSessionId = params.get("id");
|
|
18065
|
+
const rawRequestId = params.get("requestId");
|
|
18066
|
+
const requestId = rawRequestId !== void 0 ? decodePathSegment(rawRequestId) : void 0;
|
|
18067
|
+
return {
|
|
18068
|
+
route: entry.route,
|
|
18069
|
+
attribution: entry.attribution,
|
|
18070
|
+
...rawSessionId ? { sessionId: decodePathSegment(rawSessionId) } : {},
|
|
18071
|
+
...requestId !== void 0 && requestId.length <= MAX_CLIENT_ID_LENGTH && CLIENT_ID_RE.test(requestId) ? { permissionRequestId: requestId } : {}
|
|
18072
|
+
};
|
|
18073
|
+
}
|
|
18074
|
+
return void 0;
|
|
18075
|
+
}
|
|
18076
|
+
__name(matchLegacySessionTelemetryRoute, "matchLegacySessionTelemetryRoute");
|
|
18077
|
+
function setDaemonTelemetryWorkspace(res, workspaceCwd) {
|
|
18078
|
+
try {
|
|
18079
|
+
const context = res[daemonTelemetryResponseContext];
|
|
18080
|
+
if (context && context.workspaceCwd === void 0) {
|
|
18081
|
+
context.workspaceCwd = workspaceCwd;
|
|
18082
|
+
}
|
|
18083
|
+
} catch {
|
|
18084
|
+
}
|
|
18085
|
+
}
|
|
18086
|
+
__name(setDaemonTelemetryWorkspace, "setDaemonTelemetryWorkspace");
|
|
18087
|
+
function resolveDaemonTelemetryRoute(req) {
|
|
18088
|
+
const legacyRoute = matchLegacySessionTelemetryRoute(req.method, req.path);
|
|
18089
|
+
if (legacyRoute) return legacyRoute;
|
|
18090
|
+
const path15 = req.path.replace(/\/$/, "") || "/";
|
|
18091
|
+
if (req.method === "GET" && path15 === "/daemon/status") {
|
|
18092
|
+
return { route: "GET /daemon/status" };
|
|
18093
|
+
}
|
|
18094
|
+
if (req.method === "GET" && /^\/workspace\/[^/]+\/sessions$/.test(path15)) {
|
|
18095
|
+
return { route: "GET /workspace/:id/sessions" };
|
|
18096
|
+
}
|
|
18097
|
+
if (req.method === "GET" && /^\/workspaces\/[^/]+\/sessions$/.test(path15)) {
|
|
18098
|
+
return { route: "GET /workspace/:id/sessions" };
|
|
18099
|
+
}
|
|
18100
|
+
if (req.method === "GET" && /^\/workspace\/[^/]+\/session-info$/.test(path15)) {
|
|
18101
|
+
return { route: "GET /workspace/:id/session-info" };
|
|
18102
|
+
}
|
|
18103
|
+
if (req.method === "GET" && /^\/workspaces\/[^/]+\/session-info$/.test(path15)) {
|
|
18104
|
+
return { route: "GET /workspace/:id/session-info" };
|
|
18105
|
+
}
|
|
18106
|
+
const workspaceTranscript = path15.match(
|
|
18107
|
+
/^\/workspaces\/[^/]+\/session\/([^/]+)\/transcript$/
|
|
18108
|
+
);
|
|
18109
|
+
if (workspaceTranscript?.[1] && req.method === "GET") {
|
|
18110
|
+
return {
|
|
18111
|
+
route: "GET /workspaces/:workspace/session/:id/transcript",
|
|
18112
|
+
sessionId: decodePathSegment(workspaceTranscript[1])
|
|
18113
|
+
};
|
|
18114
|
+
}
|
|
18115
|
+
const workspaceExport = path15.match(
|
|
18116
|
+
/^\/workspaces\/[^/]+\/session\/([^/]+)\/export$/
|
|
18117
|
+
);
|
|
18118
|
+
if (workspaceExport?.[1] && req.method === "GET") {
|
|
18119
|
+
return {
|
|
18120
|
+
route: "GET /workspaces/:workspace/session/:id/export",
|
|
18121
|
+
sessionId: decodePathSegment(workspaceExport[1])
|
|
18122
|
+
};
|
|
18123
|
+
}
|
|
18124
|
+
const workspaceArchivedExport = path15.match(
|
|
18125
|
+
/^\/workspaces\/[^/]+\/session\/([^/]+)\/archive\/export$/
|
|
18126
|
+
);
|
|
18127
|
+
if (workspaceArchivedExport?.[1] && req.method === "GET") {
|
|
18128
|
+
return {
|
|
18129
|
+
route: "GET /workspaces/:workspace/session/:id/archive/export",
|
|
18130
|
+
sessionId: decodePathSegment(workspaceArchivedExport[1])
|
|
18131
|
+
};
|
|
18132
|
+
}
|
|
18133
|
+
const pluralWorkspacePrefix = /^\/workspaces\/[^/]+/;
|
|
18134
|
+
if (pluralWorkspacePrefix.test(path15)) {
|
|
18135
|
+
const suffix = path15.replace(pluralWorkspacePrefix, "/workspace");
|
|
18136
|
+
if (req.method === "GET") {
|
|
18137
|
+
if (suffix === "/workspace/mcp" || suffix === "/workspace/skills" || suffix === "/workspace/tools" || suffix === "/workspace/providers" || suffix === "/workspace/env" || suffix === "/workspace/preflight" || suffix === "/workspace/hooks" || suffix === "/workspace/settings" || suffix === "/workspace/voice" || suffix === "/workspace/permissions" || suffix === "/workspace/trust" || suffix === "/workspace/memory" || suffix === "/workspace/agents") {
|
|
18138
|
+
return { route: `GET ${suffix}` };
|
|
18139
|
+
}
|
|
18140
|
+
if (/^\/workspace\/agents\/[^/]+$/.test(suffix)) {
|
|
18141
|
+
return { route: "GET /workspace/agents/:agentType" };
|
|
18142
|
+
}
|
|
18143
|
+
if (suffix === "/workspace/file") return { route: "GET /file" };
|
|
18144
|
+
if (suffix === "/workspace/file/bytes") {
|
|
18145
|
+
return { route: "GET /file/bytes" };
|
|
18146
|
+
}
|
|
18147
|
+
if (suffix === "/workspace/stat") return { route: "GET /stat" };
|
|
18148
|
+
if (suffix === "/workspace/list") return { route: "GET /list" };
|
|
18149
|
+
if (suffix === "/workspace/glob") return { route: "GET /glob" };
|
|
18150
|
+
if (/^\/workspace\/mcp\/[^/]+\/tools$/.test(suffix)) {
|
|
18151
|
+
return { route: "GET /workspace/mcp/:server/tools" };
|
|
18152
|
+
}
|
|
18153
|
+
if (/^\/workspace\/mcp\/[^/]+\/resources$/.test(suffix)) {
|
|
18154
|
+
return { route: "GET /workspace/mcp/:server/resources" };
|
|
18155
|
+
}
|
|
18156
|
+
}
|
|
18157
|
+
if (req.method === "POST") {
|
|
18158
|
+
if (suffix === "/workspace/settings" || suffix === "/workspace/voice" || suffix === "/workspace/voice/transcribe" || suffix === "/workspace/permissions" || suffix === "/workspace/trust/request" || suffix === "/workspace/init" || suffix === "/workspace/reload" || suffix === "/workspace/file/write" || suffix === "/workspace/file/edit" || suffix === "/workspace/mcp/servers" || suffix === "/workspace/memory" || suffix === "/workspace/agents" || suffix === "/workspace/sessions/delete" || suffix === "/workspace/sessions/archive" || suffix === "/workspace/sessions/unarchive" || suffix === "/workspace/session-groups") {
|
|
18159
|
+
return { route: `POST ${suffix}` };
|
|
18160
|
+
}
|
|
18161
|
+
if (/^\/workspace\/tools\/[^/]+\/enable$/.test(suffix)) {
|
|
18162
|
+
return { route: "POST /workspace/tools/:name/enable" };
|
|
18163
|
+
}
|
|
18164
|
+
if (/^\/workspace\/mcp\/[^/]+\/restart$/.test(suffix)) {
|
|
18165
|
+
return { route: "POST /workspace/mcp/:server/restart" };
|
|
18166
|
+
}
|
|
18167
|
+
if (/^\/workspace\/agents\/[^/]+$/.test(suffix)) {
|
|
18168
|
+
return { route: "POST /workspace/agents/:agentType" };
|
|
18169
|
+
}
|
|
18170
|
+
if (/^\/workspace\/mcp\/[^/]+\/(approve|enable|disable|authenticate|clear-auth)$/.test(
|
|
18171
|
+
suffix
|
|
18172
|
+
)) {
|
|
18173
|
+
return {
|
|
18174
|
+
route: `POST /workspace/mcp/:server/${suffix.split("/").at(-1)}`
|
|
18175
|
+
};
|
|
18176
|
+
}
|
|
18177
|
+
}
|
|
18178
|
+
if (req.method === "DELETE" && /^\/workspace\/mcp\/servers\/[^/]+$/.test(suffix)) {
|
|
18179
|
+
return { route: "DELETE /workspace/mcp/servers/:name" };
|
|
18180
|
+
}
|
|
18181
|
+
if (req.method === "DELETE" && /^\/workspace\/agents\/[^/]+$/.test(suffix)) {
|
|
18182
|
+
return { route: "DELETE /workspace/agents/:agentType" };
|
|
18183
|
+
}
|
|
18184
|
+
if (suffix === "/workspace/session-groups" && req.method === "GET") {
|
|
18185
|
+
return { route: "GET /workspace/session-groups" };
|
|
18186
|
+
}
|
|
18187
|
+
if (/^\/workspace\/session-groups\/[^/]+$/.test(suffix) && req.method === "PATCH") {
|
|
18188
|
+
return { route: "PATCH /workspace/session-groups/:groupId" };
|
|
18189
|
+
}
|
|
18190
|
+
if (/^\/workspace\/session-groups\/[^/]+$/.test(suffix) && req.method === "DELETE") {
|
|
18191
|
+
return { route: "DELETE /workspace/session-groups/:groupId" };
|
|
18192
|
+
}
|
|
18193
|
+
}
|
|
18194
|
+
if (req.method === "POST" && path15 === "/workspace/init") {
|
|
18195
|
+
return { route: "POST /workspace/init" };
|
|
18196
|
+
}
|
|
18197
|
+
if (req.method === "POST" && path15 === "/workspace/setup-github") {
|
|
18198
|
+
return { route: "POST /workspace/setup-github" };
|
|
18199
|
+
}
|
|
18200
|
+
if (req.method === "POST" && path15 === "/workspace/reload") {
|
|
18201
|
+
return { route: "POST /workspace/reload" };
|
|
18202
|
+
}
|
|
18203
|
+
const mcpRestart = path15.match(/^\/workspace\/mcp\/([^/]+)\/restart$/);
|
|
18204
|
+
if (mcpRestart?.[1] && req.method === "POST") {
|
|
18205
|
+
return { route: "POST /workspace/mcp/:server/restart" };
|
|
18206
|
+
}
|
|
18207
|
+
if (req.method === "POST" && path15 === "/workspace/mcp/servers") {
|
|
18208
|
+
return { route: "POST /workspace/mcp/servers" };
|
|
18209
|
+
}
|
|
18210
|
+
const mcpDelete = path15.match(/^\/workspace\/mcp\/servers\/([^/]+)$/);
|
|
18211
|
+
if (mcpDelete?.[1] && req.method === "DELETE") {
|
|
18212
|
+
return { route: "DELETE /workspace/mcp/servers/:name" };
|
|
18213
|
+
}
|
|
18214
|
+
if (req.method === "POST" && path15 === "/workspace/auth/device-flow") {
|
|
18215
|
+
return { route: "POST /workspace/auth/device-flow" };
|
|
18216
|
+
}
|
|
18217
|
+
const deviceFlowDelete = path15.match(
|
|
18218
|
+
/^\/workspace\/auth\/device-flow\/([^/]+)$/
|
|
18219
|
+
);
|
|
18220
|
+
if (deviceFlowDelete?.[1] && req.method === "DELETE") {
|
|
18221
|
+
return { route: "DELETE /workspace/auth/device-flow/:id" };
|
|
18222
|
+
}
|
|
18223
|
+
const toolEnable = path15.match(/^\/workspace\/tools\/([^/]+)\/enable$/);
|
|
18224
|
+
if (toolEnable?.[1] && req.method === "POST") {
|
|
18225
|
+
return { route: "POST /workspace/tools/:name/enable" };
|
|
18226
|
+
}
|
|
18227
|
+
if (path15 === "/workspace/settings") {
|
|
18228
|
+
if (req.method === "GET") return { route: "GET /workspace/settings" };
|
|
18229
|
+
if (req.method === "POST") return { route: "POST /workspace/settings" };
|
|
18230
|
+
}
|
|
18231
|
+
if (path15 === "/workspace/permissions") {
|
|
18232
|
+
if (req.method === "GET") return { route: "GET /workspace/permissions" };
|
|
18233
|
+
if (req.method === "POST") return { route: "POST /workspace/permissions" };
|
|
18234
|
+
}
|
|
18235
|
+
if (path15 === "/workspace/trust") {
|
|
18236
|
+
if (req.method === "GET") return { route: "GET /workspace/trust" };
|
|
18237
|
+
}
|
|
18238
|
+
if (req.method === "POST" && path15 === "/workspace/trust/request") {
|
|
18239
|
+
return { route: "POST /workspace/trust/request" };
|
|
18240
|
+
}
|
|
18241
|
+
if (path15 === "/workspace/voice") {
|
|
18242
|
+
if (req.method === "GET") return { route: "GET /workspace/voice" };
|
|
18243
|
+
if (req.method === "POST") return { route: "POST /workspace/voice" };
|
|
18244
|
+
}
|
|
18245
|
+
if (req.method === "POST" && path15 === "/workspace/voice/transcribe") {
|
|
18246
|
+
return { route: "POST /workspace/voice/transcribe" };
|
|
18247
|
+
}
|
|
18248
|
+
return void 0;
|
|
18249
|
+
}
|
|
18250
|
+
__name(resolveDaemonTelemetryRoute, "resolveDaemonTelemetryRoute");
|
|
18251
|
+
function daemonTelemetryMiddleware(resolveWorkspaceCwd, recordRequest) {
|
|
18252
|
+
const workspaceHashByCwd = /* @__PURE__ */ new Map();
|
|
18253
|
+
const resolveWorkspaceHash = /* @__PURE__ */ __name((workspaceCwd) => {
|
|
18254
|
+
const existing = workspaceHashByCwd.get(workspaceCwd);
|
|
18255
|
+
if (existing !== void 0) return existing;
|
|
18256
|
+
const workspaceHash = hashDaemonWorkspace(workspaceCwd);
|
|
18257
|
+
workspaceHashByCwd.set(workspaceCwd, workspaceHash);
|
|
18258
|
+
return workspaceHash;
|
|
18259
|
+
}, "resolveWorkspaceHash");
|
|
18260
|
+
return (req, res, next) => {
|
|
18261
|
+
const route = resolveDaemonTelemetryRoute(req);
|
|
18262
|
+
if (!route) {
|
|
18263
|
+
next();
|
|
18264
|
+
return;
|
|
18265
|
+
}
|
|
18266
|
+
const sessionId = route.sessionId;
|
|
18267
|
+
let workspaceHash;
|
|
18268
|
+
if (route.attribution !== "handler_resolved") {
|
|
18269
|
+
try {
|
|
18270
|
+
workspaceHash = resolveWorkspaceHash(resolveWorkspaceCwd(req));
|
|
18271
|
+
} catch {
|
|
18272
|
+
}
|
|
18273
|
+
}
|
|
18274
|
+
const rawClientId = req.get(CLIENT_ID_HEADER);
|
|
18275
|
+
const clientId = rawClientId !== void 0 && rawClientId !== "" && rawClientId.length <= MAX_CLIENT_ID_LENGTH && CLIENT_ID_RE.test(rawClientId) ? rawClientId : void 0;
|
|
18276
|
+
const deferredRuntime = getDeferredRuntimeRequestTiming(req);
|
|
18277
|
+
const startMs = deferredRuntime?.startedAt.getTime() ?? Date.now();
|
|
18278
|
+
const telemetryRes = res;
|
|
18279
|
+
if (route.attribution === "handler_resolved") {
|
|
18280
|
+
try {
|
|
18281
|
+
telemetryRes[daemonTelemetryResponseContext] = {};
|
|
18282
|
+
} catch {
|
|
18283
|
+
}
|
|
18284
|
+
}
|
|
18285
|
+
void withDaemonRequestSpan(
|
|
18286
|
+
{
|
|
18287
|
+
method: req.method,
|
|
18288
|
+
route: route.route,
|
|
18289
|
+
...workspaceHash !== void 0 ? { workspaceHash } : {},
|
|
18290
|
+
...sessionId ? { sessionId } : {},
|
|
18291
|
+
...route.permissionRequestId ? { permissionRequestId: route.permissionRequestId } : {},
|
|
18292
|
+
...clientId ? { clientId } : {},
|
|
18293
|
+
...deferredRuntime?.waitMs !== void 0 ? {
|
|
18294
|
+
startTime: deferredRuntime.startedAt,
|
|
18295
|
+
deferredRuntimeWaitMs: deferredRuntime.waitMs,
|
|
18296
|
+
deferredRuntimePath: deferredRuntime.path
|
|
18297
|
+
} : {}
|
|
18298
|
+
},
|
|
18299
|
+
async (span) => await new Promise((resolve5, reject) => {
|
|
18300
|
+
let done = false;
|
|
18301
|
+
const finish = /* @__PURE__ */ __name(() => {
|
|
18302
|
+
if (done) return;
|
|
18303
|
+
done = true;
|
|
18304
|
+
try {
|
|
18305
|
+
const context = telemetryRes[daemonTelemetryResponseContext];
|
|
18306
|
+
delete telemetryRes[daemonTelemetryResponseContext];
|
|
18307
|
+
if (context?.workspaceCwd !== void 0) {
|
|
18308
|
+
span?.setAttribute(
|
|
18309
|
+
"qwen-code.workspace.hash",
|
|
18310
|
+
resolveWorkspaceHash(context.workspaceCwd)
|
|
18311
|
+
);
|
|
18312
|
+
}
|
|
18313
|
+
} catch {
|
|
18314
|
+
}
|
|
18315
|
+
recordDaemonHttpResponse(span, res.statusCode);
|
|
18316
|
+
const durationMs = Date.now() - startMs;
|
|
18317
|
+
const successfulSse = route.route === "GET /session/:id/events" && res.statusCode === 200 && res.headersSent;
|
|
18318
|
+
if (!successfulSse) {
|
|
18319
|
+
recordDaemonHttpRequest(
|
|
18320
|
+
durationMs,
|
|
18321
|
+
route.route,
|
|
18322
|
+
res.statusCode,
|
|
18323
|
+
deferredRuntime?.path
|
|
18324
|
+
);
|
|
18325
|
+
}
|
|
18326
|
+
if (!successfulSse && route.route !== "GET /daemon/status" && route.route !== "POST /session/:id/heartbeat") {
|
|
18327
|
+
recordRequest?.(durationMs, res.statusCode);
|
|
18328
|
+
}
|
|
18329
|
+
resolve5();
|
|
18330
|
+
}, "finish");
|
|
18331
|
+
res.once("finish", finish);
|
|
18332
|
+
res.once("close", finish);
|
|
18333
|
+
try {
|
|
18334
|
+
next();
|
|
18335
|
+
} catch (error2) {
|
|
18336
|
+
recordDaemonError(span, error2);
|
|
18337
|
+
reject(error2);
|
|
18338
|
+
}
|
|
18339
|
+
})
|
|
18340
|
+
).catch(next);
|
|
18341
|
+
};
|
|
18342
|
+
}
|
|
18343
|
+
__name(daemonTelemetryMiddleware, "daemonTelemetryMiddleware");
|
|
18344
|
+
|
|
18345
|
+
// packages/cli/src/serve/routes/session-runtime.ts
|
|
18346
|
+
function requireSessionRuntime(opts) {
|
|
18347
|
+
const {
|
|
18348
|
+
sessionId,
|
|
18349
|
+
route,
|
|
18350
|
+
res,
|
|
18351
|
+
workspaceRegistry,
|
|
18352
|
+
daemonLog,
|
|
18353
|
+
details = {}
|
|
18354
|
+
} = opts;
|
|
18355
|
+
if (workspaceRegistry.list().length === 1) {
|
|
18356
|
+
const runtime = workspaceRegistry.primary;
|
|
18357
|
+
setDaemonTelemetryWorkspace(res, runtime.workspaceCwd);
|
|
18358
|
+
return runtime;
|
|
18359
|
+
}
|
|
18360
|
+
const resolution = workspaceRegistry.resolveLiveSessionOwner(sessionId);
|
|
18361
|
+
if (resolution.kind === "found") {
|
|
18362
|
+
const runtime = resolution.runtime;
|
|
18363
|
+
setDaemonTelemetryWorkspace(res, runtime.workspaceCwd);
|
|
18364
|
+
if (!runtime.primary && !runtime.trusted) {
|
|
18365
|
+
daemonLog?.warn("session routing failed", {
|
|
18366
|
+
route,
|
|
18367
|
+
resolutionKind: "untrusted_workspace",
|
|
18368
|
+
sessionId,
|
|
18369
|
+
workspaceId: runtime.workspaceId,
|
|
18370
|
+
workspaceCwd: runtime.workspaceCwd,
|
|
18371
|
+
...details
|
|
18372
|
+
});
|
|
18373
|
+
sendUntrustedWorkspaceResponse(res, {
|
|
18374
|
+
sessionId,
|
|
18375
|
+
workspaceCwd: runtime.workspaceCwd,
|
|
18376
|
+
workspaceId: runtime.workspaceId
|
|
18377
|
+
});
|
|
18378
|
+
return void 0;
|
|
18379
|
+
}
|
|
18380
|
+
return runtime;
|
|
18381
|
+
}
|
|
18382
|
+
if (resolution.kind === "not_found") {
|
|
18383
|
+
daemonLog?.warn("session routing failed", {
|
|
18384
|
+
route,
|
|
18385
|
+
resolutionKind: "not_found",
|
|
18386
|
+
sessionId,
|
|
18387
|
+
...details
|
|
18388
|
+
});
|
|
18389
|
+
res.status(404).json({
|
|
18390
|
+
error: `No session with id "${sessionId}"`,
|
|
18391
|
+
code: "session_not_found",
|
|
18392
|
+
sessionId
|
|
18393
|
+
});
|
|
18394
|
+
return void 0;
|
|
18395
|
+
}
|
|
18396
|
+
const workspaceIds = resolution.runtimes.map(
|
|
18397
|
+
(runtime) => runtime.workspaceId
|
|
18398
|
+
);
|
|
18399
|
+
daemonLog?.warn("session routing failed", {
|
|
18400
|
+
route,
|
|
18401
|
+
resolutionKind: "ambiguous",
|
|
18402
|
+
sessionId,
|
|
18403
|
+
workspaceIds,
|
|
18404
|
+
...details
|
|
18405
|
+
});
|
|
18406
|
+
res.status(500).json({
|
|
18407
|
+
error: `Session owner is ambiguous for "${sessionId}"`,
|
|
18408
|
+
code: "ambiguous_session_owner",
|
|
18409
|
+
sessionId,
|
|
17419
18410
|
route,
|
|
17420
18411
|
workspaceIds
|
|
17421
18412
|
});
|
|
@@ -17509,7 +18500,7 @@ __name(registerPermissionRoutes, "registerPermissionRoutes");
|
|
|
17509
18500
|
|
|
17510
18501
|
// packages/cli/src/serve/routes/session.ts
|
|
17511
18502
|
init_esbuild_shims();
|
|
17512
|
-
import * as
|
|
18503
|
+
import * as crypto3 from "node:crypto";
|
|
17513
18504
|
import * as path11 from "node:path";
|
|
17514
18505
|
|
|
17515
18506
|
// packages/cli/src/serve/server/prompt-deadline.ts
|
|
@@ -17566,7 +18557,7 @@ function parseOrganizedCursor(cursor, expected) {
|
|
|
17566
18557
|
const decoded = Buffer.from(cursor, "base64url").toString("utf8");
|
|
17567
18558
|
const parsed = JSON.parse(decoded);
|
|
17568
18559
|
const last = parsed.last;
|
|
17569
|
-
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed) || typeof last !== "object" || last === null || Array.isArray(last) || typeof last.isPinned !== "boolean" || typeof last.activityTime !== "number" || !Number.isFinite(last.activityTime) || typeof last.sessionId !== "string" || last.sessionId.length === 0 || parsed.group !== expected.group || parsed.archiveState !== expected.archiveState) {
|
|
18560
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed) || typeof last !== "object" || last === null || Array.isArray(last) || typeof last.isPinned !== "boolean" || typeof last.activityTime !== "number" || !Number.isFinite(last.activityTime) || typeof last.sessionId !== "string" || last.sessionId.length === 0 || parsed.group !== expected.group || parsed.archiveState !== expected.archiveState || parsed.sourceType !== expected.sourceType || parsed.sourceId !== expected.sourceId) {
|
|
17570
18561
|
throw new Error("invalid organized cursor");
|
|
17571
18562
|
}
|
|
17572
18563
|
return last;
|
|
@@ -17575,9 +18566,9 @@ function parseOrganizedCursor(cursor, expected) {
|
|
|
17575
18566
|
}
|
|
17576
18567
|
}
|
|
17577
18568
|
__name(parseOrganizedCursor, "parseOrganizedCursor");
|
|
17578
|
-
function encodeOrganizedCursor(last, group, archiveState) {
|
|
18569
|
+
function encodeOrganizedCursor(last, group, archiveState, sourceType, sourceId) {
|
|
17579
18570
|
return Buffer.from(
|
|
17580
|
-
JSON.stringify({ group, archiveState, last }),
|
|
18571
|
+
JSON.stringify({ group, archiveState, sourceType, sourceId, last }),
|
|
17581
18572
|
"utf8"
|
|
17582
18573
|
).toString("base64url");
|
|
17583
18574
|
}
|
|
@@ -17601,29 +18592,39 @@ function encodeLiveSessionCursor(last) {
|
|
|
17601
18592
|
return Buffer.from(JSON.stringify(last), "utf8").toString("base64url");
|
|
17602
18593
|
}
|
|
17603
18594
|
__name(encodeLiveSessionCursor, "encodeLiveSessionCursor");
|
|
17604
|
-
function
|
|
18595
|
+
function matchesSessionMetadataSource(session, filter) {
|
|
18596
|
+
const sourceTypeMatches = filter.sourceType === void 0 || session.sourceType === filter.sourceType || // Legacy sessions without source metadata belong to the default catalog.
|
|
18597
|
+
filter.sourceType === "default" && session.sourceType === void 0;
|
|
18598
|
+
return sourceTypeMatches && // sourceId remains exact; only the default source type has legacy fallback.
|
|
18599
|
+
(filter.sourceId === void 0 || session.sourceId === filter.sourceId);
|
|
18600
|
+
}
|
|
18601
|
+
__name(matchesSessionMetadataSource, "matchesSessionMetadataSource");
|
|
18602
|
+
function parseMetadataSessionCursor(cursor, expected) {
|
|
17605
18603
|
if (cursor === "") return void 0;
|
|
17606
18604
|
try {
|
|
17607
18605
|
const parsed = JSON.parse(
|
|
17608
18606
|
Buffer.from(cursor, "base64url").toString("utf8")
|
|
17609
18607
|
);
|
|
17610
18608
|
const last = parsed.last;
|
|
17611
|
-
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed) || typeof last !== "object" || last === null || Array.isArray(last) || typeof last.activityTime !== "number" || !Number.isFinite(last.activityTime) || typeof last.sessionId !== "string" || last.sessionId.length === 0 || parsed.parentSessionId !== expected.parentSessionId || parsed.archiveState !== expected.archiveState) {
|
|
17612
|
-
throw new Error("invalid
|
|
18609
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed) || typeof last !== "object" || last === null || Array.isArray(last) || typeof last.activityTime !== "number" || !Number.isFinite(last.activityTime) || typeof last.sessionId !== "string" || last.sessionId.length === 0 || parsed.parentSessionId !== expected.parentSessionId || parsed.sourceType !== expected.sourceType || parsed.sourceId !== expected.sourceId || parsed.archiveState !== expected.archiveState) {
|
|
18610
|
+
throw new Error("invalid metadata cursor");
|
|
17613
18611
|
}
|
|
17614
18612
|
return { activityTime: last.activityTime, sessionId: last.sessionId };
|
|
17615
18613
|
} catch {
|
|
17616
|
-
throw new InvalidCursorError(
|
|
18614
|
+
throw new InvalidCursorError(
|
|
18615
|
+
cursor,
|
|
18616
|
+
expected.sourceType === void 0 ? "parent" : "metadata"
|
|
18617
|
+
);
|
|
17617
18618
|
}
|
|
17618
18619
|
}
|
|
17619
|
-
__name(
|
|
17620
|
-
function
|
|
18620
|
+
__name(parseMetadataSessionCursor, "parseMetadataSessionCursor");
|
|
18621
|
+
function encodeMetadataSessionCursor(last, filter, archiveState) {
|
|
17621
18622
|
return Buffer.from(
|
|
17622
|
-
JSON.stringify({
|
|
18623
|
+
JSON.stringify({ ...filter, archiveState, last }),
|
|
17623
18624
|
"utf8"
|
|
17624
18625
|
).toString("base64url");
|
|
17625
18626
|
}
|
|
17626
|
-
__name(
|
|
18627
|
+
__name(encodeMetadataSessionCursor, "encodeMetadataSessionCursor");
|
|
17627
18628
|
function toSummary2(item) {
|
|
17628
18629
|
return {
|
|
17629
18630
|
sessionId: item.sessionId,
|
|
@@ -17632,6 +18633,8 @@ function toSummary2(item) {
|
|
|
17632
18633
|
updatedAt: new Date(item.mtime).toISOString(),
|
|
17633
18634
|
displayName: item.customTitle || item.prompt,
|
|
17634
18635
|
...item.parentSessionId ? { parentSessionId: item.parentSessionId } : {},
|
|
18636
|
+
...item.sourceType ? { sourceType: item.sourceType } : {},
|
|
18637
|
+
...item.sourceId !== void 0 ? { sourceId: item.sourceId } : {},
|
|
17635
18638
|
clientCount: 0,
|
|
17636
18639
|
hasActivePrompt: false,
|
|
17637
18640
|
isArchived: item.isArchived === true
|
|
@@ -17647,6 +18650,8 @@ function mergeLiveSessionSummary(existing, live) {
|
|
|
17647
18650
|
// Immutable lineage; the persisted transcript is authoritative, and a live
|
|
17648
18651
|
// entry only carries it when spawned this run.
|
|
17649
18652
|
parentSessionId: existing.parentSessionId ?? live.parentSessionId,
|
|
18653
|
+
sourceType: existing.sourceType ?? live.sourceType,
|
|
18654
|
+
sourceId: existing.sourceType !== void 0 ? existing.sourceId : live.sourceId,
|
|
17650
18655
|
updatedAt: live.updatedAt ?? existing.updatedAt,
|
|
17651
18656
|
clientCount: live.clientCount,
|
|
17652
18657
|
hasActivePrompt: live.hasActivePrompt,
|
|
@@ -17746,7 +18751,12 @@ async function listOrganizedWorkspaceSessionsForResponse(bridge, workspaceCwd, o
|
|
|
17746
18751
|
"group"
|
|
17747
18752
|
);
|
|
17748
18753
|
}
|
|
17749
|
-
const cursorKey = options.cursor !== void 0 ? parseOrganizedCursor(options.cursor, {
|
|
18754
|
+
const cursorKey = options.cursor !== void 0 ? parseOrganizedCursor(options.cursor, {
|
|
18755
|
+
group,
|
|
18756
|
+
archiveState,
|
|
18757
|
+
sourceType: options.sourceType,
|
|
18758
|
+
sourceId: options.sourceId
|
|
18759
|
+
}) : void 0;
|
|
17750
18760
|
const isFirstPage = cursorKey === void 0;
|
|
17751
18761
|
let liveMergeFailed = false;
|
|
17752
18762
|
const bySessionId = /* @__PURE__ */ new Map();
|
|
@@ -17798,6 +18808,7 @@ async function listOrganizedWorkspaceSessionsForResponse(bridge, workspaceCwd, o
|
|
|
17798
18808
|
}
|
|
17799
18809
|
}
|
|
17800
18810
|
const filtered = [...bySessionId.values()].filter((session) => {
|
|
18811
|
+
if (!matchesSessionMetadataSource(session, options)) return false;
|
|
17801
18812
|
if (group === "all") return true;
|
|
17802
18813
|
if (group === "pinned") return session.isPinned === true;
|
|
17803
18814
|
if (group === "ungrouped")
|
|
@@ -17821,7 +18832,9 @@ async function listOrganizedWorkspaceSessionsForResponse(bridge, workspaceCwd, o
|
|
|
17821
18832
|
const nextCursor = page.length < afterCursor.length ? encodeOrganizedCursor(
|
|
17822
18833
|
getOrganizedCursorKey(activityTimeById, page[page.length - 1]),
|
|
17823
18834
|
group,
|
|
17824
|
-
archiveState
|
|
18835
|
+
archiveState,
|
|
18836
|
+
options.sourceType,
|
|
18837
|
+
options.sourceId
|
|
17825
18838
|
) : void 0;
|
|
17826
18839
|
return {
|
|
17827
18840
|
sessions: page,
|
|
@@ -17831,7 +18844,7 @@ async function listOrganizedWorkspaceSessionsForResponse(bridge, workspaceCwd, o
|
|
|
17831
18844
|
};
|
|
17832
18845
|
}
|
|
17833
18846
|
__name(listOrganizedWorkspaceSessionsForResponse, "listOrganizedWorkspaceSessionsForResponse");
|
|
17834
|
-
async function
|
|
18847
|
+
async function listWorkspaceSessionsByMetadataForResponse(bridge, workspaceCwd, options, pageSize, filter, readOptions) {
|
|
17835
18848
|
const archiveState = options.archiveState ?? "active";
|
|
17836
18849
|
const sessionService = new SessionService(workspaceCwd);
|
|
17837
18850
|
const bySessionId = /* @__PURE__ */ new Map();
|
|
@@ -17865,18 +18878,20 @@ async function listWorkspaceSessionsByParentForResponse(bridge, workspaceCwd, op
|
|
|
17865
18878
|
} catch (error2) {
|
|
17866
18879
|
liveMergeFailed = true;
|
|
17867
18880
|
writeStderrLine(
|
|
17868
|
-
`qwen serve: session
|
|
18881
|
+
`qwen serve: session metadata filter live merge failed; using persisted sessions only: ${error2 instanceof Error ? error2.message : String(error2)}`
|
|
17869
18882
|
);
|
|
17870
18883
|
}
|
|
17871
18884
|
}
|
|
17872
|
-
const matches = [...bySessionId.values()].filter(
|
|
18885
|
+
const matches = [...bySessionId.values()].filter(
|
|
18886
|
+
(session) => (filter.parentSessionId === void 0 || session.parentSessionId === filter.parentSessionId) && matchesSessionMetadataSource(session, filter)
|
|
18887
|
+
).sort(
|
|
17873
18888
|
(a, b) => compareLiveSessionCursorKeys(
|
|
17874
18889
|
getLiveSessionCursorKey(a),
|
|
17875
18890
|
getLiveSessionCursorKey(b)
|
|
17876
18891
|
)
|
|
17877
18892
|
);
|
|
17878
|
-
const cursorKey = options.cursor !== void 0 && options.cursor !== "" ?
|
|
17879
|
-
|
|
18893
|
+
const cursorKey = options.cursor !== void 0 && options.cursor !== "" ? parseMetadataSessionCursor(options.cursor, {
|
|
18894
|
+
...filter,
|
|
17880
18895
|
archiveState
|
|
17881
18896
|
}) : void 0;
|
|
17882
18897
|
const afterCursor = cursorKey === void 0 ? matches : matches.filter(
|
|
@@ -17886,9 +18901,9 @@ async function listWorkspaceSessionsByParentForResponse(bridge, workspaceCwd, op
|
|
|
17886
18901
|
) < 0
|
|
17887
18902
|
);
|
|
17888
18903
|
const page = afterCursor.slice(0, pageSize);
|
|
17889
|
-
const nextCursor = page.length < afterCursor.length ?
|
|
18904
|
+
const nextCursor = page.length < afterCursor.length ? encodeMetadataSessionCursor(
|
|
17890
18905
|
getLiveSessionCursorKey(page[page.length - 1]),
|
|
17891
|
-
|
|
18906
|
+
filter,
|
|
17892
18907
|
archiveState
|
|
17893
18908
|
) : void 0;
|
|
17894
18909
|
return {
|
|
@@ -17898,7 +18913,7 @@ async function listWorkspaceSessionsByParentForResponse(bridge, workspaceCwd, op
|
|
|
17898
18913
|
...persisted.truncated ? { truncated: true } : {}
|
|
17899
18914
|
};
|
|
17900
18915
|
}
|
|
17901
|
-
__name(
|
|
18916
|
+
__name(listWorkspaceSessionsByMetadataForResponse, "listWorkspaceSessionsByMetadataForResponse");
|
|
17902
18917
|
async function listWorkspaceSessionsForResponse(bridge, workspaceCwd, options, readOptions = {}) {
|
|
17903
18918
|
const rawSize = options?.size;
|
|
17904
18919
|
const requestedSize = typeof rawSize === "number" && Number.isSafeInteger(rawSize) ? rawSize : DEFAULT_SESSION_PAGE_SIZE;
|
|
@@ -17912,13 +18927,17 @@ async function listWorkspaceSessionsForResponse(bridge, workspaceCwd, options, r
|
|
|
17912
18927
|
readOptions
|
|
17913
18928
|
);
|
|
17914
18929
|
}
|
|
17915
|
-
if (options?.parentSessionId !== void 0) {
|
|
17916
|
-
return
|
|
18930
|
+
if (options?.parentSessionId !== void 0 || options?.sourceType !== void 0) {
|
|
18931
|
+
return listWorkspaceSessionsByMetadataForResponse(
|
|
17917
18932
|
bridge,
|
|
17918
18933
|
workspaceCwd,
|
|
17919
18934
|
options,
|
|
17920
18935
|
pageSize,
|
|
17921
|
-
|
|
18936
|
+
{
|
|
18937
|
+
...options.parentSessionId !== void 0 ? { parentSessionId: options.parentSessionId } : {},
|
|
18938
|
+
...options.sourceType !== void 0 ? { sourceType: options.sourceType } : {},
|
|
18939
|
+
...options.sourceId !== void 0 ? { sourceId: options.sourceId } : {}
|
|
18940
|
+
},
|
|
17922
18941
|
readOptions
|
|
17923
18942
|
);
|
|
17924
18943
|
}
|
|
@@ -17992,6 +19011,19 @@ function listLiveWorkspaceSessionsForResponse(bridge, workspaceCwd, options) {
|
|
|
17992
19011
|
};
|
|
17993
19012
|
}
|
|
17994
19013
|
__name(listLiveWorkspaceSessionsForResponse, "listLiveWorkspaceSessionsForResponse");
|
|
19014
|
+
async function getWorkspaceSessionInfoForResponse(bridge, workspaceCwd, options = {}) {
|
|
19015
|
+
const counts = await new SessionService(workspaceCwd).getSessionInfoCounts();
|
|
19016
|
+
return {
|
|
19017
|
+
active: counts.active,
|
|
19018
|
+
archived: counts.archived,
|
|
19019
|
+
total: counts.total,
|
|
19020
|
+
...options.includeLive === false ? {} : { live: bridge.listWorkspaceSessions(workspaceCwd).length },
|
|
19021
|
+
expensive: true,
|
|
19022
|
+
cost: "disk_scan",
|
|
19023
|
+
...counts.truncated ? { truncated: true } : {}
|
|
19024
|
+
};
|
|
19025
|
+
}
|
|
19026
|
+
__name(getWorkspaceSessionInfoForResponse, "getWorkspaceSessionInfoForResponse");
|
|
17995
19027
|
function parseSessionPageSizeQuery(raw) {
|
|
17996
19028
|
if (typeof raw !== "string") return void 0;
|
|
17997
19029
|
const trimmed = raw.trim();
|
|
@@ -18036,9 +19068,10 @@ function sessionExportFormatValues() {
|
|
|
18036
19068
|
__name(sessionExportFormatValues, "sessionExportFormatValues");
|
|
18037
19069
|
async function exportSessionTranscript(params) {
|
|
18038
19070
|
const { workspaceCwd, sessionId, format } = params;
|
|
18039
|
-
const
|
|
18040
|
-
|
|
18041
|
-
|
|
19071
|
+
const service = new SessionService(workspaceCwd);
|
|
19072
|
+
const sessionData = params.archiveState === "archived" ? await service.loadArchivedSession(sessionId, {
|
|
19073
|
+
maxBytes: SESSION_TRANSCRIPT_MAX_INDEX_BYTES
|
|
19074
|
+
}) : await service.loadSession(sessionId);
|
|
18042
19075
|
if (!sessionData) {
|
|
18043
19076
|
throw new SessionNotFoundError(sessionId);
|
|
18044
19077
|
}
|
|
@@ -18063,10 +19096,63 @@ async function exportSessionTranscript(params) {
|
|
|
18063
19096
|
__name(exportSessionTranscript, "exportSessionTranscript");
|
|
18064
19097
|
|
|
18065
19098
|
// packages/cli/src/serve/routes/session.ts
|
|
18066
|
-
var WORKSPACE_TRANSCRIPT_PAGE_SOURCE_MAX_BYTES = 4 * 1024 * 1024;
|
|
18067
19099
|
var WORKSPACE_TRANSCRIPT_RESPONSE_MAX_BYTES = 32 * 1024 * 1024;
|
|
18068
19100
|
var WORKSPACE_TRANSCRIPT_CURSOR_MAX_BYTES = 64 * 1024;
|
|
18069
19101
|
var TRANSCRIPT_CURSOR_TOO_LARGE_REPLAY_ERROR = "Transcript pagination state exceeds the safe limit";
|
|
19102
|
+
var GENERATION_HEARTBEAT_MS = 15e3;
|
|
19103
|
+
var PRIMARY_ONLY_LIVE_SESSION_ROUTES = [
|
|
19104
|
+
"POST /session/:id/branch",
|
|
19105
|
+
"POST /session/:id/fork",
|
|
19106
|
+
"POST /session/:id/cd"
|
|
19107
|
+
];
|
|
19108
|
+
function isPrimaryOnlyLiveSessionRoute(route) {
|
|
19109
|
+
return PRIMARY_ONLY_LIVE_SESSION_ROUTES.includes(
|
|
19110
|
+
route
|
|
19111
|
+
);
|
|
19112
|
+
}
|
|
19113
|
+
__name(isPrimaryOnlyLiveSessionRoute, "isPrimaryOnlyLiveSessionRoute");
|
|
19114
|
+
function formatGenerationSse(event, data) {
|
|
19115
|
+
return `event: ${event}
|
|
19116
|
+
data: ${JSON.stringify({ v: 1, ...data })}
|
|
19117
|
+
|
|
19118
|
+
`;
|
|
19119
|
+
}
|
|
19120
|
+
__name(formatGenerationSse, "formatGenerationSse");
|
|
19121
|
+
function writeGenerationSseChunk(res, chunk) {
|
|
19122
|
+
if (res.destroyed) {
|
|
19123
|
+
return Promise.reject(new Error("Generation SSE connection destroyed"));
|
|
19124
|
+
}
|
|
19125
|
+
const writable = res.write(chunk);
|
|
19126
|
+
const flush = res.flush;
|
|
19127
|
+
flush?.call(res);
|
|
19128
|
+
if (writable) {
|
|
19129
|
+
return res.destroyed ? Promise.reject(new Error("Generation SSE connection destroyed")) : Promise.resolve();
|
|
19130
|
+
}
|
|
19131
|
+
return new Promise((resolve5, reject) => {
|
|
19132
|
+
const cleanup = /* @__PURE__ */ __name(() => {
|
|
19133
|
+
res.off("drain", onDrain);
|
|
19134
|
+
res.off("close", onClose);
|
|
19135
|
+
res.off("error", onError);
|
|
19136
|
+
}, "cleanup");
|
|
19137
|
+
const onDrain = /* @__PURE__ */ __name(() => {
|
|
19138
|
+
cleanup();
|
|
19139
|
+
resolve5();
|
|
19140
|
+
}, "onDrain");
|
|
19141
|
+
const onClose = /* @__PURE__ */ __name(() => {
|
|
19142
|
+
cleanup();
|
|
19143
|
+
reject(new Error("Generation SSE connection closed"));
|
|
19144
|
+
}, "onClose");
|
|
19145
|
+
const onError = /* @__PURE__ */ __name((error2) => {
|
|
19146
|
+
cleanup();
|
|
19147
|
+
reject(error2);
|
|
19148
|
+
}, "onError");
|
|
19149
|
+
res.once("drain", onDrain);
|
|
19150
|
+
res.once("close", onClose);
|
|
19151
|
+
res.once("error", onError);
|
|
19152
|
+
if (res.destroyed) onClose();
|
|
19153
|
+
});
|
|
19154
|
+
}
|
|
19155
|
+
__name(writeGenerationSseChunk, "writeGenerationSseChunk");
|
|
18070
19156
|
function isReadOnlyWorkspaceInspection(runtime) {
|
|
18071
19157
|
return !runtime.primary && !runtime.trusted;
|
|
18072
19158
|
}
|
|
@@ -18153,6 +19239,32 @@ function parseTranscriptCursorQuery(rawCursor, res) {
|
|
|
18153
19239
|
return rawCursor;
|
|
18154
19240
|
}
|
|
18155
19241
|
__name(parseTranscriptCursorQuery, "parseTranscriptCursorQuery");
|
|
19242
|
+
function parseTranscriptRecordBoundaryQuery(rawBoundary, res) {
|
|
19243
|
+
if (rawBoundary === void 0) return void 0;
|
|
19244
|
+
if (typeof rawBoundary !== "string" || rawBoundary.trim() === "" || rawBoundary.length > 200) {
|
|
19245
|
+
res.status(400).json({
|
|
19246
|
+
error: "`beforeRecordId` must be a non-empty record id",
|
|
19247
|
+
code: "invalid_transcript_cursor"
|
|
19248
|
+
});
|
|
19249
|
+
return null;
|
|
19250
|
+
}
|
|
19251
|
+
return rawBoundary;
|
|
19252
|
+
}
|
|
19253
|
+
__name(parseTranscriptRecordBoundaryQuery, "parseTranscriptRecordBoundaryQuery");
|
|
19254
|
+
function parseHistoryPageSize(body, res) {
|
|
19255
|
+
const value = body["historyPageSize"];
|
|
19256
|
+
if (value === void 0) return void 0;
|
|
19257
|
+
if (!Number.isSafeInteger(value) || value < 1 || value > SESSION_TRANSCRIPT_MAX_LIMIT) {
|
|
19258
|
+
res.status(400).json({
|
|
19259
|
+
error: `\`historyPageSize\` must be between 1 and ${SESSION_TRANSCRIPT_MAX_LIMIT}`,
|
|
19260
|
+
code: "invalid_transcript_limit",
|
|
19261
|
+
maxLimit: SESSION_TRANSCRIPT_MAX_LIMIT
|
|
19262
|
+
});
|
|
19263
|
+
return null;
|
|
19264
|
+
}
|
|
19265
|
+
return value;
|
|
19266
|
+
}
|
|
19267
|
+
__name(parseHistoryPageSize, "parseHistoryPageSize");
|
|
18156
19268
|
function workspaceTranscriptCursorExceedsLimit(cursor, maxBytes = WORKSPACE_TRANSCRIPT_CURSOR_MAX_BYTES) {
|
|
18157
19269
|
return Buffer.byteLength(cursor) > maxBytes;
|
|
18158
19270
|
}
|
|
@@ -18212,14 +19324,14 @@ function registerSessionRoutes(app, deps) {
|
|
|
18212
19324
|
sessionShellCommandEnabled
|
|
18213
19325
|
} = deps;
|
|
18214
19326
|
const LANGUAGE_CODES = deps.languageCodes;
|
|
18215
|
-
const transcriptCursorMasterKey =
|
|
19327
|
+
const transcriptCursorMasterKey = crypto3.randomBytes(32);
|
|
18216
19328
|
const transcriptCursorCodecs = /* @__PURE__ */ new Map();
|
|
18217
19329
|
const getTranscriptCursorCodec = /* @__PURE__ */ __name((runtime) => {
|
|
18218
19330
|
const canonicalCwd = canonicalizeWorkspace(runtime.workspaceCwd);
|
|
18219
19331
|
const cacheKey = `${runtime.workspaceId}\0${canonicalCwd}`;
|
|
18220
19332
|
const cached = transcriptCursorCodecs.get(cacheKey);
|
|
18221
19333
|
if (cached) return cached;
|
|
18222
|
-
const derivedKey =
|
|
19334
|
+
const derivedKey = crypto3.hkdfSync(
|
|
18223
19335
|
"sha256",
|
|
18224
19336
|
transcriptCursorMasterKey,
|
|
18225
19337
|
Buffer.alloc(0),
|
|
@@ -18274,6 +19386,7 @@ function registerSessionRoutes(app, deps) {
|
|
|
18274
19386
|
return void 0;
|
|
18275
19387
|
}
|
|
18276
19388
|
if (workspaceRegistry.list().length === 1) {
|
|
19389
|
+
setDaemonTelemetryWorkspace(res, workspaceRegistry.primary.workspaceCwd);
|
|
18277
19390
|
return {
|
|
18278
19391
|
runtime: workspaceRegistry.primary,
|
|
18279
19392
|
workspaceCwd: "cwd" in body ? key : workspaceRegistry.primary.workspaceCwd
|
|
@@ -18289,6 +19402,7 @@ function registerSessionRoutes(app, deps) {
|
|
|
18289
19402
|
sendWorkspaceMismatch2(res, key);
|
|
18290
19403
|
return void 0;
|
|
18291
19404
|
}
|
|
19405
|
+
setDaemonTelemetryWorkspace(res, runtime.workspaceCwd);
|
|
18292
19406
|
if (!runtime.primary && !runtime.trusted) {
|
|
18293
19407
|
logSessionRoutingFailure("POST /session", "untrusted_workspace", {
|
|
18294
19408
|
workspaceId: runtime.workspaceId,
|
|
@@ -18397,11 +19511,16 @@ function registerSessionRoutes(app, deps) {
|
|
|
18397
19511
|
const result = await archiveCoordinator.runSharedMany(
|
|
18398
19512
|
[sessionId],
|
|
18399
19513
|
async () => {
|
|
18400
|
-
|
|
19514
|
+
if (target.archiveState === "archived") {
|
|
19515
|
+
await assertSessionArchived(target.workspaceCwd, sessionId);
|
|
19516
|
+
} else {
|
|
19517
|
+
await assertSessionLoadable(target.workspaceCwd, sessionId);
|
|
19518
|
+
}
|
|
18401
19519
|
return exportSessionTranscript({
|
|
18402
19520
|
workspaceCwd: target.workspaceCwd,
|
|
18403
19521
|
sessionId,
|
|
18404
19522
|
format,
|
|
19523
|
+
archiveState: target.archiveState,
|
|
18405
19524
|
config: { getChannel: /* @__PURE__ */ __name(() => "daemon", "getChannel") }
|
|
18406
19525
|
});
|
|
18407
19526
|
}
|
|
@@ -18536,6 +19655,7 @@ function registerSessionRoutes(app, deps) {
|
|
|
18536
19655
|
sendWorkspaceMismatch2(res, key);
|
|
18537
19656
|
return void 0;
|
|
18538
19657
|
}
|
|
19658
|
+
setDaemonTelemetryWorkspace(res, runtime.workspaceCwd);
|
|
18539
19659
|
if (!runtime.primary && !runtime.trusted) {
|
|
18540
19660
|
logSessionRoutingFailure(route, "untrusted_workspace", {
|
|
18541
19661
|
workspaceId: runtime.workspaceId,
|
|
@@ -18573,7 +19693,7 @@ function registerSessionRoutes(app, deps) {
|
|
|
18573
19693
|
}), "resolveLiveSessionRuntime");
|
|
18574
19694
|
const sendNonPrimarySessionRouteUnsupported = /* @__PURE__ */ __name((res, route, sessionId, runtime) => {
|
|
18575
19695
|
res.status(400).json({
|
|
18576
|
-
error: `Route "${route}" is
|
|
19696
|
+
error: `Route "${route}" is only available for primary workspace sessions.`,
|
|
18577
19697
|
code: "non_primary_session_route_not_supported",
|
|
18578
19698
|
sessionId,
|
|
18579
19699
|
workspaceId: runtime.workspaceId,
|
|
@@ -18621,6 +19741,7 @@ function registerSessionRoutes(app, deps) {
|
|
|
18621
19741
|
}, "throwMissingActiveTranscript");
|
|
18622
19742
|
if (workspaceRegistry.list().length === 1) {
|
|
18623
19743
|
const runtime = workspaceRegistry.primary;
|
|
19744
|
+
setDaemonTelemetryWorkspace(res, runtime.workspaceCwd);
|
|
18624
19745
|
if (await activeInRuntime(runtime)) {
|
|
18625
19746
|
return runtime;
|
|
18626
19747
|
}
|
|
@@ -18632,6 +19753,7 @@ function registerSessionRoutes(app, deps) {
|
|
|
18632
19753
|
return void 0;
|
|
18633
19754
|
}
|
|
18634
19755
|
if (liveOwner.kind === "found") {
|
|
19756
|
+
setDaemonTelemetryWorkspace(res, liveOwner.runtime.workspaceCwd);
|
|
18635
19757
|
if (!assertTrustedSessionOwner(res, route, sessionId, liveOwner.runtime)) {
|
|
18636
19758
|
return void 0;
|
|
18637
19759
|
}
|
|
@@ -18666,6 +19788,7 @@ function registerSessionRoutes(app, deps) {
|
|
|
18666
19788
|
}
|
|
18667
19789
|
if (activeRuntimes.length === 1) {
|
|
18668
19790
|
const runtime = activeRuntimes[0];
|
|
19791
|
+
setDaemonTelemetryWorkspace(res, runtime.workspaceCwd);
|
|
18669
19792
|
if (!assertTrustedSessionOwner(res, route, sessionId, runtime)) {
|
|
18670
19793
|
return void 0;
|
|
18671
19794
|
}
|
|
@@ -18722,23 +19845,37 @@ function registerSessionRoutes(app, deps) {
|
|
|
18722
19845
|
}
|
|
18723
19846
|
return key;
|
|
18724
19847
|
}, "resolveWorkspaceParam");
|
|
18725
|
-
const
|
|
18726
|
-
|
|
18727
|
-
|
|
18728
|
-
const runtime = resolveLiveSessionRuntime(sessionId, res, route);
|
|
18729
|
-
if (!runtime) return;
|
|
18730
|
-
if (!runtime.primary) {
|
|
18731
|
-
sendNonPrimarySessionRouteUnsupported(res, route, sessionId, runtime);
|
|
18732
|
-
return;
|
|
18733
|
-
}
|
|
18734
|
-
try {
|
|
18735
|
-
await archiveCoordinator.runSharedMany([sessionId], async () => {
|
|
18736
|
-
await handler(req, res, sessionId);
|
|
18737
|
-
});
|
|
18738
|
-
} catch (err) {
|
|
18739
|
-
sendBridgeError2(res, err, { route, sessionId });
|
|
19848
|
+
const withPrimaryOnlyMutableSession = /* @__PURE__ */ __name((route, handler) => {
|
|
19849
|
+
if (!isPrimaryOnlyLiveSessionRoute(route)) {
|
|
19850
|
+
throw new Error(`Unregistered primary-only session route: ${route}`);
|
|
18740
19851
|
}
|
|
18741
|
-
|
|
19852
|
+
return async (req, res) => {
|
|
19853
|
+
const sessionId = requireSessionId(req, res);
|
|
19854
|
+
if (sessionId === null) return;
|
|
19855
|
+
const runtime = resolveLiveSessionRuntime(sessionId, res, route);
|
|
19856
|
+
if (!runtime) return;
|
|
19857
|
+
if (!runtime.primary) {
|
|
19858
|
+
logSessionRoutingFailure(
|
|
19859
|
+
route,
|
|
19860
|
+
"non_primary_session_route_not_supported",
|
|
19861
|
+
{
|
|
19862
|
+
sessionId,
|
|
19863
|
+
workspaceId: runtime.workspaceId,
|
|
19864
|
+
workspaceCwd: runtime.workspaceCwd
|
|
19865
|
+
}
|
|
19866
|
+
);
|
|
19867
|
+
sendNonPrimarySessionRouteUnsupported(res, route, sessionId, runtime);
|
|
19868
|
+
return;
|
|
19869
|
+
}
|
|
19870
|
+
try {
|
|
19871
|
+
await archiveCoordinator.runSharedMany([sessionId], async () => {
|
|
19872
|
+
await handler(req, res, sessionId);
|
|
19873
|
+
});
|
|
19874
|
+
} catch (err) {
|
|
19875
|
+
sendBridgeError2(res, err, { route, sessionId });
|
|
19876
|
+
}
|
|
19877
|
+
};
|
|
19878
|
+
}, "withPrimaryOnlyMutableSession");
|
|
18742
19879
|
app.post("/session", mutate(), async (req, res) => {
|
|
18743
19880
|
const body = safeBody(req);
|
|
18744
19881
|
const resolvedRuntime = resolveRuntimeForSessionCreation(body, res);
|
|
@@ -18759,6 +19896,14 @@ function registerSessionRoutes(app, deps) {
|
|
|
18759
19896
|
}
|
|
18760
19897
|
const approvalMode = parseOptionalApprovalMode(body, res);
|
|
18761
19898
|
if (approvalMode === null) return;
|
|
19899
|
+
const source = parseSessionSource(body["sourceType"], body["sourceId"]);
|
|
19900
|
+
if ("error" in source) {
|
|
19901
|
+
res.status(400).json({
|
|
19902
|
+
error: source.error,
|
|
19903
|
+
code: "invalid_session_source"
|
|
19904
|
+
});
|
|
19905
|
+
return;
|
|
19906
|
+
}
|
|
18762
19907
|
const clientId = parseClientIdHeader(req, res);
|
|
18763
19908
|
if (clientId === null) return;
|
|
18764
19909
|
try {
|
|
@@ -18767,7 +19912,9 @@ function registerSessionRoutes(app, deps) {
|
|
|
18767
19912
|
modelServiceId,
|
|
18768
19913
|
...clientId !== void 0 ? { clientId } : {},
|
|
18769
19914
|
...sessionScope !== void 0 ? { sessionScope } : {},
|
|
18770
|
-
...approvalMode !== void 0 ? { approvalMode } : {}
|
|
19915
|
+
...approvalMode !== void 0 ? { approvalMode } : {},
|
|
19916
|
+
...source.sourceType !== void 0 ? { sourceType: source.sourceType } : {},
|
|
19917
|
+
...source.sourceId !== void 0 ? { sourceId: source.sourceId } : {}
|
|
18771
19918
|
});
|
|
18772
19919
|
if (daemonLog) {
|
|
18773
19920
|
daemonLog.info(
|
|
@@ -18786,8 +19933,17 @@ function registerSessionRoutes(app, deps) {
|
|
|
18786
19933
|
);
|
|
18787
19934
|
}
|
|
18788
19935
|
if (!session.attached) {
|
|
18789
|
-
|
|
18790
|
-
|
|
19936
|
+
try {
|
|
19937
|
+
const killed = await runtime.bridge.killSession(session.sessionId, {
|
|
19938
|
+
requireZeroAttaches: true
|
|
19939
|
+
});
|
|
19940
|
+
if (killed) {
|
|
19941
|
+
await new SessionService(runtime.workspaceCwd).removeSession(
|
|
19942
|
+
session.sessionId
|
|
19943
|
+
);
|
|
19944
|
+
}
|
|
19945
|
+
} catch {
|
|
19946
|
+
}
|
|
18791
19947
|
} else {
|
|
18792
19948
|
runtime.bridge.detachClient(session.sessionId, session.clientId).catch(() => {
|
|
18793
19949
|
});
|
|
@@ -18830,6 +19986,11 @@ function registerSessionRoutes(app, deps) {
|
|
|
18830
19986
|
releaseRestoreOwner();
|
|
18831
19987
|
return;
|
|
18832
19988
|
}
|
|
19989
|
+
const historyPageSize = action === "load" ? parseHistoryPageSize(body ?? {}, res) : void 0;
|
|
19990
|
+
if (historyPageSize === null) {
|
|
19991
|
+
releaseRestoreOwner();
|
|
19992
|
+
return;
|
|
19993
|
+
}
|
|
18833
19994
|
const clientId = parseClientIdHeader(req, res);
|
|
18834
19995
|
if (clientId === null) {
|
|
18835
19996
|
releaseRestoreOwner();
|
|
@@ -18840,22 +20001,23 @@ function registerSessionRoutes(app, deps) {
|
|
|
18840
20001
|
[sessionId],
|
|
18841
20002
|
async () => {
|
|
18842
20003
|
await assertSessionLoadable(workspaceCwd, sessionId);
|
|
18843
|
-
const
|
|
20004
|
+
const metadata = await new SessionService(
|
|
18844
20005
|
workspaceCwd
|
|
18845
|
-
).
|
|
20006
|
+
).readCreationMetadata(sessionId);
|
|
18846
20007
|
return action === "load" ? await runtime.bridge.loadSession({
|
|
18847
20008
|
sessionId,
|
|
18848
20009
|
workspaceCwd,
|
|
18849
20010
|
historyReplay: "response",
|
|
20011
|
+
...historyPageSize !== void 0 ? { historyPageSize } : {},
|
|
18850
20012
|
...clientId !== void 0 ? { clientId } : {},
|
|
18851
20013
|
...approvalMode !== void 0 ? { approvalMode } : {},
|
|
18852
|
-
...
|
|
20014
|
+
...metadata
|
|
18853
20015
|
}) : await runtime.bridge.resumeSession({
|
|
18854
20016
|
sessionId,
|
|
18855
20017
|
workspaceCwd,
|
|
18856
20018
|
...clientId !== void 0 ? { clientId } : {},
|
|
18857
20019
|
...approvalMode !== void 0 ? { approvalMode } : {},
|
|
18858
|
-
...
|
|
20020
|
+
...metadata
|
|
18859
20021
|
});
|
|
18860
20022
|
}
|
|
18861
20023
|
);
|
|
@@ -18890,7 +20052,7 @@ function registerSessionRoutes(app, deps) {
|
|
|
18890
20052
|
app.post(
|
|
18891
20053
|
"/session/:id/branch",
|
|
18892
20054
|
mutate(),
|
|
18893
|
-
|
|
20055
|
+
withPrimaryOnlyMutableSession(
|
|
18894
20056
|
"POST /session/:id/branch",
|
|
18895
20057
|
async (req, res, sessionId) => {
|
|
18896
20058
|
const body = safeBody(req);
|
|
@@ -18925,7 +20087,7 @@ function registerSessionRoutes(app, deps) {
|
|
|
18925
20087
|
app.post(
|
|
18926
20088
|
"/session/:id/fork",
|
|
18927
20089
|
mutate(),
|
|
18928
|
-
|
|
20090
|
+
withPrimaryOnlyMutableSession(
|
|
18929
20091
|
"POST /session/:id/fork",
|
|
18930
20092
|
async (req, res, sessionId) => {
|
|
18931
20093
|
const body = safeBody(req);
|
|
@@ -18951,25 +20113,28 @@ function registerSessionRoutes(app, deps) {
|
|
|
18951
20113
|
app.post(
|
|
18952
20114
|
"/session/:id/cd",
|
|
18953
20115
|
mutate(),
|
|
18954
|
-
|
|
18955
|
-
|
|
18956
|
-
|
|
18957
|
-
|
|
18958
|
-
|
|
18959
|
-
|
|
18960
|
-
|
|
18961
|
-
|
|
18962
|
-
|
|
20116
|
+
withPrimaryOnlyMutableSession(
|
|
20117
|
+
"POST /session/:id/cd",
|
|
20118
|
+
async (req, res, sessionId) => {
|
|
20119
|
+
const body = safeBody(req);
|
|
20120
|
+
const targetPath = body["path"];
|
|
20121
|
+
if (typeof targetPath !== "string" || targetPath.length === 0 || !path11.isAbsolute(targetPath)) {
|
|
20122
|
+
res.status(400).json({
|
|
20123
|
+
error: "`path` is required and must be an absolute path",
|
|
20124
|
+
code: "invalid_path"
|
|
20125
|
+
});
|
|
20126
|
+
return;
|
|
20127
|
+
}
|
|
20128
|
+
const clientId = parseClientIdHeader(req, res);
|
|
20129
|
+
if (clientId === null) return;
|
|
20130
|
+
const result = await bridge.changeSessionCwd(
|
|
20131
|
+
sessionId,
|
|
20132
|
+
{ path: targetPath },
|
|
20133
|
+
clientId !== void 0 ? { clientId } : void 0
|
|
20134
|
+
);
|
|
20135
|
+
res.status(200).json(result);
|
|
18963
20136
|
}
|
|
18964
|
-
|
|
18965
|
-
if (clientId === null) return;
|
|
18966
|
-
const result = await bridge.changeSessionCwd(
|
|
18967
|
-
sessionId,
|
|
18968
|
-
{ path: targetPath },
|
|
18969
|
-
clientId !== void 0 ? { clientId } : void 0
|
|
18970
|
-
);
|
|
18971
|
-
res.status(200).json(result);
|
|
18972
|
-
})
|
|
20137
|
+
)
|
|
18973
20138
|
);
|
|
18974
20139
|
app.get("/session/:id/status", (req, res) => {
|
|
18975
20140
|
const sessionId = requireSessionId(req, res);
|
|
@@ -19005,6 +20170,20 @@ function registerSessionRoutes(app, deps) {
|
|
|
19005
20170
|
workspaceQualified: true
|
|
19006
20171
|
});
|
|
19007
20172
|
});
|
|
20173
|
+
app.get(
|
|
20174
|
+
"/workspaces/:workspace/session/:id/archive/export",
|
|
20175
|
+
async (req, res) => {
|
|
20176
|
+
const route = "GET /workspaces/:workspace/session/:id/archive/export";
|
|
20177
|
+
const runtime = requireTrustedRuntimeForWorkspaceRoute(req, res, route);
|
|
20178
|
+
if (!runtime) return;
|
|
20179
|
+
await handleSessionExport(req, res, {
|
|
20180
|
+
route,
|
|
20181
|
+
workspaceCwd: runtime.workspaceCwd,
|
|
20182
|
+
workspaceQualified: true,
|
|
20183
|
+
archiveState: "archived"
|
|
20184
|
+
});
|
|
20185
|
+
}
|
|
20186
|
+
);
|
|
19008
20187
|
app.get("/session/:id/transcript", async (req, res) => {
|
|
19009
20188
|
const route = "GET /session/:id/transcript";
|
|
19010
20189
|
const sessionId = requireSessionId(req, res);
|
|
@@ -19013,6 +20192,18 @@ function registerSessionRoutes(app, deps) {
|
|
|
19013
20192
|
if (limit === null) return;
|
|
19014
20193
|
const cursor = parseTranscriptCursorQuery(req.query["cursor"], res);
|
|
19015
20194
|
if (cursor === null) return;
|
|
20195
|
+
const beforeRecordId = parseTranscriptRecordBoundaryQuery(
|
|
20196
|
+
req.query["beforeRecordId"],
|
|
20197
|
+
res
|
|
20198
|
+
);
|
|
20199
|
+
if (beforeRecordId === null) return;
|
|
20200
|
+
if (cursor !== void 0 && beforeRecordId !== void 0) {
|
|
20201
|
+
res.status(400).json({
|
|
20202
|
+
error: "`cursor` and `beforeRecordId` are mutually exclusive",
|
|
20203
|
+
code: "invalid_transcript_cursor"
|
|
20204
|
+
});
|
|
20205
|
+
return;
|
|
20206
|
+
}
|
|
19016
20207
|
try {
|
|
19017
20208
|
const result = await archiveCoordinator.runSharedMany(
|
|
19018
20209
|
[sessionId],
|
|
@@ -19027,7 +20218,8 @@ function registerSessionRoutes(app, deps) {
|
|
|
19027
20218
|
return runtime.bridge.getSessionTranscriptPage({
|
|
19028
20219
|
sessionId,
|
|
19029
20220
|
...limit !== void 0 ? { limit } : {},
|
|
19030
|
-
...cursor !== void 0 ? { cursor } : {}
|
|
20221
|
+
...cursor !== void 0 ? { cursor } : {},
|
|
20222
|
+
...beforeRecordId !== void 0 ? { beforeRecordId } : {}
|
|
19031
20223
|
});
|
|
19032
20224
|
}
|
|
19033
20225
|
);
|
|
@@ -19062,6 +20254,18 @@ function registerSessionRoutes(app, deps) {
|
|
|
19062
20254
|
if (limit === null) return;
|
|
19063
20255
|
const cursor = parseTranscriptCursorQuery(req.query["cursor"], res);
|
|
19064
20256
|
if (cursor === null) return;
|
|
20257
|
+
const beforeRecordId = parseTranscriptRecordBoundaryQuery(
|
|
20258
|
+
req.query["beforeRecordId"],
|
|
20259
|
+
res
|
|
20260
|
+
);
|
|
20261
|
+
if (beforeRecordId === null) return;
|
|
20262
|
+
if (cursor !== void 0 && beforeRecordId !== void 0) {
|
|
20263
|
+
res.status(400).json({
|
|
20264
|
+
error: "`cursor` and `beforeRecordId` are mutually exclusive",
|
|
20265
|
+
code: "invalid_transcript_cursor"
|
|
20266
|
+
});
|
|
20267
|
+
return;
|
|
20268
|
+
}
|
|
19065
20269
|
if (cursor !== void 0 && workspaceTranscriptCursorExceedsLimit(cursor)) {
|
|
19066
20270
|
res.status(400).json({
|
|
19067
20271
|
error: "`cursor` exceeds the maximum size",
|
|
@@ -19086,7 +20290,8 @@ function registerSessionRoutes(app, deps) {
|
|
|
19086
20290
|
page = await reader.readPage(sessionId, {
|
|
19087
20291
|
...limit !== void 0 ? { limit } : {},
|
|
19088
20292
|
...cursor !== void 0 ? { cursor } : {},
|
|
19089
|
-
|
|
20293
|
+
...beforeRecordId !== void 0 ? { beforeRecordId } : {},
|
|
20294
|
+
maxBytes: SESSION_TRANSCRIPT_MAX_PAGE_BYTES
|
|
19090
20295
|
});
|
|
19091
20296
|
} catch (error2) {
|
|
19092
20297
|
if (error2.code !== "ENOENT") {
|
|
@@ -19348,7 +20553,7 @@ function registerSessionRoutes(app, deps) {
|
|
|
19348
20553
|
async (req, res, sessionId, runtime) => {
|
|
19349
20554
|
const clientId = parseClientIdHeader(req, res);
|
|
19350
20555
|
if (clientId === null) return;
|
|
19351
|
-
const promptId =
|
|
20556
|
+
const promptId = crypto3.randomUUID();
|
|
19352
20557
|
res.status(200).json(
|
|
19353
20558
|
await runtime.bridge.continueSession(sessionId, {
|
|
19354
20559
|
...clientId !== void 0 ? { clientId } : {},
|
|
@@ -19395,7 +20600,7 @@ function registerSessionRoutes(app, deps) {
|
|
|
19395
20600
|
}
|
|
19396
20601
|
const clientId = parseClientIdHeader(req, res);
|
|
19397
20602
|
if (clientId === null) return;
|
|
19398
|
-
const promptId =
|
|
20603
|
+
const promptId = crypto3.randomUUID();
|
|
19399
20604
|
const forwardedBody = { ...body };
|
|
19400
20605
|
delete forwardedBody["deadlineMs"];
|
|
19401
20606
|
const lastEventId = ownerBridge.getSessionLastEventId(sessionId);
|
|
@@ -19496,6 +20701,88 @@ function registerSessionRoutes(app, deps) {
|
|
|
19496
20701
|
}
|
|
19497
20702
|
)
|
|
19498
20703
|
);
|
|
20704
|
+
app.post(
|
|
20705
|
+
"/session/:id/generate",
|
|
20706
|
+
mutate(),
|
|
20707
|
+
withOwnerReadSession(
|
|
20708
|
+
"POST /session/:id/generate",
|
|
20709
|
+
async (req, res, sessionId, runtime) => {
|
|
20710
|
+
const body = safeBody(req);
|
|
20711
|
+
const prompt = body["prompt"];
|
|
20712
|
+
if (typeof prompt !== "string" || prompt.trim().length === 0 || Buffer.byteLength(prompt, "utf8") > GENERATION_MAX_PROMPT_BYTES) {
|
|
20713
|
+
res.status(400).json({
|
|
20714
|
+
error: `\`prompt\` must be a non-empty string no larger than ${GENERATION_MAX_PROMPT_BYTES} UTF-8 bytes`,
|
|
20715
|
+
code: "invalid_prompt"
|
|
20716
|
+
});
|
|
20717
|
+
return;
|
|
20718
|
+
}
|
|
20719
|
+
const clientId = parseClientIdHeader(req, res);
|
|
20720
|
+
if (clientId === null) return;
|
|
20721
|
+
if (!runtime.bridge.generateSessionContent) {
|
|
20722
|
+
res.status(501).json({
|
|
20723
|
+
error: "Stateless generation is not supported by this bridge",
|
|
20724
|
+
code: "generation_not_supported"
|
|
20725
|
+
});
|
|
20726
|
+
return;
|
|
20727
|
+
}
|
|
20728
|
+
const abort = new AbortController();
|
|
20729
|
+
let completed = false;
|
|
20730
|
+
const onClose = /* @__PURE__ */ __name(() => {
|
|
20731
|
+
if (!completed) abort.abort();
|
|
20732
|
+
}, "onClose");
|
|
20733
|
+
res.once("close", onClose);
|
|
20734
|
+
const stream = runtime.bridge.generateSessionContent(
|
|
20735
|
+
sessionId,
|
|
20736
|
+
prompt,
|
|
20737
|
+
abort.signal,
|
|
20738
|
+
clientId !== void 0 ? { clientId } : void 0
|
|
20739
|
+
);
|
|
20740
|
+
res.status(200);
|
|
20741
|
+
res.setHeader("Content-Type", "text/event-stream");
|
|
20742
|
+
res.setHeader("Cache-Control", "no-cache, no-transform");
|
|
20743
|
+
res.setHeader("Connection", "keep-alive");
|
|
20744
|
+
res.setHeader("X-Accel-Buffering", "no");
|
|
20745
|
+
res.flushHeaders();
|
|
20746
|
+
let writeChain = Promise.resolve();
|
|
20747
|
+
const write = /* @__PURE__ */ __name((chunk) => {
|
|
20748
|
+
writeChain = writeChain.then(
|
|
20749
|
+
() => writeGenerationSseChunk(res, chunk)
|
|
20750
|
+
);
|
|
20751
|
+
return writeChain;
|
|
20752
|
+
}, "write");
|
|
20753
|
+
await write(": connected\n\n");
|
|
20754
|
+
const heartbeat = setInterval(() => {
|
|
20755
|
+
void write(": heartbeat\n\n").catch(() => abort.abort());
|
|
20756
|
+
}, GENERATION_HEARTBEAT_MS);
|
|
20757
|
+
heartbeat.unref();
|
|
20758
|
+
try {
|
|
20759
|
+
for await (const event of stream) {
|
|
20760
|
+
await write(formatGenerationSse(event.type, event));
|
|
20761
|
+
}
|
|
20762
|
+
} catch (err) {
|
|
20763
|
+
if (!abort.signal.aborted && !res.destroyed) {
|
|
20764
|
+
daemonLog?.error(
|
|
20765
|
+
"session generation failed",
|
|
20766
|
+
err instanceof Error ? err : new Error(String(err)),
|
|
20767
|
+
{ sessionId, clientId }
|
|
20768
|
+
);
|
|
20769
|
+
await write(
|
|
20770
|
+
formatGenerationSse("error", {
|
|
20771
|
+
type: "error",
|
|
20772
|
+
code: "generation_failed",
|
|
20773
|
+
message: "Generation failed"
|
|
20774
|
+
})
|
|
20775
|
+
).catch(() => void 0);
|
|
20776
|
+
}
|
|
20777
|
+
} finally {
|
|
20778
|
+
completed = true;
|
|
20779
|
+
clearInterval(heartbeat);
|
|
20780
|
+
res.off("close", onClose);
|
|
20781
|
+
if (!res.destroyed) res.end();
|
|
20782
|
+
}
|
|
20783
|
+
}
|
|
20784
|
+
)
|
|
20785
|
+
);
|
|
19499
20786
|
app.post(
|
|
19500
20787
|
"/session/:id/heartbeat",
|
|
19501
20788
|
mutate(),
|
|
@@ -20064,16 +21351,28 @@ function registerSessionRoutes(app, deps) {
|
|
|
20064
21351
|
}
|
|
20065
21352
|
parentSessionId = rawParentSessionId;
|
|
20066
21353
|
}
|
|
21354
|
+
const parsedSource = parseSessionSource(
|
|
21355
|
+
req.query["sourceType"],
|
|
21356
|
+
req.query["sourceId"]
|
|
21357
|
+
);
|
|
21358
|
+
if ("error" in parsedSource) {
|
|
21359
|
+
res.status(400).json({
|
|
21360
|
+
error: parsedSource.error,
|
|
21361
|
+
code: "invalid_session_source"
|
|
21362
|
+
});
|
|
21363
|
+
return;
|
|
21364
|
+
}
|
|
20067
21365
|
const options = {
|
|
20068
21366
|
...cursor !== void 0 ? { cursor } : {},
|
|
20069
21367
|
...size !== void 0 ? { size } : {},
|
|
20070
21368
|
...archiveState !== void 0 ? { archiveState } : {},
|
|
20071
21369
|
...view !== void 0 ? { view } : {},
|
|
20072
21370
|
...group !== void 0 ? { group } : {},
|
|
20073
|
-
...parentSessionId !== void 0 ? { parentSessionId } : {}
|
|
21371
|
+
...parentSessionId !== void 0 ? { parentSessionId } : {},
|
|
21372
|
+
...parsedSource
|
|
20074
21373
|
};
|
|
20075
|
-
const usePersisted = readOnlySecondary || runtime.primary || view === "organized" || archiveState === "archived" || parentSessionId !== void 0 || (cursor !== void 0 && cursor !== "" ? isNumericSessionCursor(cursor) : await hasActivePersistedSessions(key));
|
|
20076
|
-
if (!usePersisted && (view !== void 0 || archiveState === "archived")) {
|
|
21374
|
+
const usePersisted = readOnlySecondary || runtime.primary || view === "organized" || archiveState === "archived" || parentSessionId !== void 0 || parsedSource.sourceType !== void 0 || (cursor !== void 0 && cursor !== "" ? isNumericSessionCursor(cursor) : await hasActivePersistedSessions(key));
|
|
21375
|
+
if (!usePersisted && (view !== void 0 || archiveState === "archived" || parentSessionId !== void 0 || parsedSource.sourceType !== void 0)) {
|
|
20077
21376
|
throw new Error(
|
|
20078
21377
|
"session list live path received persisted-only options"
|
|
20079
21378
|
);
|
|
@@ -20123,6 +21422,36 @@ function registerSessionRoutes(app, deps) {
|
|
|
20123
21422
|
"/workspaces/:workspace/sessions",
|
|
20124
21423
|
listWorkspaceSessionsHandler("workspace")
|
|
20125
21424
|
);
|
|
21425
|
+
const workspaceSessionInfoHandler = /* @__PURE__ */ __name((paramName) => async (req, res) => {
|
|
21426
|
+
const route = paramName === "workspace" ? "GET /workspaces/:workspace/session-info" : "GET /workspace/:id/session-info";
|
|
21427
|
+
const runtime = resolveRuntimeForCatalogRoute(req, res, paramName, route);
|
|
21428
|
+
if (runtime === null) return;
|
|
21429
|
+
const key = runtime.workspaceCwd;
|
|
21430
|
+
try {
|
|
21431
|
+
const info = await runWorkspaceInspectionWithLogPolicy(
|
|
21432
|
+
runtime,
|
|
21433
|
+
() => getWorkspaceSessionInfoForResponse(runtime.bridge, key, {
|
|
21434
|
+
includeLive: !isReadOnlyWorkspaceInspection(runtime)
|
|
21435
|
+
})
|
|
21436
|
+
);
|
|
21437
|
+
res.status(200).json(info);
|
|
21438
|
+
} catch (err) {
|
|
21439
|
+
writeStderrLine(
|
|
21440
|
+
`qwen serve: failed to read session-info for workspace ${safeLogValue(
|
|
21441
|
+
key
|
|
21442
|
+
)}: ${safeLogValue(err instanceof Error ? err.message : String(err))}`
|
|
21443
|
+
);
|
|
21444
|
+
res.status(500).json({
|
|
21445
|
+
error: "Failed to read session info",
|
|
21446
|
+
code: "session_info_failed"
|
|
21447
|
+
});
|
|
21448
|
+
}
|
|
21449
|
+
}, "workspaceSessionInfoHandler");
|
|
21450
|
+
app.get("/workspace/:id/session-info", workspaceSessionInfoHandler("id"));
|
|
21451
|
+
app.get(
|
|
21452
|
+
"/workspaces/:workspace/session-info",
|
|
21453
|
+
workspaceSessionInfoHandler("workspace")
|
|
21454
|
+
);
|
|
20126
21455
|
app.post(
|
|
20127
21456
|
"/session/:id/model",
|
|
20128
21457
|
mutate(),
|
|
@@ -20672,6 +22001,7 @@ function registerScheduledTaskCrudRoutes(app, deps) {
|
|
|
20672
22001
|
}
|
|
20673
22002
|
const recurring = body["recurring"] !== false;
|
|
20674
22003
|
const enabled = body["enabled"] !== false;
|
|
22004
|
+
const taskId = generateCronTaskId();
|
|
20675
22005
|
let boundSessionId;
|
|
20676
22006
|
if (bridge) {
|
|
20677
22007
|
try {
|
|
@@ -20687,7 +22017,9 @@ function registerScheduledTaskCrudRoutes(app, deps) {
|
|
|
20687
22017
|
try {
|
|
20688
22018
|
const session = await bridge.spawnOrAttach({
|
|
20689
22019
|
workspaceCwd,
|
|
20690
|
-
sessionScope: "thread"
|
|
22020
|
+
sessionScope: "thread",
|
|
22021
|
+
sourceType: "scheduled_task",
|
|
22022
|
+
sourceId: taskId
|
|
20691
22023
|
});
|
|
20692
22024
|
boundSessionId = session.sessionId;
|
|
20693
22025
|
try {
|
|
@@ -20709,7 +22041,7 @@ function registerScheduledTaskCrudRoutes(app, deps) {
|
|
|
20709
22041
|
}
|
|
20710
22042
|
const now = Date.now();
|
|
20711
22043
|
const task = {
|
|
20712
|
-
id:
|
|
22044
|
+
id: taskId,
|
|
20713
22045
|
cron,
|
|
20714
22046
|
prompt,
|
|
20715
22047
|
recurring,
|
|
@@ -21192,7 +22524,9 @@ async function bindAndNameSessions(bridge, boundWorkspace, tasks, renamed, spawn
|
|
|
21192
22524
|
binding.add(task.id);
|
|
21193
22525
|
const rawSpawn = bridge.spawnOrAttach({
|
|
21194
22526
|
workspaceCwd: boundWorkspace,
|
|
21195
|
-
sessionScope: "thread"
|
|
22527
|
+
sessionScope: "thread",
|
|
22528
|
+
sourceType: "scheduled_task",
|
|
22529
|
+
sourceId: task.id
|
|
21196
22530
|
});
|
|
21197
22531
|
let timedOut = false;
|
|
21198
22532
|
rawSpawn.then(({ sessionId: sessionId2 }) => {
|
|
@@ -21301,12 +22635,16 @@ function startScheduledTaskKeepalive(opts) {
|
|
|
21301
22635
|
continue;
|
|
21302
22636
|
}
|
|
21303
22637
|
log.debug("keepalive: recordHeartbeat failed for", sessionId, err);
|
|
22638
|
+
reviving.add(sessionId);
|
|
22639
|
+
const metadata = await new SessionService(
|
|
22640
|
+
boundWorkspace
|
|
22641
|
+
).readCreationMetadata(sessionId);
|
|
21304
22642
|
const load = bridge.loadSession({
|
|
21305
22643
|
sessionId,
|
|
21306
22644
|
workspaceCwd: boundWorkspace,
|
|
21307
|
-
historyReplay: "response"
|
|
22645
|
+
historyReplay: "response",
|
|
22646
|
+
...metadata
|
|
21308
22647
|
});
|
|
21309
|
-
reviving.add(sessionId);
|
|
21310
22648
|
void load.catch(() => {
|
|
21311
22649
|
}).finally(() => {
|
|
21312
22650
|
reviving.delete(sessionId);
|
|
@@ -21417,10 +22755,14 @@ async function rehydrateScheduledTaskSessions(deps) {
|
|
|
21417
22755
|
const loaded = [];
|
|
21418
22756
|
const failed = [];
|
|
21419
22757
|
const loadOne = /* @__PURE__ */ __name(async (sessionId) => {
|
|
22758
|
+
const metadata = await new SessionService(
|
|
22759
|
+
boundWorkspace
|
|
22760
|
+
).readCreationMetadata(sessionId);
|
|
21420
22761
|
const load = bridge.loadSession({
|
|
21421
22762
|
sessionId,
|
|
21422
22763
|
workspaceCwd: boundWorkspace,
|
|
21423
|
-
historyReplay: "response"
|
|
22764
|
+
historyReplay: "response",
|
|
22765
|
+
...metadata
|
|
21424
22766
|
});
|
|
21425
22767
|
void load.catch(() => {
|
|
21426
22768
|
});
|
|
@@ -21767,6 +23109,7 @@ function createServeFeatures(deps) {
|
|
|
21767
23109
|
boundWorkspace,
|
|
21768
23110
|
persistSettingAvailable,
|
|
21769
23111
|
sessionArtifactsPersistenceAvailable,
|
|
23112
|
+
sessionGenerationAvailable,
|
|
21770
23113
|
reloadAvailable,
|
|
21771
23114
|
channelReloadAvailable,
|
|
21772
23115
|
channelControlAvailable,
|
|
@@ -21800,6 +23143,7 @@ function createServeFeatures(deps) {
|
|
|
21800
23143
|
persistSettingAvailable,
|
|
21801
23144
|
sessionShellCommandEnabled,
|
|
21802
23145
|
sessionArtifactsPersistenceAvailable,
|
|
23146
|
+
sessionGenerationAvailable: sessionGenerationAvailable(),
|
|
21803
23147
|
rateLimit: opts.rateLimit === true,
|
|
21804
23148
|
reloadAvailable,
|
|
21805
23149
|
channelReloadAvailable: channelReloadAvailable(),
|
|
@@ -22089,6 +23433,7 @@ init_esbuild_shims();
|
|
|
22089
23433
|
var TUI_ONLY_SETTINGS = /* @__PURE__ */ new Set([
|
|
22090
23434
|
"general.vimMode",
|
|
22091
23435
|
"general.terminalBell",
|
|
23436
|
+
"general.notificationMode",
|
|
22092
23437
|
"general.preferredEditor",
|
|
22093
23438
|
"general.outputLanguage",
|
|
22094
23439
|
"ide.enabled",
|
|
@@ -22099,9 +23444,14 @@ var TUI_ONLY_SETTINGS = /* @__PURE__ */ new Set([
|
|
|
22099
23444
|
"ui.accessibility.enableLoadingPhrases",
|
|
22100
23445
|
"ui.enableWelcomeBack"
|
|
22101
23446
|
]);
|
|
22102
|
-
var WEB_SHELL_SETTINGS = /* @__PURE__ */ new Set([
|
|
23447
|
+
var WEB_SHELL_SETTINGS = /* @__PURE__ */ new Set([
|
|
23448
|
+
"ui.compactMode",
|
|
23449
|
+
"voiceModel",
|
|
23450
|
+
"mcpServers"
|
|
23451
|
+
]);
|
|
22103
23452
|
var VALID_WRITE_SCOPES = /* @__PURE__ */ new Set(["workspace", "user"]);
|
|
22104
23453
|
var QUALIFIED_WRITE_SCOPES = /* @__PURE__ */ new Set(["workspace"]);
|
|
23454
|
+
var mcpServerMutationQueues = /* @__PURE__ */ new Map();
|
|
22105
23455
|
var SECURITY_SENSITIVE_SETTINGS = /* @__PURE__ */ new Set(["tools.approvalMode"]);
|
|
22106
23456
|
function getAllowedKeys() {
|
|
22107
23457
|
const keys = new Set(
|
|
@@ -22133,11 +23483,12 @@ function buildSettingsResponse(boundWorkspace, keys) {
|
|
|
22133
23483
|
loaded.workspace.settings,
|
|
22134
23484
|
key
|
|
22135
23485
|
);
|
|
23486
|
+
const publicValue = /* @__PURE__ */ __name((value) => key === "mcpServers" ? redactMcpServersSetting(value) : value, "publicValue");
|
|
22136
23487
|
const values = {
|
|
22137
|
-
effective: effective !== void 0 ? effective : def.default
|
|
23488
|
+
effective: publicValue(effective !== void 0 ? effective : def.default)
|
|
22138
23489
|
};
|
|
22139
|
-
if (userVal !== void 0) values.user = userVal;
|
|
22140
|
-
if (wsVal !== void 0) values.workspace = wsVal;
|
|
23490
|
+
if (userVal !== void 0) values.user = publicValue(userVal);
|
|
23491
|
+
if (wsVal !== void 0) values.workspace = publicValue(wsVal);
|
|
22141
23492
|
settings.push({
|
|
22142
23493
|
key,
|
|
22143
23494
|
type: def.type,
|
|
@@ -22165,9 +23516,62 @@ function buildSettingsResponse(boundWorkspace, keys) {
|
|
|
22165
23516
|
}
|
|
22166
23517
|
__name(buildSettingsResponse, "buildSettingsResponse");
|
|
22167
23518
|
var SCOPE_MAP = {
|
|
22168
|
-
|
|
22169
|
-
|
|
23519
|
+
user: "User" /* User */,
|
|
23520
|
+
workspace: "Workspace" /* Workspace */
|
|
22170
23521
|
};
|
|
23522
|
+
function prepareSettingWrite(workspace, scope, key, value, mcpServerMutation) {
|
|
23523
|
+
if (key !== "mcpServers") {
|
|
23524
|
+
return { persistedValue: value, publicValue: value };
|
|
23525
|
+
}
|
|
23526
|
+
const existing = loadSettings(workspace).forScope(scope).settings.mcpServers ?? {};
|
|
23527
|
+
let nextValue = value;
|
|
23528
|
+
if (mcpServerMutation) {
|
|
23529
|
+
const servers = { ...existing };
|
|
23530
|
+
if (mcpServerMutation.operation === "set") {
|
|
23531
|
+
servers[mcpServerMutation.name] = value;
|
|
23532
|
+
} else {
|
|
23533
|
+
delete servers[mcpServerMutation.name];
|
|
23534
|
+
}
|
|
23535
|
+
nextValue = servers;
|
|
23536
|
+
}
|
|
23537
|
+
const persistedValue = restoreRedactedMcpServersSetting(nextValue, existing);
|
|
23538
|
+
return {
|
|
23539
|
+
persistedValue,
|
|
23540
|
+
publicValue: redactMcpServersSetting(persistedValue)
|
|
23541
|
+
};
|
|
23542
|
+
}
|
|
23543
|
+
__name(prepareSettingWrite, "prepareSettingWrite");
|
|
23544
|
+
function parseMcpServerMutation(key, value) {
|
|
23545
|
+
if (value === void 0) return void 0;
|
|
23546
|
+
if (key !== "mcpServers" || typeof value !== "object" || value === null) {
|
|
23547
|
+
throw new Error("mcpServerMutation is only valid for mcpServers");
|
|
23548
|
+
}
|
|
23549
|
+
const operation = value["operation"];
|
|
23550
|
+
const name = value["name"];
|
|
23551
|
+
if (operation !== "set" && operation !== "remove" || typeof name !== "string" || !name.trim()) {
|
|
23552
|
+
throw new Error("mcpServerMutation requires a valid operation and name");
|
|
23553
|
+
}
|
|
23554
|
+
return { operation, name };
|
|
23555
|
+
}
|
|
23556
|
+
__name(parseMcpServerMutation, "parseMcpServerMutation");
|
|
23557
|
+
async function withMcpServerMutationLock(workspace, scope, operation) {
|
|
23558
|
+
const key = `${workspace}\0${scope}`;
|
|
23559
|
+
const previous = mcpServerMutationQueues.get(key) ?? Promise.resolve();
|
|
23560
|
+
const run = previous.catch(() => void 0).then(operation);
|
|
23561
|
+
const tail = run.then(
|
|
23562
|
+
() => void 0,
|
|
23563
|
+
() => void 0
|
|
23564
|
+
);
|
|
23565
|
+
mcpServerMutationQueues.set(key, tail);
|
|
23566
|
+
try {
|
|
23567
|
+
return await run;
|
|
23568
|
+
} finally {
|
|
23569
|
+
if (mcpServerMutationQueues.get(key) === tail) {
|
|
23570
|
+
mcpServerMutationQueues.delete(key);
|
|
23571
|
+
}
|
|
23572
|
+
}
|
|
23573
|
+
}
|
|
23574
|
+
__name(withMcpServerMutationLock, "withMcpServerMutationLock");
|
|
22171
23575
|
function registerWorkspaceSettingsRoutes(app, deps) {
|
|
22172
23576
|
const {
|
|
22173
23577
|
boundWorkspace,
|
|
@@ -22200,6 +23604,19 @@ function registerWorkspaceSettingsRoutes(app, deps) {
|
|
|
22200
23604
|
const scope = body["scope"];
|
|
22201
23605
|
const key = body["key"];
|
|
22202
23606
|
const value = body["value"];
|
|
23607
|
+
let mcpServerMutation;
|
|
23608
|
+
try {
|
|
23609
|
+
mcpServerMutation = parseMcpServerMutation(
|
|
23610
|
+
typeof key === "string" ? key : "",
|
|
23611
|
+
body["mcpServerMutation"]
|
|
23612
|
+
);
|
|
23613
|
+
} catch (error2) {
|
|
23614
|
+
res.status(400).json({
|
|
23615
|
+
error: error2 instanceof Error ? error2.message : String(error2),
|
|
23616
|
+
code: "invalid_mcp_server_mutation"
|
|
23617
|
+
});
|
|
23618
|
+
return;
|
|
23619
|
+
}
|
|
22203
23620
|
if (typeof scope !== "string" || !VALID_WRITE_SCOPES.has(scope)) {
|
|
22204
23621
|
res.status(400).json({
|
|
22205
23622
|
error: `scope must be one of: ${[...VALID_WRITE_SCOPES].join(", ")}`,
|
|
@@ -22246,16 +23663,41 @@ function registerWorkspaceSettingsRoutes(app, deps) {
|
|
|
22246
23663
|
}
|
|
22247
23664
|
const clientId = parseAndValidateClientId(req, res);
|
|
22248
23665
|
if (clientId === null) return;
|
|
23666
|
+
const settingScope = SCOPE_MAP[scope];
|
|
23667
|
+
if (!settingScope) {
|
|
23668
|
+
res.status(400).json({
|
|
23669
|
+
error: `scope must be one of: ${[...VALID_WRITE_SCOPES].join(", ")}`,
|
|
23670
|
+
code: "invalid_scope"
|
|
23671
|
+
});
|
|
23672
|
+
return;
|
|
23673
|
+
}
|
|
23674
|
+
let publicValue = value;
|
|
22249
23675
|
try {
|
|
22250
|
-
const
|
|
22251
|
-
|
|
22252
|
-
|
|
22253
|
-
|
|
22254
|
-
|
|
22255
|
-
|
|
22256
|
-
|
|
23676
|
+
const persist = /* @__PURE__ */ __name(async () => {
|
|
23677
|
+
const prepared = prepareSettingWrite(
|
|
23678
|
+
boundWorkspace,
|
|
23679
|
+
settingScope,
|
|
23680
|
+
key,
|
|
23681
|
+
value,
|
|
23682
|
+
mcpServerMutation
|
|
23683
|
+
);
|
|
23684
|
+
publicValue = prepared.publicValue;
|
|
23685
|
+
await persistSetting(
|
|
23686
|
+
boundWorkspace,
|
|
23687
|
+
settingScope,
|
|
23688
|
+
key,
|
|
23689
|
+
prepared.persistedValue
|
|
23690
|
+
);
|
|
23691
|
+
}, "persist");
|
|
23692
|
+
if (mcpServerMutation) {
|
|
23693
|
+
await withMcpServerMutationLock(
|
|
23694
|
+
boundWorkspace,
|
|
23695
|
+
settingScope,
|
|
23696
|
+
persist
|
|
23697
|
+
);
|
|
23698
|
+
} else {
|
|
23699
|
+
await persist();
|
|
22257
23700
|
}
|
|
22258
|
-
await persistSetting(boundWorkspace, settingScope, key, value);
|
|
22259
23701
|
} catch (err) {
|
|
22260
23702
|
writeStderrLine(
|
|
22261
23703
|
`qwen serve: POST /workspace/settings persist error (key=${key}, scope=${scope}, workspace=${boundWorkspace}): ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -22267,7 +23709,7 @@ function registerWorkspaceSettingsRoutes(app, deps) {
|
|
|
22267
23709
|
return;
|
|
22268
23710
|
}
|
|
22269
23711
|
try {
|
|
22270
|
-
broadcastSettingsChanged(key,
|
|
23712
|
+
broadcastSettingsChanged(key, publicValue, scope, clientId);
|
|
22271
23713
|
} catch (err) {
|
|
22272
23714
|
writeStderrLine(
|
|
22273
23715
|
`qwen serve: POST /workspace/settings broadcast error (key=${key}, scope=${scope}): ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -22276,7 +23718,7 @@ function registerWorkspaceSettingsRoutes(app, deps) {
|
|
|
22276
23718
|
res.status(200).json({
|
|
22277
23719
|
key,
|
|
22278
23720
|
scope,
|
|
22279
|
-
value,
|
|
23721
|
+
value: publicValue,
|
|
22280
23722
|
requiresRestart: def.requiresRestart
|
|
22281
23723
|
});
|
|
22282
23724
|
}
|
|
@@ -22319,6 +23761,19 @@ function registerWorkspaceQualifiedSettingsRoutes(app, deps) {
|
|
|
22319
23761
|
const scope = body["scope"];
|
|
22320
23762
|
const key = body["key"];
|
|
22321
23763
|
const value = body["value"];
|
|
23764
|
+
let mcpServerMutation;
|
|
23765
|
+
try {
|
|
23766
|
+
mcpServerMutation = parseMcpServerMutation(
|
|
23767
|
+
typeof key === "string" ? key : "",
|
|
23768
|
+
body["mcpServerMutation"]
|
|
23769
|
+
);
|
|
23770
|
+
} catch (error2) {
|
|
23771
|
+
res.status(400).json({
|
|
23772
|
+
error: error2 instanceof Error ? error2.message : String(error2),
|
|
23773
|
+
code: "invalid_mcp_server_mutation"
|
|
23774
|
+
});
|
|
23775
|
+
return;
|
|
23776
|
+
}
|
|
22322
23777
|
if (typeof scope !== "string" || !QUALIFIED_WRITE_SCOPES.has(scope)) {
|
|
22323
23778
|
res.status(400).json({
|
|
22324
23779
|
error: `scope must be one of: ${[...QUALIFIED_WRITE_SCOPES].join(", ")}`,
|
|
@@ -22377,13 +23832,33 @@ function registerWorkspaceQualifiedSettingsRoutes(app, deps) {
|
|
|
22377
23832
|
});
|
|
22378
23833
|
return;
|
|
22379
23834
|
}
|
|
23835
|
+
let publicValue = value;
|
|
22380
23836
|
try {
|
|
22381
|
-
|
|
22382
|
-
|
|
22383
|
-
|
|
22384
|
-
|
|
22385
|
-
|
|
22386
|
-
|
|
23837
|
+
const persist = /* @__PURE__ */ __name(async () => {
|
|
23838
|
+
const prepared = prepareSettingWrite(
|
|
23839
|
+
runtime.workspaceCwd,
|
|
23840
|
+
settingScope,
|
|
23841
|
+
key,
|
|
23842
|
+
value,
|
|
23843
|
+
mcpServerMutation
|
|
23844
|
+
);
|
|
23845
|
+
publicValue = prepared.publicValue;
|
|
23846
|
+
await deps.persistSetting(
|
|
23847
|
+
runtime.workspaceCwd,
|
|
23848
|
+
settingScope,
|
|
23849
|
+
key,
|
|
23850
|
+
prepared.persistedValue
|
|
23851
|
+
);
|
|
23852
|
+
}, "persist");
|
|
23853
|
+
if (mcpServerMutation) {
|
|
23854
|
+
await withMcpServerMutationLock(
|
|
23855
|
+
runtime.workspaceCwd,
|
|
23856
|
+
settingScope,
|
|
23857
|
+
persist
|
|
23858
|
+
);
|
|
23859
|
+
} else {
|
|
23860
|
+
await persist();
|
|
23861
|
+
}
|
|
22387
23862
|
} catch (err) {
|
|
22388
23863
|
writeStderrLine(
|
|
22389
23864
|
`qwen serve: POST /workspaces/:workspace/settings persist error (key=${key}, scope=${scope}, workspace=${runtime.workspaceCwd}): ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -22397,13 +23872,13 @@ function registerWorkspaceQualifiedSettingsRoutes(app, deps) {
|
|
|
22397
23872
|
deps.invalidateServeFeaturesCache();
|
|
22398
23873
|
runtime.bridge.publishWorkspaceEvent({
|
|
22399
23874
|
type: "settings_changed",
|
|
22400
|
-
data: { key, value, scope },
|
|
23875
|
+
data: { key, value: publicValue, scope },
|
|
22401
23876
|
...clientId ? { originatorClientId: clientId } : {}
|
|
22402
23877
|
});
|
|
22403
23878
|
res.status(200).json({
|
|
22404
23879
|
key,
|
|
22405
23880
|
scope,
|
|
22406
|
-
value,
|
|
23881
|
+
value: publicValue,
|
|
22407
23882
|
requiresRestart: def.requiresRestart
|
|
22408
23883
|
});
|
|
22409
23884
|
}
|
|
@@ -22479,7 +23954,7 @@ function sendBridgeError(res, err, ctx, daemonLog) {
|
|
|
22479
23954
|
if (err instanceof WorkspaceSkillNotToggleableError) {
|
|
22480
23955
|
res.status(409).json({
|
|
22481
23956
|
error: err.message,
|
|
22482
|
-
code: "skill_not_toggleable",
|
|
23957
|
+
code: err.reason === "inactive_extension" ? "skill_inactive_extension" : "skill_not_toggleable",
|
|
22483
23958
|
skillName: err.skillName,
|
|
22484
23959
|
reason: err.reason,
|
|
22485
23960
|
...err.lockedScope ? { lockedScope: err.lockedScope } : {}
|
|
@@ -22621,6 +24096,14 @@ function sendBridgeError(res, err, ctx, daemonLog) {
|
|
|
22621
24096
|
});
|
|
22622
24097
|
return;
|
|
22623
24098
|
}
|
|
24099
|
+
if (err instanceof SessionNotArchivedError) {
|
|
24100
|
+
res.status(409).json({
|
|
24101
|
+
error: err.message,
|
|
24102
|
+
code: "session_not_archived",
|
|
24103
|
+
sessionId: err.sessionId
|
|
24104
|
+
});
|
|
24105
|
+
return;
|
|
24106
|
+
}
|
|
22624
24107
|
if (err instanceof SessionConflictError) {
|
|
22625
24108
|
res.status(409).json({
|
|
22626
24109
|
error: err.message,
|
|
@@ -22674,7 +24157,7 @@ function sendBridgeError(res, err, ctx, daemonLog) {
|
|
|
22674
24157
|
}
|
|
22675
24158
|
if (err instanceof WorkspaceMismatchError) {
|
|
22676
24159
|
writeStderrLine(
|
|
22677
|
-
`qwen serve: workspace_mismatch (POST /session):
|
|
24160
|
+
`qwen serve: workspace_mismatch (POST /session): runtime bound to ${JSON.stringify(err.bound)}, rejected ${JSON.stringify(err.requested)}`
|
|
22678
24161
|
);
|
|
22679
24162
|
res.status(400).json({
|
|
22680
24163
|
error: err.message,
|
|
@@ -22862,9 +24345,20 @@ function sendBridgeError(res, err, ctx, daemonLog) {
|
|
|
22862
24345
|
const d = data;
|
|
22863
24346
|
res.status(413).json({
|
|
22864
24347
|
error: errorMessage2(err),
|
|
22865
|
-
code: "transcript_too_large",
|
|
24348
|
+
code: "transcript_too_large",
|
|
24349
|
+
...d.sessionId ? { sessionId: d.sessionId } : {},
|
|
24350
|
+
...typeof d.snapshotSize === "number" ? { snapshotSize: d.snapshotSize } : {},
|
|
24351
|
+
...typeof d.maxBytes === "number" ? { maxBytes: d.maxBytes } : {}
|
|
24352
|
+
});
|
|
24353
|
+
return;
|
|
24354
|
+
}
|
|
24355
|
+
if (kind === "transcript_page_too_large") {
|
|
24356
|
+
const d = data;
|
|
24357
|
+
res.status(413).json({
|
|
24358
|
+
error: errorMessage2(err),
|
|
24359
|
+
code: "transcript_page_too_large",
|
|
22866
24360
|
...d.sessionId ? { sessionId: d.sessionId } : {},
|
|
22867
|
-
...typeof d.
|
|
24361
|
+
...typeof d.pageBytes === "number" ? { pageBytes: d.pageBytes } : {},
|
|
22868
24362
|
...typeof d.maxBytes === "number" ? { maxBytes: d.maxBytes } : {}
|
|
22869
24363
|
});
|
|
22870
24364
|
return;
|
|
@@ -23635,320 +25129,26 @@ function parseIdeWorkspacePathEnv(value) {
|
|
|
23635
25129
|
}
|
|
23636
25130
|
return value.split(path14.delimiter).filter((workspace) => workspace.length > 0 && path14.isAbsolute(workspace));
|
|
23637
25131
|
}
|
|
23638
|
-
__name(parseIdeWorkspacePathEnv, "parseIdeWorkspacePathEnv");
|
|
23639
|
-
function dropNestedWorkspacesPreservingPrimary(workspaces) {
|
|
23640
|
-
const primary = workspaces[0];
|
|
23641
|
-
if (primary === void 0) return [];
|
|
23642
|
-
const withoutPrimaryOverlaps = workspaces.filter(
|
|
23643
|
-
(workspace, i) => i === 0 || workspace !== primary && !isWithinRoot2(workspace, primary) && !isWithinRoot2(primary, workspace)
|
|
23644
|
-
);
|
|
23645
|
-
const filtered = withoutPrimaryOverlaps.filter(
|
|
23646
|
-
(workspace, i) => i === 0 || !withoutPrimaryOverlaps.some(
|
|
23647
|
-
(other, j) => i !== j && j !== 0 && workspace !== other && isWithinRoot2(workspace, other)
|
|
23648
|
-
)
|
|
23649
|
-
);
|
|
23650
|
-
if (filtered.length < workspaces.length) {
|
|
23651
|
-
writeStderrLine(
|
|
23652
|
-
"qwen serve: dropping nested IDE workspace roots (parent folders already cover children)"
|
|
23653
|
-
);
|
|
23654
|
-
}
|
|
23655
|
-
return filtered;
|
|
23656
|
-
}
|
|
23657
|
-
__name(dropNestedWorkspacesPreservingPrimary, "dropNestedWorkspacesPreservingPrimary");
|
|
23658
|
-
|
|
23659
|
-
// packages/cli/src/serve/server/telemetry.ts
|
|
23660
|
-
init_esbuild_shims();
|
|
23661
|
-
function decodePathSegment(value) {
|
|
23662
|
-
try {
|
|
23663
|
-
return decodeURIComponent(value);
|
|
23664
|
-
} catch {
|
|
23665
|
-
return value;
|
|
23666
|
-
}
|
|
23667
|
-
}
|
|
23668
|
-
__name(decodePathSegment, "decodePathSegment");
|
|
23669
|
-
function resolveDaemonTelemetryRoute(req) {
|
|
23670
|
-
const path15 = req.path.replace(/\/$/, "") || "/";
|
|
23671
|
-
if (req.method === "POST" && path15 === "/session") {
|
|
23672
|
-
return { route: "POST /session" };
|
|
23673
|
-
}
|
|
23674
|
-
if (req.method === "POST" && path15 === "/sessions/delete") {
|
|
23675
|
-
return { route: "POST /sessions/delete" };
|
|
23676
|
-
}
|
|
23677
|
-
if (req.method === "GET" && path15 === "/daemon/status") {
|
|
23678
|
-
return { route: "GET /daemon/status" };
|
|
23679
|
-
}
|
|
23680
|
-
const rewindSnapshots = path15.match(/^\/session\/([^/]+)\/rewind\/snapshots$/);
|
|
23681
|
-
if (rewindSnapshots?.[1] && req.method === "GET") {
|
|
23682
|
-
return {
|
|
23683
|
-
route: "GET /session/:id/rewind/snapshots",
|
|
23684
|
-
sessionId: rewindSnapshots[1]
|
|
23685
|
-
};
|
|
23686
|
-
}
|
|
23687
|
-
const sessionAction = path15.match(
|
|
23688
|
-
/^\/session\/([^/]+)\/(load|resume|prompt|cancel|recap|btw|mid-turn-message|model|shell|detach|rewind|approval-mode|language|a2ui-action)$/
|
|
23689
|
-
);
|
|
23690
|
-
const sessionActionId = sessionAction?.[1];
|
|
23691
|
-
const sessionActionName = sessionAction?.[2];
|
|
23692
|
-
if (sessionActionId && sessionActionName && req.method === "POST") {
|
|
23693
|
-
return {
|
|
23694
|
-
route: `POST /session/:id/${sessionActionName}`,
|
|
23695
|
-
sessionId: sessionActionId
|
|
23696
|
-
};
|
|
23697
|
-
}
|
|
23698
|
-
const sessionMetadata = path15.match(/^\/session\/([^/]+)\/metadata$/);
|
|
23699
|
-
if (sessionMetadata?.[1] && req.method === "PATCH") {
|
|
23700
|
-
return {
|
|
23701
|
-
route: "PATCH /session/:id/metadata",
|
|
23702
|
-
sessionId: sessionMetadata[1]
|
|
23703
|
-
};
|
|
23704
|
-
}
|
|
23705
|
-
const sessionArtifacts = path15.match(/^\/session\/([^/]+)\/artifacts$/);
|
|
23706
|
-
if (sessionArtifacts?.[1]) {
|
|
23707
|
-
if (req.method === "GET") {
|
|
23708
|
-
return {
|
|
23709
|
-
route: "GET /session/:id/artifacts",
|
|
23710
|
-
sessionId: sessionArtifacts[1]
|
|
23711
|
-
};
|
|
23712
|
-
}
|
|
23713
|
-
if (req.method === "POST") {
|
|
23714
|
-
return {
|
|
23715
|
-
route: "POST /session/:id/artifacts",
|
|
23716
|
-
sessionId: sessionArtifacts[1]
|
|
23717
|
-
};
|
|
23718
|
-
}
|
|
23719
|
-
}
|
|
23720
|
-
const sessionArtifact = path15.match(
|
|
23721
|
-
/^\/session\/([^/]+)\/artifacts\/([^/]+)$/
|
|
23722
|
-
);
|
|
23723
|
-
if (sessionArtifact?.[1] && req.method === "DELETE") {
|
|
23724
|
-
return {
|
|
23725
|
-
route: "DELETE /session/:id/artifacts/:artifactId",
|
|
23726
|
-
sessionId: sessionArtifact[1]
|
|
23727
|
-
};
|
|
23728
|
-
}
|
|
23729
|
-
const sessionPermission = path15.match(
|
|
23730
|
-
/^\/session\/([^/]+)\/permission\/([^/]+)$/
|
|
23731
|
-
);
|
|
23732
|
-
if (sessionPermission?.[1] && sessionPermission?.[2] && req.method === "POST") {
|
|
23733
|
-
const rawRequestId = sessionPermission[2];
|
|
23734
|
-
return {
|
|
23735
|
-
route: "POST /session/:id/permission/:requestId",
|
|
23736
|
-
sessionId: sessionPermission[1],
|
|
23737
|
-
...rawRequestId.length <= MAX_CLIENT_ID_LENGTH && CLIENT_ID_RE.test(rawRequestId) ? { permissionRequestId: rawRequestId } : {}
|
|
23738
|
-
};
|
|
23739
|
-
}
|
|
23740
|
-
const globalPermission = path15.match(/^\/permission\/([^/]+)$/);
|
|
23741
|
-
if (globalPermission?.[1] && req.method === "POST") {
|
|
23742
|
-
const rawRequestId = globalPermission[1];
|
|
23743
|
-
return {
|
|
23744
|
-
route: "POST /permission/:requestId",
|
|
23745
|
-
...rawRequestId.length <= MAX_CLIENT_ID_LENGTH && CLIENT_ID_RE.test(rawRequestId) ? { permissionRequestId: rawRequestId } : {}
|
|
23746
|
-
};
|
|
23747
|
-
}
|
|
23748
|
-
const deleteSession = path15.match(/^\/session\/([^/]+)$/);
|
|
23749
|
-
const deleteSessionId = deleteSession?.[1];
|
|
23750
|
-
if (deleteSessionId && req.method === "DELETE") {
|
|
23751
|
-
return { route: "DELETE /session/:id", sessionId: deleteSessionId };
|
|
23752
|
-
}
|
|
23753
|
-
if (req.method === "GET" && /^\/workspace\/[^/]+\/sessions$/.test(path15)) {
|
|
23754
|
-
return { route: "GET /workspace/:id/sessions" };
|
|
23755
|
-
}
|
|
23756
|
-
if (req.method === "GET" && /^\/workspaces\/[^/]+\/sessions$/.test(path15)) {
|
|
23757
|
-
return { route: "GET /workspace/:id/sessions" };
|
|
23758
|
-
}
|
|
23759
|
-
const workspaceTranscript = path15.match(
|
|
23760
|
-
/^\/workspaces\/[^/]+\/session\/([^/]+)\/transcript$/
|
|
23761
|
-
);
|
|
23762
|
-
if (workspaceTranscript?.[1] && req.method === "GET") {
|
|
23763
|
-
return {
|
|
23764
|
-
route: "GET /workspaces/:workspace/session/:id/transcript",
|
|
23765
|
-
sessionId: workspaceTranscript[1]
|
|
23766
|
-
};
|
|
23767
|
-
}
|
|
23768
|
-
const workspaceExport = path15.match(
|
|
23769
|
-
/^\/workspaces\/[^/]+\/session\/([^/]+)\/export$/
|
|
23770
|
-
);
|
|
23771
|
-
if (workspaceExport?.[1] && req.method === "GET") {
|
|
23772
|
-
return {
|
|
23773
|
-
route: "GET /workspaces/:workspace/session/:id/export",
|
|
23774
|
-
sessionId: workspaceExport[1]
|
|
23775
|
-
};
|
|
23776
|
-
}
|
|
23777
|
-
const pluralWorkspacePrefix = /^\/workspaces\/[^/]+/;
|
|
23778
|
-
if (pluralWorkspacePrefix.test(path15)) {
|
|
23779
|
-
const suffix = path15.replace(pluralWorkspacePrefix, "/workspace");
|
|
23780
|
-
if (req.method === "GET") {
|
|
23781
|
-
if (suffix === "/workspace/mcp" || suffix === "/workspace/skills" || suffix === "/workspace/tools" || suffix === "/workspace/providers" || suffix === "/workspace/env" || suffix === "/workspace/preflight" || suffix === "/workspace/hooks" || suffix === "/workspace/settings" || suffix === "/workspace/voice" || suffix === "/workspace/permissions" || suffix === "/workspace/trust" || suffix === "/workspace/memory" || suffix === "/workspace/agents") {
|
|
23782
|
-
return { route: `GET ${suffix}` };
|
|
23783
|
-
}
|
|
23784
|
-
if (/^\/workspace\/agents\/[^/]+$/.test(suffix)) {
|
|
23785
|
-
return { route: "GET /workspace/agents/:agentType" };
|
|
23786
|
-
}
|
|
23787
|
-
if (suffix === "/workspace/file") return { route: "GET /file" };
|
|
23788
|
-
if (suffix === "/workspace/file/bytes") {
|
|
23789
|
-
return { route: "GET /file/bytes" };
|
|
23790
|
-
}
|
|
23791
|
-
if (suffix === "/workspace/stat") return { route: "GET /stat" };
|
|
23792
|
-
if (suffix === "/workspace/list") return { route: "GET /list" };
|
|
23793
|
-
if (suffix === "/workspace/glob") return { route: "GET /glob" };
|
|
23794
|
-
if (/^\/workspace\/mcp\/[^/]+\/tools$/.test(suffix)) {
|
|
23795
|
-
return { route: "GET /workspace/mcp/:server/tools" };
|
|
23796
|
-
}
|
|
23797
|
-
if (/^\/workspace\/mcp\/[^/]+\/resources$/.test(suffix)) {
|
|
23798
|
-
return { route: "GET /workspace/mcp/:server/resources" };
|
|
23799
|
-
}
|
|
23800
|
-
}
|
|
23801
|
-
if (req.method === "POST") {
|
|
23802
|
-
if (suffix === "/workspace/settings" || suffix === "/workspace/voice" || suffix === "/workspace/voice/transcribe" || suffix === "/workspace/permissions" || suffix === "/workspace/trust/request" || suffix === "/workspace/init" || suffix === "/workspace/reload" || suffix === "/workspace/file/write" || suffix === "/workspace/file/edit" || suffix === "/workspace/mcp/servers" || suffix === "/workspace/memory" || suffix === "/workspace/agents" || suffix === "/workspace/sessions/delete" || suffix === "/workspace/sessions/archive" || suffix === "/workspace/sessions/unarchive" || suffix === "/workspace/session-groups") {
|
|
23803
|
-
return { route: `POST ${suffix}` };
|
|
23804
|
-
}
|
|
23805
|
-
if (/^\/workspace\/tools\/[^/]+\/enable$/.test(suffix)) {
|
|
23806
|
-
return { route: "POST /workspace/tools/:name/enable" };
|
|
23807
|
-
}
|
|
23808
|
-
if (/^\/workspace\/mcp\/[^/]+\/restart$/.test(suffix)) {
|
|
23809
|
-
return { route: "POST /workspace/mcp/:server/restart" };
|
|
23810
|
-
}
|
|
23811
|
-
if (/^\/workspace\/agents\/[^/]+$/.test(suffix)) {
|
|
23812
|
-
return { route: "POST /workspace/agents/:agentType" };
|
|
23813
|
-
}
|
|
23814
|
-
if (/^\/workspace\/mcp\/[^/]+\/(enable|disable|authenticate|clear-auth)$/.test(
|
|
23815
|
-
suffix
|
|
23816
|
-
)) {
|
|
23817
|
-
return {
|
|
23818
|
-
route: `POST /workspace/mcp/:server/${suffix.split("/").at(-1)}`
|
|
23819
|
-
};
|
|
23820
|
-
}
|
|
23821
|
-
}
|
|
23822
|
-
if (req.method === "DELETE" && /^\/workspace\/mcp\/servers\/[^/]+$/.test(suffix)) {
|
|
23823
|
-
return { route: "DELETE /workspace/mcp/servers/:name" };
|
|
23824
|
-
}
|
|
23825
|
-
if (req.method === "DELETE" && /^\/workspace\/agents\/[^/]+$/.test(suffix)) {
|
|
23826
|
-
return { route: "DELETE /workspace/agents/:agentType" };
|
|
23827
|
-
}
|
|
23828
|
-
if (suffix === "/workspace/session-groups" && req.method === "GET") {
|
|
23829
|
-
return { route: "GET /workspace/session-groups" };
|
|
23830
|
-
}
|
|
23831
|
-
if (/^\/workspace\/session-groups\/[^/]+$/.test(suffix) && req.method === "PATCH") {
|
|
23832
|
-
return { route: "PATCH /workspace/session-groups/:groupId" };
|
|
23833
|
-
}
|
|
23834
|
-
if (/^\/workspace\/session-groups\/[^/]+$/.test(suffix) && req.method === "DELETE") {
|
|
23835
|
-
return { route: "DELETE /workspace/session-groups/:groupId" };
|
|
23836
|
-
}
|
|
23837
|
-
}
|
|
23838
|
-
if (req.method === "POST" && path15 === "/workspace/init") {
|
|
23839
|
-
return { route: "POST /workspace/init" };
|
|
23840
|
-
}
|
|
23841
|
-
if (req.method === "POST" && path15 === "/workspace/setup-github") {
|
|
23842
|
-
return { route: "POST /workspace/setup-github" };
|
|
23843
|
-
}
|
|
23844
|
-
if (req.method === "POST" && path15 === "/workspace/reload") {
|
|
23845
|
-
return { route: "POST /workspace/reload" };
|
|
23846
|
-
}
|
|
23847
|
-
const mcpRestart = path15.match(/^\/workspace\/mcp\/([^/]+)\/restart$/);
|
|
23848
|
-
if (mcpRestart?.[1] && req.method === "POST") {
|
|
23849
|
-
return { route: "POST /workspace/mcp/:server/restart" };
|
|
23850
|
-
}
|
|
23851
|
-
if (req.method === "POST" && path15 === "/workspace/mcp/servers") {
|
|
23852
|
-
return { route: "POST /workspace/mcp/servers" };
|
|
23853
|
-
}
|
|
23854
|
-
const mcpDelete = path15.match(/^\/workspace\/mcp\/servers\/([^/]+)$/);
|
|
23855
|
-
if (mcpDelete?.[1] && req.method === "DELETE") {
|
|
23856
|
-
return { route: "DELETE /workspace/mcp/servers/:name" };
|
|
23857
|
-
}
|
|
23858
|
-
if (req.method === "POST" && path15 === "/workspace/auth/device-flow") {
|
|
23859
|
-
return { route: "POST /workspace/auth/device-flow" };
|
|
23860
|
-
}
|
|
23861
|
-
const deviceFlowDelete = path15.match(
|
|
23862
|
-
/^\/workspace\/auth\/device-flow\/([^/]+)$/
|
|
23863
|
-
);
|
|
23864
|
-
if (deviceFlowDelete?.[1] && req.method === "DELETE") {
|
|
23865
|
-
return { route: "DELETE /workspace/auth/device-flow/:id" };
|
|
23866
|
-
}
|
|
23867
|
-
const toolEnable = path15.match(/^\/workspace\/tools\/([^/]+)\/enable$/);
|
|
23868
|
-
if (toolEnable?.[1] && req.method === "POST") {
|
|
23869
|
-
return { route: "POST /workspace/tools/:name/enable" };
|
|
23870
|
-
}
|
|
23871
|
-
if (path15 === "/workspace/settings") {
|
|
23872
|
-
if (req.method === "GET") return { route: "GET /workspace/settings" };
|
|
23873
|
-
if (req.method === "POST") return { route: "POST /workspace/settings" };
|
|
23874
|
-
}
|
|
23875
|
-
if (path15 === "/workspace/permissions") {
|
|
23876
|
-
if (req.method === "GET") return { route: "GET /workspace/permissions" };
|
|
23877
|
-
if (req.method === "POST") return { route: "POST /workspace/permissions" };
|
|
23878
|
-
}
|
|
23879
|
-
if (path15 === "/workspace/trust") {
|
|
23880
|
-
if (req.method === "GET") return { route: "GET /workspace/trust" };
|
|
23881
|
-
}
|
|
23882
|
-
if (req.method === "POST" && path15 === "/workspace/trust/request") {
|
|
23883
|
-
return { route: "POST /workspace/trust/request" };
|
|
23884
|
-
}
|
|
23885
|
-
if (path15 === "/workspace/voice") {
|
|
23886
|
-
if (req.method === "GET") return { route: "GET /workspace/voice" };
|
|
23887
|
-
if (req.method === "POST") return { route: "POST /workspace/voice" };
|
|
23888
|
-
}
|
|
23889
|
-
if (req.method === "POST" && path15 === "/workspace/voice/transcribe") {
|
|
23890
|
-
return { route: "POST /workspace/voice/transcribe" };
|
|
23891
|
-
}
|
|
23892
|
-
return void 0;
|
|
23893
|
-
}
|
|
23894
|
-
__name(resolveDaemonTelemetryRoute, "resolveDaemonTelemetryRoute");
|
|
23895
|
-
function daemonTelemetryMiddleware(resolveWorkspaceCwd, recordRequest, resolveSessionWorkspaceCwd) {
|
|
23896
|
-
const workspaceHashByCwd = /* @__PURE__ */ new Map();
|
|
23897
|
-
const resolveWorkspaceHash = /* @__PURE__ */ __name((workspaceCwd) => {
|
|
23898
|
-
const existing = workspaceHashByCwd.get(workspaceCwd);
|
|
23899
|
-
if (existing !== void 0) return existing;
|
|
23900
|
-
const workspaceHash = hashDaemonWorkspace(workspaceCwd);
|
|
23901
|
-
workspaceHashByCwd.set(workspaceCwd, workspaceHash);
|
|
23902
|
-
return workspaceHash;
|
|
23903
|
-
}, "resolveWorkspaceHash");
|
|
23904
|
-
return (req, res, next) => {
|
|
23905
|
-
const route = resolveDaemonTelemetryRoute(req);
|
|
23906
|
-
if (!route) {
|
|
23907
|
-
next();
|
|
23908
|
-
return;
|
|
23909
|
-
}
|
|
23910
|
-
const resolveOwnerWorkspace = route.route === "GET /session/:id/rewind/snapshots" || route.route === "POST /session/:id/rewind" || route.route === "POST /session/:id/shell";
|
|
23911
|
-
const sessionId = route.sessionId ? decodePathSegment(route.sessionId) : void 0;
|
|
23912
|
-
const workspaceCwd = (resolveOwnerWorkspace && sessionId ? resolveSessionWorkspaceCwd?.(sessionId) : void 0) ?? resolveWorkspaceCwd(req);
|
|
23913
|
-
const workspaceHash = resolveWorkspaceHash(workspaceCwd);
|
|
23914
|
-
const rawClientId = req.get(CLIENT_ID_HEADER);
|
|
23915
|
-
const clientId = rawClientId !== void 0 && rawClientId !== "" && rawClientId.length <= MAX_CLIENT_ID_LENGTH && CLIENT_ID_RE.test(rawClientId) ? rawClientId : void 0;
|
|
23916
|
-
const startMs = Date.now();
|
|
23917
|
-
void withDaemonRequestSpan(
|
|
23918
|
-
{
|
|
23919
|
-
method: req.method,
|
|
23920
|
-
route: route.route,
|
|
23921
|
-
workspaceHash,
|
|
23922
|
-
...sessionId ? { sessionId } : {},
|
|
23923
|
-
...route.permissionRequestId ? { permissionRequestId: route.permissionRequestId } : {},
|
|
23924
|
-
...clientId ? { clientId } : {}
|
|
23925
|
-
},
|
|
23926
|
-
async (span) => await new Promise((resolve5, reject) => {
|
|
23927
|
-
let done = false;
|
|
23928
|
-
const finish = /* @__PURE__ */ __name(() => {
|
|
23929
|
-
if (done) return;
|
|
23930
|
-
done = true;
|
|
23931
|
-
recordDaemonHttpResponse(span, res.statusCode);
|
|
23932
|
-
const durationMs = Date.now() - startMs;
|
|
23933
|
-
recordDaemonHttpRequest(durationMs, route.route, res.statusCode);
|
|
23934
|
-
if (route.route !== "GET /daemon/status") {
|
|
23935
|
-
recordRequest?.(durationMs, res.statusCode);
|
|
23936
|
-
}
|
|
23937
|
-
resolve5();
|
|
23938
|
-
}, "finish");
|
|
23939
|
-
res.once("finish", finish);
|
|
23940
|
-
res.once("close", finish);
|
|
23941
|
-
try {
|
|
23942
|
-
next();
|
|
23943
|
-
} catch (error2) {
|
|
23944
|
-
recordDaemonError(span, error2);
|
|
23945
|
-
reject(error2);
|
|
23946
|
-
}
|
|
23947
|
-
})
|
|
23948
|
-
).catch(next);
|
|
23949
|
-
};
|
|
25132
|
+
__name(parseIdeWorkspacePathEnv, "parseIdeWorkspacePathEnv");
|
|
25133
|
+
function dropNestedWorkspacesPreservingPrimary(workspaces) {
|
|
25134
|
+
const primary = workspaces[0];
|
|
25135
|
+
if (primary === void 0) return [];
|
|
25136
|
+
const withoutPrimaryOverlaps = workspaces.filter(
|
|
25137
|
+
(workspace, i) => i === 0 || workspace !== primary && !isWithinRoot2(workspace, primary) && !isWithinRoot2(primary, workspace)
|
|
25138
|
+
);
|
|
25139
|
+
const filtered = withoutPrimaryOverlaps.filter(
|
|
25140
|
+
(workspace, i) => i === 0 || !withoutPrimaryOverlaps.some(
|
|
25141
|
+
(other, j) => i !== j && j !== 0 && workspace !== other && isWithinRoot2(workspace, other)
|
|
25142
|
+
)
|
|
25143
|
+
);
|
|
25144
|
+
if (filtered.length < workspaces.length) {
|
|
25145
|
+
writeStderrLine(
|
|
25146
|
+
"qwen serve: dropping nested IDE workspace roots (parent folders already cover children)"
|
|
25147
|
+
);
|
|
25148
|
+
}
|
|
25149
|
+
return filtered;
|
|
23950
25150
|
}
|
|
23951
|
-
__name(
|
|
25151
|
+
__name(dropNestedWorkspacesPreservingPrimary, "dropNestedWorkspacesPreservingPrimary");
|
|
23952
25152
|
|
|
23953
25153
|
// packages/cli/src/serve/server/access-log.ts
|
|
23954
25154
|
init_esbuild_shims();
|
|
@@ -24473,9 +25673,10 @@ __name(registerWorkspaceQualifiedLifecycleRoutes, "registerWorkspaceQualifiedLif
|
|
|
24473
25673
|
|
|
24474
25674
|
// packages/cli/src/serve/routes/workspace-management.ts
|
|
24475
25675
|
init_esbuild_shims();
|
|
24476
|
-
import { stat } from "node:fs/promises";
|
|
25676
|
+
import { readdir, stat } from "node:fs/promises";
|
|
24477
25677
|
import { realpathSync } from "node:fs";
|
|
24478
|
-
import { isAbsolute as isAbsolute7, resolve as resolve4 } from "node:path";
|
|
25678
|
+
import { basename as basename4, dirname as dirname4, isAbsolute as isAbsolute7, join as join7, resolve as resolve4, sep as sep3 } from "node:path";
|
|
25679
|
+
var MAX_PATH_SUGGESTIONS = 50;
|
|
24479
25680
|
function registerWorkspaceManagementRoutes(app, deps) {
|
|
24480
25681
|
const {
|
|
24481
25682
|
workspaceRegistry,
|
|
@@ -24505,6 +25706,72 @@ function registerWorkspaceManagementRoutes(app, deps) {
|
|
|
24505
25706
|
code: "daemon_shutting_down"
|
|
24506
25707
|
});
|
|
24507
25708
|
}, "sendSealed");
|
|
25709
|
+
app.get(
|
|
25710
|
+
"/workspace-path-suggestions",
|
|
25711
|
+
async (req, res) => {
|
|
25712
|
+
const prefixRaw = req.query["prefix"];
|
|
25713
|
+
if (typeof prefixRaw !== "string" || prefixRaw.trim().length === 0) {
|
|
25714
|
+
res.status(400).json({
|
|
25715
|
+
error: "`prefix` must be a non-empty string",
|
|
25716
|
+
code: "invalid_prefix"
|
|
25717
|
+
});
|
|
25718
|
+
return;
|
|
25719
|
+
}
|
|
25720
|
+
const prefix = prefixRaw;
|
|
25721
|
+
if (prefix.length > MAX_WORKSPACE_PATH_LENGTH) {
|
|
25722
|
+
res.status(400).json({
|
|
25723
|
+
error: `\`prefix\` exceeds the ${MAX_WORKSPACE_PATH_LENGTH}-character limit`,
|
|
25724
|
+
code: "invalid_prefix"
|
|
25725
|
+
});
|
|
25726
|
+
return;
|
|
25727
|
+
}
|
|
25728
|
+
if (!isAbsolute7(prefix)) {
|
|
25729
|
+
res.status(400).json({
|
|
25730
|
+
error: "`prefix` must be an absolute path",
|
|
25731
|
+
code: "invalid_prefix"
|
|
25732
|
+
});
|
|
25733
|
+
return;
|
|
25734
|
+
}
|
|
25735
|
+
const endsWithSep = prefix.endsWith("/") || process.platform === "win32" && prefix.endsWith("\\");
|
|
25736
|
+
const dir = endsWithSep ? join7(prefix, ".") : dirname4(prefix);
|
|
25737
|
+
const filter = endsWithSep ? "" : basename4(prefix);
|
|
25738
|
+
const filterLower = filter.toLowerCase();
|
|
25739
|
+
const suggestions = [];
|
|
25740
|
+
let truncated = false;
|
|
25741
|
+
try {
|
|
25742
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
25743
|
+
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
25744
|
+
for (const entry of entries) {
|
|
25745
|
+
if (entry.name.startsWith(".") && !filter.startsWith(".")) continue;
|
|
25746
|
+
if (filter && !entry.name.toLowerCase().startsWith(filterLower)) {
|
|
25747
|
+
continue;
|
|
25748
|
+
}
|
|
25749
|
+
let isDir = entry.isDirectory();
|
|
25750
|
+
if (!isDir && entry.isSymbolicLink()) {
|
|
25751
|
+
try {
|
|
25752
|
+
isDir = (await stat(join7(dir, entry.name))).isDirectory();
|
|
25753
|
+
} catch {
|
|
25754
|
+
continue;
|
|
25755
|
+
}
|
|
25756
|
+
}
|
|
25757
|
+
if (!isDir) continue;
|
|
25758
|
+
if (suggestions.length >= MAX_PATH_SUGGESTIONS) {
|
|
25759
|
+
truncated = true;
|
|
25760
|
+
break;
|
|
25761
|
+
}
|
|
25762
|
+
suggestions.push({ name: entry.name, path: join7(dir, entry.name) });
|
|
25763
|
+
}
|
|
25764
|
+
} catch {
|
|
25765
|
+
}
|
|
25766
|
+
res.status(200).json({
|
|
25767
|
+
kind: "workspace-path-suggestions",
|
|
25768
|
+
dir,
|
|
25769
|
+
sep: sep3,
|
|
25770
|
+
suggestions,
|
|
25771
|
+
truncated
|
|
25772
|
+
});
|
|
25773
|
+
}
|
|
25774
|
+
);
|
|
24508
25775
|
app.post(
|
|
24509
25776
|
"/workspaces",
|
|
24510
25777
|
mutate({ strict: true }),
|
|
@@ -25330,6 +26597,30 @@ function registerWorkspaceMcpControlRoutes(app, deps) {
|
|
|
25330
26597
|
parseAndValidateClientId
|
|
25331
26598
|
} = deps;
|
|
25332
26599
|
const buildWorkspaceCtx = createBuildWorkspaceCtx(boundWorkspace);
|
|
26600
|
+
app.post(
|
|
26601
|
+
"/workspace/mcp/initialize",
|
|
26602
|
+
mutate({ strict: true }),
|
|
26603
|
+
async (_req, res) => {
|
|
26604
|
+
try {
|
|
26605
|
+
const result = await bridge.initializeWorkspaceMcp();
|
|
26606
|
+
res.status(202).json(result);
|
|
26607
|
+
} catch (err) {
|
|
26608
|
+
sendBridgeError2(res, err, { route: "POST /workspace/mcp/initialize" });
|
|
26609
|
+
}
|
|
26610
|
+
}
|
|
26611
|
+
);
|
|
26612
|
+
app.post(
|
|
26613
|
+
"/workspace/mcp/reload",
|
|
26614
|
+
mutate({ strict: true }),
|
|
26615
|
+
async (_req, res) => {
|
|
26616
|
+
try {
|
|
26617
|
+
const result = await bridge.reloadWorkspaceMcp();
|
|
26618
|
+
res.status(202).json(result);
|
|
26619
|
+
} catch (err) {
|
|
26620
|
+
sendBridgeError2(res, err, { route: "POST /workspace/mcp/reload" });
|
|
26621
|
+
}
|
|
26622
|
+
}
|
|
26623
|
+
);
|
|
25333
26624
|
app.post(
|
|
25334
26625
|
"/workspace/mcp/:server/restart",
|
|
25335
26626
|
mutate({ strict: true }),
|
|
@@ -25384,6 +26675,7 @@ function registerWorkspaceMcpControlRoutes(app, deps) {
|
|
|
25384
26675
|
}
|
|
25385
26676
|
);
|
|
25386
26677
|
for (const [routeAction, bridgeAction] of [
|
|
26678
|
+
["approve", "approve"],
|
|
25387
26679
|
["enable", "enable"],
|
|
25388
26680
|
["disable", "disable"],
|
|
25389
26681
|
["authenticate", "authenticate"],
|
|
@@ -25498,6 +26790,44 @@ function resolveTrustedMcpRuntime(registry, req, res) {
|
|
|
25498
26790
|
}
|
|
25499
26791
|
__name(resolveTrustedMcpRuntime, "resolveTrustedMcpRuntime");
|
|
25500
26792
|
function registerWorkspaceQualifiedMcpControlRoutes(app, deps) {
|
|
26793
|
+
app.post(
|
|
26794
|
+
"/workspaces/:workspace/mcp/initialize",
|
|
26795
|
+
deps.mutate({ strict: true }),
|
|
26796
|
+
async (req, res) => {
|
|
26797
|
+
const runtime = resolveTrustedMcpRuntime(
|
|
26798
|
+
deps.workspaceRegistry,
|
|
26799
|
+
req,
|
|
26800
|
+
res
|
|
26801
|
+
);
|
|
26802
|
+
if (!runtime) return;
|
|
26803
|
+
const route = "POST /workspaces/:workspace/mcp/initialize";
|
|
26804
|
+
try {
|
|
26805
|
+
const result = await runtime.bridge.initializeWorkspaceMcp();
|
|
26806
|
+
res.status(202).json(result);
|
|
26807
|
+
} catch (err) {
|
|
26808
|
+
deps.sendBridgeError(res, err, { route });
|
|
26809
|
+
}
|
|
26810
|
+
}
|
|
26811
|
+
);
|
|
26812
|
+
app.post(
|
|
26813
|
+
"/workspaces/:workspace/mcp/reload",
|
|
26814
|
+
deps.mutate({ strict: true }),
|
|
26815
|
+
async (req, res) => {
|
|
26816
|
+
const runtime = resolveTrustedMcpRuntime(
|
|
26817
|
+
deps.workspaceRegistry,
|
|
26818
|
+
req,
|
|
26819
|
+
res
|
|
26820
|
+
);
|
|
26821
|
+
if (!runtime) return;
|
|
26822
|
+
const route = "POST /workspaces/:workspace/mcp/reload";
|
|
26823
|
+
try {
|
|
26824
|
+
const result = await runtime.bridge.reloadWorkspaceMcp();
|
|
26825
|
+
res.status(202).json(result);
|
|
26826
|
+
} catch (err) {
|
|
26827
|
+
deps.sendBridgeError(res, err, { route });
|
|
26828
|
+
}
|
|
26829
|
+
}
|
|
26830
|
+
);
|
|
25501
26831
|
app.post(
|
|
25502
26832
|
"/workspaces/:workspace/mcp/:server/restart",
|
|
25503
26833
|
deps.mutate({ strict: true }),
|
|
@@ -25561,6 +26891,7 @@ function registerWorkspaceQualifiedMcpControlRoutes(app, deps) {
|
|
|
25561
26891
|
}
|
|
25562
26892
|
);
|
|
25563
26893
|
for (const [routeAction, bridgeAction] of [
|
|
26894
|
+
["approve", "approve"],
|
|
25564
26895
|
["enable", "enable"],
|
|
25565
26896
|
["disable", "disable"],
|
|
25566
26897
|
["authenticate", "authenticate"],
|
|
@@ -25752,11 +27083,84 @@ function parseSelection(body, res) {
|
|
|
25752
27083
|
}
|
|
25753
27084
|
}
|
|
25754
27085
|
__name(parseSelection, "parseSelection");
|
|
27086
|
+
function sanitizeControlDiagnostic(value, maxLength) {
|
|
27087
|
+
return sanitizeLogText(
|
|
27088
|
+
redactLogCredentials(normalizeWorkerDiagnostic(value)),
|
|
27089
|
+
maxLength
|
|
27090
|
+
);
|
|
27091
|
+
}
|
|
27092
|
+
__name(sanitizeControlDiagnostic, "sanitizeControlDiagnostic");
|
|
27093
|
+
function startupFailureResponseFields(error2) {
|
|
27094
|
+
if (!error2 || typeof error2 !== "object") return {};
|
|
27095
|
+
let rawFailures;
|
|
27096
|
+
let rawTruncated;
|
|
27097
|
+
try {
|
|
27098
|
+
rawFailures = Reflect.get(error2, "startupFailures");
|
|
27099
|
+
rawTruncated = Reflect.get(error2, "startupFailuresTruncated");
|
|
27100
|
+
} catch {
|
|
27101
|
+
return {};
|
|
27102
|
+
}
|
|
27103
|
+
if (!Array.isArray(rawFailures)) return {};
|
|
27104
|
+
let limitedFailures;
|
|
27105
|
+
let rawFailureCount;
|
|
27106
|
+
try {
|
|
27107
|
+
limitedFailures = rawFailures.slice(0, MAX_CHANNEL_STARTUP_FAILURES);
|
|
27108
|
+
rawFailureCount = rawFailures.length;
|
|
27109
|
+
} catch {
|
|
27110
|
+
return {};
|
|
27111
|
+
}
|
|
27112
|
+
const startupFailures = limitedFailures.flatMap((raw) => {
|
|
27113
|
+
try {
|
|
27114
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return [];
|
|
27115
|
+
const failure = raw;
|
|
27116
|
+
if (typeof failure["workspaceCwd"] !== "string" || failure["workspaceCwd"].length === 0 || typeof failure["channel"] !== "string" || failure["channel"].length === 0 || failure["phase"] !== "connect" || typeof failure["message"] !== "string" || failure["message"].length === 0 || failure["code"] !== void 0 && (typeof failure["code"] !== "string" || failure["code"].length === 0)) {
|
|
27117
|
+
return [];
|
|
27118
|
+
}
|
|
27119
|
+
const workspaceCwd = sanitizeControlDiagnostic(
|
|
27120
|
+
failure["workspaceCwd"],
|
|
27121
|
+
MAX_WORKSPACE_PATH_LENGTH
|
|
27122
|
+
);
|
|
27123
|
+
const channel = sanitizeControlDiagnostic(
|
|
27124
|
+
failure["channel"],
|
|
27125
|
+
MAX_CHANNEL_STARTUP_FAILURE_CHANNEL_LENGTH
|
|
27126
|
+
);
|
|
27127
|
+
const message = sanitizeControlDiagnostic(
|
|
27128
|
+
failure["message"],
|
|
27129
|
+
MAX_CHANNEL_STARTUP_FAILURE_MESSAGE_LENGTH
|
|
27130
|
+
);
|
|
27131
|
+
const code = typeof failure["code"] === "string" ? sanitizeControlDiagnostic(
|
|
27132
|
+
failure["code"],
|
|
27133
|
+
MAX_CHANNEL_STARTUP_FAILURE_CODE_LENGTH
|
|
27134
|
+
) : void 0;
|
|
27135
|
+
if (!workspaceCwd || !channel || !message) return [];
|
|
27136
|
+
return [
|
|
27137
|
+
{
|
|
27138
|
+
workspaceCwd,
|
|
27139
|
+
channel,
|
|
27140
|
+
phase: "connect",
|
|
27141
|
+
...code ? { code } : {},
|
|
27142
|
+
message
|
|
27143
|
+
}
|
|
27144
|
+
];
|
|
27145
|
+
} catch {
|
|
27146
|
+
return [];
|
|
27147
|
+
}
|
|
27148
|
+
});
|
|
27149
|
+
if (startupFailures.length === 0) return {};
|
|
27150
|
+
const truncated = rawTruncated === true || rawFailureCount > MAX_CHANNEL_STARTUP_FAILURES;
|
|
27151
|
+
return {
|
|
27152
|
+
startupFailures,
|
|
27153
|
+
...truncated ? { startupFailuresTruncated: true } : {}
|
|
27154
|
+
};
|
|
27155
|
+
}
|
|
27156
|
+
__name(startupFailureResponseFields, "startupFailureResponseFields");
|
|
25755
27157
|
function sendChannelControlError(res, error2, getState) {
|
|
25756
27158
|
const code = error2 && typeof error2 === "object" && "code" in error2 ? error2.code : void 0;
|
|
25757
|
-
const
|
|
25758
|
-
|
|
25759
|
-
|
|
27159
|
+
const rawMessage = error2 instanceof Error ? error2.message : String(error2);
|
|
27160
|
+
const message = code === "channel_worker_start_failed" ? sanitizeControlDiagnostic(
|
|
27161
|
+
rawMessage,
|
|
27162
|
+
MAX_CHANNEL_STARTUP_FAILURE_MESSAGE_LENGTH
|
|
27163
|
+
) : redactLogCredentials(rawMessage);
|
|
25760
27164
|
if (code === "channel_workspace_mismatch" || code === "ambiguous_channel_workspace") {
|
|
25761
27165
|
res.status(400).json({ error: message, code });
|
|
25762
27166
|
return true;
|
|
@@ -25792,7 +27196,13 @@ function sendChannelControlError(res, error2, getState) {
|
|
|
25792
27196
|
error: message,
|
|
25793
27197
|
code,
|
|
25794
27198
|
...typeof controlError.rolledBack === "boolean" ? { rolledBack: controlError.rolledBack } : {},
|
|
25795
|
-
...typeof controlError.rollbackError === "string" && controlError.rollbackError ? {
|
|
27199
|
+
...typeof controlError.rollbackError === "string" && controlError.rollbackError ? {
|
|
27200
|
+
rollbackError: sanitizeControlDiagnostic(
|
|
27201
|
+
controlError.rollbackError,
|
|
27202
|
+
512
|
|
27203
|
+
)
|
|
27204
|
+
} : {},
|
|
27205
|
+
...code === "channel_worker_start_failed" ? startupFailureResponseFields(error2) : {},
|
|
25796
27206
|
state: getState()
|
|
25797
27207
|
});
|
|
25798
27208
|
return true;
|
|
@@ -26053,9 +27463,9 @@ function parseSkillToggleRequest(req, res, safeBody2) {
|
|
|
26053
27463
|
});
|
|
26054
27464
|
return void 0;
|
|
26055
27465
|
}
|
|
26056
|
-
if (skillName.length >
|
|
27466
|
+
if (skillName.length > MAX_WORKSPACE_SKILL_NAME_LENGTH) {
|
|
26057
27467
|
res.status(400).json({
|
|
26058
|
-
error: `Skill name exceeds ${
|
|
27468
|
+
error: `Skill name exceeds ${MAX_WORKSPACE_SKILL_NAME_LENGTH}-character limit`,
|
|
26059
27469
|
code: "invalid_skill_name"
|
|
26060
27470
|
});
|
|
26061
27471
|
return void 0;
|
|
@@ -26071,11 +27481,138 @@ function parseSkillToggleRequest(req, res, safeBody2) {
|
|
|
26071
27481
|
return { skillName, enabled };
|
|
26072
27482
|
}
|
|
26073
27483
|
__name(parseSkillToggleRequest, "parseSkillToggleRequest");
|
|
27484
|
+
function parseSkillScope(value, res) {
|
|
27485
|
+
if (value === "workspace" || value === "global") return value;
|
|
27486
|
+
res.status(400).json({
|
|
27487
|
+
error: '`scope` must be "workspace" or "global"',
|
|
27488
|
+
code: "invalid_skill_scope"
|
|
27489
|
+
});
|
|
27490
|
+
return void 0;
|
|
27491
|
+
}
|
|
27492
|
+
__name(parseSkillScope, "parseSkillScope");
|
|
27493
|
+
function parseSkillInstallRequest(req, res, safeBody2) {
|
|
27494
|
+
const body = safeBody2(req);
|
|
27495
|
+
const name = body["name"];
|
|
27496
|
+
if (typeof name !== "string" || !name.trim()) {
|
|
27497
|
+
res.status(400).json({
|
|
27498
|
+
error: "`name` is required and must be a string",
|
|
27499
|
+
code: "invalid_skill_name"
|
|
27500
|
+
});
|
|
27501
|
+
return void 0;
|
|
27502
|
+
}
|
|
27503
|
+
if (name.trim().length > MAX_WORKSPACE_SKILL_NAME_LENGTH) {
|
|
27504
|
+
res.status(400).json({
|
|
27505
|
+
error: `Skill name exceeds ${MAX_WORKSPACE_SKILL_NAME_LENGTH}-character limit`,
|
|
27506
|
+
code: "invalid_skill_name"
|
|
27507
|
+
});
|
|
27508
|
+
return void 0;
|
|
27509
|
+
}
|
|
27510
|
+
const scope = parseSkillScope(body["scope"], res);
|
|
27511
|
+
if (!scope) return void 0;
|
|
27512
|
+
const rawSource = body["source"];
|
|
27513
|
+
if (!rawSource || typeof rawSource !== "object" || Array.isArray(rawSource)) {
|
|
27514
|
+
res.status(400).json({
|
|
27515
|
+
error: "`source` is required",
|
|
27516
|
+
code: "invalid_skill_source"
|
|
27517
|
+
});
|
|
27518
|
+
return void 0;
|
|
27519
|
+
}
|
|
27520
|
+
const source = rawSource;
|
|
27521
|
+
if (source["type"] === "github" && typeof source["url"] === "string") {
|
|
27522
|
+
return { name, scope, source: { type: "github", url: source["url"] } };
|
|
27523
|
+
}
|
|
27524
|
+
if (source["type"] === "zip" && typeof source["contentBase64"] === "string") {
|
|
27525
|
+
return {
|
|
27526
|
+
name,
|
|
27527
|
+
scope,
|
|
27528
|
+
source: { type: "zip", contentBase64: source["contentBase64"] }
|
|
27529
|
+
};
|
|
27530
|
+
}
|
|
27531
|
+
if (source["type"] === "folder" && typeof source["path"] === "string") {
|
|
27532
|
+
return {
|
|
27533
|
+
name,
|
|
27534
|
+
scope,
|
|
27535
|
+
source: { type: "folder", path: source["path"] }
|
|
27536
|
+
};
|
|
27537
|
+
}
|
|
27538
|
+
res.status(400).json({
|
|
27539
|
+
error: "Invalid Skill install source",
|
|
27540
|
+
code: "invalid_skill_source"
|
|
27541
|
+
});
|
|
27542
|
+
return void 0;
|
|
27543
|
+
}
|
|
27544
|
+
__name(parseSkillInstallRequest, "parseSkillInstallRequest");
|
|
27545
|
+
function parseDeleteScope(req, res) {
|
|
27546
|
+
return parseSkillScope(req.query["scope"], res);
|
|
27547
|
+
}
|
|
27548
|
+
__name(parseDeleteScope, "parseDeleteScope");
|
|
27549
|
+
function sendSkillManagementError(res, error2) {
|
|
27550
|
+
if (!(error2 instanceof WorkspaceSkillManagementError)) return false;
|
|
27551
|
+
res.status(error2.statusCode).json({
|
|
27552
|
+
error: error2.message,
|
|
27553
|
+
code: error2.code
|
|
27554
|
+
});
|
|
27555
|
+
return true;
|
|
27556
|
+
}
|
|
27557
|
+
__name(sendSkillManagementError, "sendSkillManagementError");
|
|
26074
27558
|
function registerWorkspaceSkillsRoutes(app, deps) {
|
|
26075
27559
|
const buildWorkspaceCtx = createBuildWorkspaceCtx(
|
|
26076
27560
|
deps.workspaceRuntime.workspaceCwd
|
|
26077
27561
|
);
|
|
26078
27562
|
const route = "POST /workspace/skills/:name/enable";
|
|
27563
|
+
app.post(
|
|
27564
|
+
"/workspace/skills/install",
|
|
27565
|
+
deps.mutate({ strict: true }),
|
|
27566
|
+
async (req, res) => {
|
|
27567
|
+
if (!requireTrustedWorkspaceRuntime(deps.workspaceRuntime, res)) return;
|
|
27568
|
+
const input = parseSkillInstallRequest(req, res, deps.safeBody);
|
|
27569
|
+
if (!input) return;
|
|
27570
|
+
const clientId = deps.parseAndValidateClientId(req, res);
|
|
27571
|
+
if (clientId === null) return;
|
|
27572
|
+
const installRoute = "POST /workspace/skills/install";
|
|
27573
|
+
try {
|
|
27574
|
+
const result = await deps.workspaceRuntime.workspaceService.installWorkspaceSkill(
|
|
27575
|
+
buildWorkspaceCtx(installRoute, clientId),
|
|
27576
|
+
input
|
|
27577
|
+
);
|
|
27578
|
+
res.status(200).json(result);
|
|
27579
|
+
} catch (err) {
|
|
27580
|
+
if (!sendSkillManagementError(res, err))
|
|
27581
|
+
deps.sendBridgeError(res, err, { route: installRoute });
|
|
27582
|
+
}
|
|
27583
|
+
}
|
|
27584
|
+
);
|
|
27585
|
+
app.delete(
|
|
27586
|
+
"/workspace/skills/:name",
|
|
27587
|
+
deps.mutate({ strict: true }),
|
|
27588
|
+
async (req, res) => {
|
|
27589
|
+
if (!requireTrustedWorkspaceRuntime(deps.workspaceRuntime, res)) return;
|
|
27590
|
+
const rawSkillName = req.params["name"];
|
|
27591
|
+
const scope = parseDeleteScope(req, res);
|
|
27592
|
+
if (!rawSkillName || !scope) return;
|
|
27593
|
+
let skillName;
|
|
27594
|
+
try {
|
|
27595
|
+
skillName = validateWorkspaceSkillName(rawSkillName);
|
|
27596
|
+
} catch (error2) {
|
|
27597
|
+
sendSkillManagementError(res, error2);
|
|
27598
|
+
return;
|
|
27599
|
+
}
|
|
27600
|
+
const clientId = deps.parseAndValidateClientId(req, res);
|
|
27601
|
+
if (clientId === null) return;
|
|
27602
|
+
const deleteRoute = "DELETE /workspace/skills/:name";
|
|
27603
|
+
try {
|
|
27604
|
+
const result = await deps.workspaceRuntime.workspaceService.deleteWorkspaceSkill(
|
|
27605
|
+
buildWorkspaceCtx(deleteRoute, clientId),
|
|
27606
|
+
skillName,
|
|
27607
|
+
scope
|
|
27608
|
+
);
|
|
27609
|
+
res.status(200).json(result);
|
|
27610
|
+
} catch (err) {
|
|
27611
|
+
if (!sendSkillManagementError(res, err))
|
|
27612
|
+
deps.sendBridgeError(res, err, { route: deleteRoute });
|
|
27613
|
+
}
|
|
27614
|
+
}
|
|
27615
|
+
);
|
|
26079
27616
|
app.post(
|
|
26080
27617
|
"/workspace/skills/:name/enable",
|
|
26081
27618
|
deps.mutate({ strict: true }),
|
|
@@ -26101,6 +27638,77 @@ function registerWorkspaceSkillsRoutes(app, deps) {
|
|
|
26101
27638
|
__name(registerWorkspaceSkillsRoutes, "registerWorkspaceSkillsRoutes");
|
|
26102
27639
|
function registerWorkspaceQualifiedSkillsRoutes(app, deps) {
|
|
26103
27640
|
const route = "POST /workspaces/:workspace/skills/:name/enable";
|
|
27641
|
+
app.post(
|
|
27642
|
+
"/workspaces/:workspace/skills/install",
|
|
27643
|
+
deps.mutate({ strict: true }),
|
|
27644
|
+
async (req, res) => {
|
|
27645
|
+
const runtime = resolveWorkspaceRuntimeFromParam(
|
|
27646
|
+
deps.workspaceRegistry,
|
|
27647
|
+
req,
|
|
27648
|
+
res
|
|
27649
|
+
);
|
|
27650
|
+
if (!runtime || !requireTrustedWorkspaceRuntime(runtime, res)) return;
|
|
27651
|
+
const input = parseSkillInstallRequest(req, res, deps.safeBody);
|
|
27652
|
+
if (!input) return;
|
|
27653
|
+
const clientId = parseAndValidateWorkspaceClientId(
|
|
27654
|
+
req,
|
|
27655
|
+
res,
|
|
27656
|
+
runtime.bridge
|
|
27657
|
+
);
|
|
27658
|
+
if (clientId === null) return;
|
|
27659
|
+
const installRoute = "POST /workspaces/:workspace/skills/install";
|
|
27660
|
+
try {
|
|
27661
|
+
const result = await runtime.workspaceService.installWorkspaceSkill(
|
|
27662
|
+
createBuildWorkspaceCtx(runtime.workspaceCwd)(installRoute, clientId),
|
|
27663
|
+
input
|
|
27664
|
+
);
|
|
27665
|
+
res.status(200).json(result);
|
|
27666
|
+
} catch (err) {
|
|
27667
|
+
if (!sendSkillManagementError(res, err))
|
|
27668
|
+
deps.sendBridgeError(res, err, { route: installRoute });
|
|
27669
|
+
}
|
|
27670
|
+
}
|
|
27671
|
+
);
|
|
27672
|
+
app.delete(
|
|
27673
|
+
"/workspaces/:workspace/skills/:name",
|
|
27674
|
+
deps.mutate({ strict: true }),
|
|
27675
|
+
async (req, res) => {
|
|
27676
|
+
const runtime = resolveWorkspaceRuntimeFromParam(
|
|
27677
|
+
deps.workspaceRegistry,
|
|
27678
|
+
req,
|
|
27679
|
+
res
|
|
27680
|
+
);
|
|
27681
|
+
if (!runtime || !requireTrustedWorkspaceRuntime(runtime, res)) return;
|
|
27682
|
+
const rawSkillName = req.params["name"];
|
|
27683
|
+
const scope = parseDeleteScope(req, res);
|
|
27684
|
+
if (!rawSkillName || !scope) return;
|
|
27685
|
+
let skillName;
|
|
27686
|
+
try {
|
|
27687
|
+
skillName = validateWorkspaceSkillName(rawSkillName);
|
|
27688
|
+
} catch (error2) {
|
|
27689
|
+
sendSkillManagementError(res, error2);
|
|
27690
|
+
return;
|
|
27691
|
+
}
|
|
27692
|
+
const clientId = parseAndValidateWorkspaceClientId(
|
|
27693
|
+
req,
|
|
27694
|
+
res,
|
|
27695
|
+
runtime.bridge
|
|
27696
|
+
);
|
|
27697
|
+
if (clientId === null) return;
|
|
27698
|
+
const deleteRoute = "DELETE /workspaces/:workspace/skills/:name";
|
|
27699
|
+
try {
|
|
27700
|
+
const result = await runtime.workspaceService.deleteWorkspaceSkill(
|
|
27701
|
+
createBuildWorkspaceCtx(runtime.workspaceCwd)(deleteRoute, clientId),
|
|
27702
|
+
skillName,
|
|
27703
|
+
scope
|
|
27704
|
+
);
|
|
27705
|
+
res.status(200).json(result);
|
|
27706
|
+
} catch (err) {
|
|
27707
|
+
if (!sendSkillManagementError(res, err))
|
|
27708
|
+
deps.sendBridgeError(res, err, { route: deleteRoute });
|
|
27709
|
+
}
|
|
27710
|
+
}
|
|
27711
|
+
);
|
|
26104
27712
|
app.post(
|
|
26105
27713
|
"/workspaces/:workspace/skills/:name/enable",
|
|
26106
27714
|
deps.mutate({ strict: true }),
|
|
@@ -26525,6 +28133,12 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
26525
28133
|
boundWorkspace,
|
|
26526
28134
|
persistSettingAvailable: deps.persistSetting !== void 0,
|
|
26527
28135
|
sessionArtifactsPersistenceAvailable: deps.sessionArtifactsPersistenceAvailable !== false,
|
|
28136
|
+
sessionGenerationAvailable: /* @__PURE__ */ __name(() => {
|
|
28137
|
+
const runtimes = workspaceRegistry.list();
|
|
28138
|
+
return runtimes.length > 0 && runtimes.every(
|
|
28139
|
+
(runtime) => runtime.bridge.generateSessionContent !== void 0
|
|
28140
|
+
);
|
|
28141
|
+
}, "sessionGenerationAvailable"),
|
|
26528
28142
|
// Registry injection supplies the primary workspace service through the
|
|
26529
28143
|
// runtime, so it has the same reload surface as legacy deps.workspace.
|
|
26530
28144
|
reloadAvailable: deps.workspace !== void 0 || injectedWorkspaceRegistry !== void 0,
|
|
@@ -26609,6 +28223,7 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
26609
28223
|
primaryEffectiveEnv ? { env: primaryEffectiveEnv } : {}
|
|
26610
28224
|
),
|
|
26611
28225
|
workspaceSkillsStatusProvider: createWorkspaceSkillsStatusProvider(),
|
|
28226
|
+
...primaryEffectiveEnv ? { skillInstallEnv: primaryEffectiveEnv } : {},
|
|
26612
28227
|
...primaryEffectiveEnv ? { voiceEnv: primaryEffectiveEnv } : {},
|
|
26613
28228
|
isChannelLive: /* @__PURE__ */ __name(() => bridge.isChannelLive(), "isChannelLive"),
|
|
26614
28229
|
persistDisabledTools: deps.persistDisabledTools ?? (async () => {
|
|
@@ -26653,6 +28268,8 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
26653
28268
|
);
|
|
26654
28269
|
app.locals.workspaceRegistry = workspaceRegistry;
|
|
26655
28270
|
const primaryRuntime = workspaceRegistry.primary;
|
|
28271
|
+
const daemonEnv = deps.daemonEnv ?? process.env;
|
|
28272
|
+
const primaryRuntimeEffectiveEnv = getRuntimeEffectiveEnv(primaryRuntime.env) ?? daemonEnv;
|
|
26656
28273
|
const voiceCoordinator = deps.voiceCoordinator ?? new WorkspaceVoiceCoordinator();
|
|
26657
28274
|
const primaryBoundWorkspace = primaryRuntime.workspaceCwd;
|
|
26658
28275
|
const primaryBridge = primaryRuntime.bridge;
|
|
@@ -26681,7 +28298,7 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
26681
28298
|
const healthDemoRoutes = createHealthDemoRoutes({
|
|
26682
28299
|
opts,
|
|
26683
28300
|
getPort,
|
|
26684
|
-
|
|
28301
|
+
workspaceRegistry,
|
|
26685
28302
|
getActiveSseCount,
|
|
26686
28303
|
getRateLimiter: /* @__PURE__ */ __name(() => rateLimiter, "getRateLimiter")
|
|
26687
28304
|
});
|
|
@@ -26742,38 +28359,27 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
26742
28359
|
requireAuth: opts.requireAuth === true
|
|
26743
28360
|
});
|
|
26744
28361
|
app.use(
|
|
26745
|
-
daemonTelemetryMiddleware(
|
|
26746
|
-
(
|
|
26747
|
-
|
|
26748
|
-
|
|
26749
|
-
if (rawSelector) {
|
|
26750
|
-
try {
|
|
26751
|
-
const selector = decodeURIComponent(rawSelector);
|
|
26752
|
-
const byId = workspaceRegistry.getByWorkspaceId(selector);
|
|
26753
|
-
if (byId) return byId.workspaceCwd;
|
|
26754
|
-
if (isPortableAbsolutePath(selector)) {
|
|
26755
|
-
const runtime = resolveRegisteredWorkspaceRuntimeByPathSelector(
|
|
26756
|
-
workspaceRegistry,
|
|
26757
|
-
selector
|
|
26758
|
-
);
|
|
26759
|
-
if (runtime) return runtime.workspaceCwd;
|
|
26760
|
-
}
|
|
26761
|
-
} catch {
|
|
26762
|
-
return primaryBoundWorkspace;
|
|
26763
|
-
}
|
|
26764
|
-
}
|
|
26765
|
-
return primaryBoundWorkspace;
|
|
26766
|
-
},
|
|
26767
|
-
deps.recordDaemonRequest,
|
|
26768
|
-
(sessionId) => {
|
|
28362
|
+
daemonTelemetryMiddleware((req) => {
|
|
28363
|
+
const match = req.path.match(/^\/workspaces\/([^/]+)/);
|
|
28364
|
+
const rawSelector = match?.[1];
|
|
28365
|
+
if (rawSelector) {
|
|
26769
28366
|
try {
|
|
26770
|
-
const
|
|
26771
|
-
|
|
28367
|
+
const selector = decodeURIComponent(rawSelector);
|
|
28368
|
+
const byId = workspaceRegistry.getByWorkspaceId(selector);
|
|
28369
|
+
if (byId) return byId.workspaceCwd;
|
|
28370
|
+
if (isPortableAbsolutePath(selector)) {
|
|
28371
|
+
const runtime = resolveRegisteredWorkspaceRuntimeByPathSelector(
|
|
28372
|
+
workspaceRegistry,
|
|
28373
|
+
selector
|
|
28374
|
+
);
|
|
28375
|
+
if (runtime) return runtime.workspaceCwd;
|
|
28376
|
+
}
|
|
26772
28377
|
} catch {
|
|
26773
|
-
return
|
|
28378
|
+
return primaryBoundWorkspace;
|
|
26774
28379
|
}
|
|
26775
28380
|
}
|
|
26776
|
-
|
|
28381
|
+
return primaryBoundWorkspace;
|
|
28382
|
+
}, deps.recordDaemonRequest)
|
|
26777
28383
|
);
|
|
26778
28384
|
const buildWorkspaceCtx = createBuildWorkspaceCtx(primaryBoundWorkspace);
|
|
26779
28385
|
const acpHandleRef = {};
|
|
@@ -26915,6 +28521,7 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
26915
28521
|
registerWorkspaceSetupGithubRoutes(app, {
|
|
26916
28522
|
boundWorkspace: primaryBoundWorkspace,
|
|
26917
28523
|
bridge: primaryBridge,
|
|
28524
|
+
env: primaryRuntimeEffectiveEnv,
|
|
26918
28525
|
mutate,
|
|
26919
28526
|
parseClientId: parseClientIdHeader,
|
|
26920
28527
|
safeBody
|
|
@@ -27211,6 +28818,7 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
27211
28818
|
});
|
|
27212
28819
|
acpHandleRef.current = mountAcpHttp(app, primaryBridge, {
|
|
27213
28820
|
boundWorkspace: primaryBoundWorkspace,
|
|
28821
|
+
daemonEnv,
|
|
27214
28822
|
// Phase 4 (issue #6378): pass the registry so `/workspaces/:workspace/acp`
|
|
27215
28823
|
// mounts a per-runtime ACP dispatcher for each registered workspace.
|
|
27216
28824
|
workspaceRegistry,
|
|
@@ -27282,6 +28890,7 @@ export {
|
|
|
27282
28890
|
createServeApp,
|
|
27283
28891
|
detectFromLoopback,
|
|
27284
28892
|
getActiveSseCount,
|
|
28893
|
+
getWorkspaceSessionInfoForResponse,
|
|
27285
28894
|
listWorkspaceSessionsForResponse,
|
|
27286
28895
|
resolveBoundWorkspacesFromIdeEnv,
|
|
27287
28896
|
resolveBridgeFsFactory,
|