@qwen-code/qwen-code 0.20.1 → 0.20.2-gdpval-vl-bridge.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundled/qc-helper/docs/integration-github-action.md +9 -9
- package/chunks/{MaxSizedBox-4WZYPSRU.js → MaxSizedBox-LJXM44LM.js} +10 -11
- package/chunks/{StandaloneSessionPicker-PE4JAIFA.js → StandaloneSessionPicker-PJL4SUNJ.js} +25 -26
- package/chunks/{acpAgent-BVIKGJ2C.js → acpAgent-QILHBOVE.js} +121 -80
- package/chunks/{agent-DHLFAOUV.js → agent-MITS5NNF.js} +10 -11
- package/chunks/{agent-headless-ZP5WTNXZ.js → agent-headless-CSKMTZYT.js} +10 -11
- package/chunks/{anthropicContentGenerator-NMSS7IMV.js → anthropicContentGenerator-HGWAHO24.js} +6 -8
- package/chunks/{bridge-XAK7JKMD.js → bridge-OTBUREJB.js} +14 -15
- package/chunks/{channel-worker-group-LFBT7K64.js → channel-worker-group-QZV2SP5U.js} +3 -3
- package/chunks/{channel-worker-manager-3RUPERG2.js → channel-worker-manager-3GMAU45H.js} +3 -3
- package/chunks/{channel-worker-supervisor-A3KVATD3.js → channel-worker-supervisor-QCXSXCRY.js} +2 -2
- package/chunks/{chunk-76OFFG6L.js → chunk-2DGTZXPP.js} +1 -1
- package/chunks/{chunk-BWQRDISK.js → chunk-2M6SP3YW.js} +1 -1
- package/chunks/chunk-3Z43GZUQ.js +32 -0
- package/chunks/{chunk-N5ARKAVE.js → chunk-4I7Z3D2K.js} +6 -6
- package/chunks/{chunk-EFIOE2EH.js → chunk-4WI3O5SO.js} +1 -1
- package/chunks/{chunk-27CLX4FV.js → chunk-54ABO2GD.js} +1 -1
- package/chunks/{chunk-BKZEHVPV.js → chunk-5G3ZVADU.js} +148 -47
- package/chunks/{chunk-PIHKWN7M.js → chunk-5IDR6XE4.js} +1 -1
- package/chunks/{chunk-Q3GGJDYN.js → chunk-5VLWDXVW.js} +3 -3
- package/chunks/{chunk-3KQSDUK3.js → chunk-5ZJ76VN7.js} +7 -8
- package/chunks/{chunk-R7MPKABX.js → chunk-6KTYB3BL.js} +70 -36
- package/chunks/{chunk-4DSBFQMI.js → chunk-6KWPAL2Y.js} +2 -2
- package/chunks/{chunk-PSVSP2OS.js → chunk-6PMESZR4.js} +3 -3
- package/chunks/{chunk-TXRKCFWS.js → chunk-7UOLRSUW.js} +1 -1
- package/chunks/{chunk-DRIXALGM.js → chunk-7Z3BQV36.js} +2 -2
- package/chunks/{chunk-KQQ757OQ.js → chunk-ACW3VNUE.js} +1 -1
- package/chunks/{chunk-TPR35HHZ.js → chunk-AIAHTIQX.js} +3 -3
- package/chunks/{chunk-KSZZBDVD.js → chunk-AWRZQTYG.js} +25 -25
- package/chunks/{chunk-PPIHLGNE.js → chunk-B3QY5TAE.js} +1 -1
- package/chunks/{chunk-M7WBGLYP.js → chunk-BULDBTYC.js} +2 -0
- package/chunks/{chunk-JYS55H6Z.js → chunk-CBOQ3HY7.js} +400 -3
- package/chunks/{chunk-6PRNSLMB.js → chunk-CNXESX7W.js} +16 -17
- package/chunks/{chunk-S3YQCNJE.js → chunk-DZDM2LCO.js} +1 -1
- package/chunks/{chunk-JKFHJK5U.js → chunk-ENTIQ7PN.js} +4 -4
- package/chunks/{chunk-7SWFAKVH.js → chunk-ERCSSQY3.js} +10 -10
- package/chunks/{chunk-3LH5Q2AR.js → chunk-EXVVHNPJ.js} +4 -4
- package/chunks/{chunk-JTUAAVUT.js → chunk-FFDPKCID.js} +2 -2
- package/chunks/{chunk-CHXKGIMK.js → chunk-FLLYXUZE.js} +1 -1
- package/chunks/{chunk-X7XWGRDT.js → chunk-GCEE2HJ5.js} +3 -3
- package/chunks/{chunk-7LH6CHKG.js → chunk-GHERLCN5.js} +1 -1
- package/chunks/{chunk-QD6BRERJ.js → chunk-GHRSKGHF.js} +1 -1
- package/chunks/{chunk-5G2SK2OO.js → chunk-IGAR75ZK.js} +192 -105
- package/chunks/{chunk-AZD6KAV7.js → chunk-ISOHMBTV.js} +3 -3
- package/chunks/{chunk-JO7FGOSY.js → chunk-JIK3TDIA.js} +3 -3
- package/chunks/{chunk-EWXXMRMP.js → chunk-JJEBXTZW.js} +2 -2
- package/chunks/{chunk-QUHJRRUA.js → chunk-KCJDKAVN.js} +29 -18
- package/chunks/{chunk-G6LRTI62.js → chunk-KXFNYTHD.js} +4 -4
- package/chunks/{chunk-OUDZVU7H.js → chunk-LCKGROQ7.js} +7 -5
- package/chunks/{chunk-JJEFX6U5.js → chunk-LESHKUWF.js} +2 -4
- package/chunks/{chunk-WCFTQD7H.js → chunk-LX4HOTPK.js} +1 -1
- package/chunks/{chunk-6NHK6HS7.js → chunk-MDZTPSXO.js} +1 -1
- package/chunks/{chunk-MTSYH4MB.js → chunk-MQCQ2RPF.js} +2 -2
- package/chunks/{chunk-R3BCL5XW.js → chunk-NOXG3VV4.js} +3 -3
- package/chunks/{chunk-QSJ6JIF5.js → chunk-OBGWF32G.js} +3 -3
- package/chunks/{chunk-BZAEENUV.js → chunk-PCW6IHMC.js} +2 -2
- package/chunks/{chunk-KDPIV6WC.js → chunk-PFSXIGJ4.js} +1 -1
- package/chunks/{chunk-766HLFAG.js → chunk-QOXNPPAQ.js} +3 -3
- package/chunks/{chunk-GEB2CGUV.js → chunk-QPYT2PMU.js} +1368 -984
- package/chunks/{chunk-IS2SBY6T.js → chunk-RCUEYZDE.js} +36 -2
- package/chunks/{chunk-JIBBZH37.js → chunk-RWAYXN3M.js} +23 -25
- package/chunks/{chunk-5EA5NVXS.js → chunk-RXIGY3Z7.js} +1 -1
- package/chunks/{chunk-NNFK277W.js → chunk-RXXCWIIT.js} +1 -1
- package/chunks/{chunk-SP32MK6J.js → chunk-S5OLFBI4.js} +1 -1
- package/chunks/{chunk-LPMBFOWH.js → chunk-SD4BYEST.js} +33 -33
- package/chunks/{chunk-DPRMI6NU.js → chunk-SJFV5DCS.js} +1 -1
- package/chunks/{chunk-PBED7USE.js → chunk-SJYO564B.js} +1 -1
- package/chunks/{chunk-4BRH6FP5.js → chunk-TQOHIH3J.js} +4 -4
- package/chunks/{chunk-3SXF4GMQ.js → chunk-TSHDJIHT.js} +1 -1
- package/chunks/{chunk-Q2V2ADXF.js → chunk-TZD76DW5.js} +4 -4
- package/chunks/{chunk-7NDXG4MB.js → chunk-VMK4GQ7U.js} +7 -7
- package/chunks/{chunk-52T5UHAZ.js → chunk-VO6WUB5V.js} +1 -1
- package/chunks/{chunk-LYEKAAEH.js → chunk-VV6A6GOJ.js} +3 -3
- package/chunks/{chunk-EC2ET5ZZ.js → chunk-WO7ZDMC3.js} +1 -1
- package/chunks/{chunk-WML6JOGQ.js → chunk-WUK6EDXF.js} +5 -7
- package/chunks/{chunk-JHFVJQRO.js → chunk-XP4OZD4C.js} +1 -1
- package/chunks/{chunk-Y2DAH52F.js → chunk-YLBIIEB3.js} +4 -4
- package/chunks/{chunk-RYSMKY43.js → chunk-Z4CVMZDO.js} +4 -4
- package/chunks/{chunk-D6ZOVZLF.js → chunk-Z4KOWJRT.js} +1 -1
- package/chunks/{chunk-D53NR4GO.js → chunk-ZLEQDVBN.js} +66 -52
- package/chunks/{computer-use-MV4K6WJM.js → computer-use-XH5KVSRK.js} +10 -11
- package/chunks/{config-utils-WYUQ7II4.js → config-utils-FYTBZLCJ.js} +1 -1
- package/chunks/{contextCommand-TQD36VNX.js → contextCommand-TLVGNAYE.js} +12 -13
- package/chunks/{create-sub-session-JOW4BKMC.js → create-sub-session-EJ6CRFF2.js} +10 -11
- package/chunks/{daemon-KLPTQIE4.js → daemon-GJRFILYS.js} +185 -18
- package/chunks/{daemon-status-provider-TII4SMCZ.js → daemon-status-provider-KOO2M6UX.js} +18 -19
- package/chunks/{earlyInputCapture-2V57RG6H.js → earlyInputCapture-XQBXXREG.js} +10 -11
- package/chunks/{edit-TTUH7PWR.js → edit-KYBZLIFH.js} +10 -11
- package/chunks/{enter-worktree-D4IVCXYB.js → enter-worktree-4QGJGFEV.js} +10 -11
- package/chunks/{enterPlanMode-WRUJTVYN.js → enterPlanMode-JVGORNU6.js} +10 -11
- package/chunks/{environment-SEPKXB2C.js → environment-BHBI5AZ6.js} +12 -13
- package/chunks/{errors-YSVGBLBU.js → errors-JEUC6I3K.js} +12 -13
- package/chunks/{exit-worktree-MZ4JSSP6.js → exit-worktree-CWTHMB5Z.js} +10 -11
- package/chunks/{exitPlanMode-HAZLSSOJ.js → exitPlanMode-BBSMHTLY.js} +10 -11
- package/chunks/{fast-path-EVBVIE2U.js → fast-path-TKXQ2N7L.js} +3 -3
- package/chunks/{fast-path-settings-XB3CPUJT.js → fast-path-settings-DAOVFADC.js} +2 -2
- package/chunks/{gemini-APQ76464.js → gemini-TZWFMMSH.js} +53 -54
- package/chunks/{geminiContentGenerator-LB4MA2LI.js → geminiContentGenerator-WWGEJKFB.js} +1 -1
- package/chunks/{glob-LABYMYKG.js → glob-CUK5IVAR.js} +10 -11
- package/chunks/{grep-HKIKJCAS.js → grep-5KK7VUB2.js} +10 -11
- package/chunks/{handleAutoUpdate-RWAAL2UM.js → handleAutoUpdate-7VWATKG6.js} +15 -16
- package/chunks/{i18n-ZUVDAJIJ.js → i18n-S3SUCYS6.js} +11 -12
- package/chunks/{initializer-7YUHIC36.js → initializer-4TGXLN4W.js} +16 -17
- package/chunks/{installationInfo-DVEOMWDE.js → installationInfo-HP345PUE.js} +11 -12
- package/chunks/{list-WHCZSIR2.js → list-Z4B2PADO.js} +19 -20
- package/chunks/{loadedSettingsAdapter-YCWN6AK3.js → loadedSettingsAdapter-HPSBPLTA.js} +16 -17
- package/chunks/{managed-npm-update-PG3463CJ.js → managed-npm-update-MIAA4DVB.js} +11 -12
- package/chunks/{mcp-VLHDCKAN.js → mcp-SRDAT3US.js} +16 -17
- package/chunks/{monitor-GG4F4YM6.js → monitor-WXB5MY4U.js} +10 -11
- package/chunks/{nonInteractiveCli-UYXYV4YX.js → nonInteractiveCli-2GFHBH47.js} +46 -47
- package/chunks/{notebook-edit-US4VLN6Q.js → notebook-edit-A22GKYUC.js} +10 -11
- package/chunks/{openaiContentGenerator-CVEDTMDB.js → openaiContentGenerator-ZQ6CYL4U.js} +7 -8
- package/chunks/{pidfile-QQ45OIOY.js → pidfile-PBV63DT4.js} +10 -11
- package/chunks/{processUtils-3WMHLQE5.js → processUtils-D3F5NRBV.js} +2 -2
- package/chunks/{qwenContentGenerator-Y2GRNYZQ.js → qwenContentGenerator-2N24PNP3.js} +15 -16
- package/chunks/{qwenOAuth2-J2X6E5VO.js → qwenOAuth2-YFFJOT4S.js} +7 -8
- package/chunks/{read-file-C7Z266CU.js → read-file-PJ6S7IGJ.js} +4 -4
- package/chunks/{resumeHistoryUtils-KBQWX77U.js → resumeHistoryUtils-RQUWKOKB.js} +13 -14
- package/chunks/{ripGrep-RW26MTQ3.js → ripGrep-I5FH2I7V.js} +10 -11
- package/chunks/{run-qwen-serve-MXFMOMEL.js → run-qwen-serve-4VHQN3CF.js} +67 -48
- package/chunks/{runtime-APNO3V6D.js → runtime-K4BTMDOK.js} +18 -19
- package/chunks/{scheduler-L6FYCGVO.js → scheduler-YLNOB2ZX.js} +10 -11
- package/chunks/{sdk-exporters-http-IDGLRBGP.js → sdk-exporters-http-6MCQH335.js} +2 -2
- package/chunks/{sdk-impl-5ESZBGJQ.js → sdk-impl-HOLWAXC6.js} +9 -2
- package/chunks/{send-message-PYIJ2PZL.js → send-message-KBO6X4ZS.js} +1 -1
- package/chunks/{serve-6QBXDVWT.js → serve-CNPQK3RE.js} +16 -17
- package/chunks/{server-5TJJEMVQ.js → server-YMIGPXOS.js} +1322 -178
- package/chunks/{session-BWEUHKQB.js → session-ZJHIJ6XL.js} +49 -50
- package/chunks/{settings-O7IUQNRR.js → settings-IJECFRXI.js} +18 -19
- package/chunks/{shell-R5L4NQYY.js → shell-LFSMRD3H.js} +10 -11
- package/chunks/{skill-ITEOSNW6.js → skill-HOUMVQOO.js} +4 -4
- package/chunks/{spawnChannel-E7NTWSGW.js → spawnChannel-H5V2VAS4.js} +12 -13
- package/chunks/{src-FFXGUTNL.js → src-PT66JDFR.js} +45 -33
- package/chunks/{standalone-update-JCJOXW4P.js → standalone-update-BELF5IPT.js} +13 -14
- package/chunks/{startInteractiveUI-IJSBLZFO.js → startInteractiveUI-POZD5EYR.js} +150 -144
- package/chunks/{team-create-OVSZTJZO.js → team-create-IXRXGMLS.js} +10 -11
- package/chunks/{team-plan-approval-SLEVDLT5.js → team-plan-approval-4LIT4KTC.js} +10 -11
- package/chunks/{theme-manager-V6ZQISHM.js → theme-manager-5POAFV4H.js} +10 -11
- package/chunks/{tool-search-KYIF6C6E.js → tool-search-TDETP5WK.js} +4 -4
- package/chunks/{total-session-admission-EU77XTL7.js → total-session-admission-E7DO4SAC.js} +14 -15
- package/chunks/{tree-sitter-4D7QS7F6.js → tree-sitter-L5BFT64K.js} +1 -1
- package/chunks/{tree-sitter-bash-VEJGF5XF.js → tree-sitter-bash-ZKDNQGID.js} +1 -1
- package/chunks/{trustedFolders-DDEF3ADH.js → trustedFolders-TYGSOWS6.js} +11 -12
- package/chunks/{chunk-5I5BM454.js → undici-3FJYTMOF.js} +24 -399
- package/chunks/{chunk-L573Z2QZ.js → undici-PYHBDDPN.js} +1 -5
- package/chunks/{update-relaunch-XEZTDP6K.js → update-relaunch-IWFT5NLP.js} +5 -5
- package/chunks/{updateCheck-KZ5LZ545.js → updateCheck-5EGA5DYR.js} +13 -14
- package/chunks/{useAutoAcceptIndicator-47EZERGQ.js → useAutoAcceptIndicator-SD44HHNK.js} +18 -19
- package/chunks/{validateNonInterActiveAuth-J2DM4LWZ.js → validateNonInterActiveAuth-5NAZUFHP.js} +43 -44
- package/chunks/{version-PN7WYXHP.js → version-ZSU7UBMZ.js} +1 -1
- package/chunks/{web-fetch-WRI5QRFR.js → web-fetch-QGHG72G2.js} +6 -7
- package/chunks/{web-search-2HCXNAVX.js → web-search-F6CEDF53.js} +13 -12
- package/chunks/{workflow-U5XBPGQZ.js → workflow-DWUUO6GZ.js} +11 -12
- package/chunks/{workspace-providers-status-2T54GIJZ.js → workspace-providers-status-XOINT6H3.js} +19 -20
- package/chunks/{workspace-registration-store-F3V4KBIW.js → workspace-registration-store-WMR4IVHM.js} +1 -1
- package/chunks/{workspace-registry-U6QVZ5BU.js → workspace-registry-E3R2OXHI.js} +14 -15
- package/chunks/{workspace-service-734D36QD.js → workspace-service-46DNRBIV.js} +21 -22
- package/chunks/{workspace-skills-status-5ABUKOAQ.js → workspace-skills-status-ENBQGA5A.js} +17 -18
- package/chunks/{write-file-CIH4I4CS.js → write-file-RVSFV5UL.js} +10 -11
- package/cli.js +12 -12
- package/package.json +3 -3
- package/web-shell/assets/{arc-ByltRugA.js → arc-DIQrcXXh.js} +1 -1
- package/web-shell/assets/{architectureDiagram-3BPJPVTR-CCRTto5d.js → architectureDiagram-3BPJPVTR-CbPd-DSw.js} +1 -1
- package/web-shell/assets/{blockDiagram-GPEHLZMM-Jfy36u1L.js → blockDiagram-GPEHLZMM-yzBIVhMX.js} +1 -1
- package/web-shell/assets/{c4Diagram-AAUBKEIU-4d5FfEZ0.js → c4Diagram-AAUBKEIU-B88Swcsu.js} +1 -1
- package/web-shell/assets/channel-BaTMUesZ.js +1 -0
- package/web-shell/assets/{chunk-2J33WTMH-BPwxCEro.js → chunk-2J33WTMH-BbOLo6NX.js} +1 -1
- package/web-shell/assets/{chunk-4BX2VUAB-jY7ZmJWY.js → chunk-4BX2VUAB-Bg6in0r0.js} +1 -1
- package/web-shell/assets/{chunk-55IACEB6-C98HgCsS.js → chunk-55IACEB6-Bv9QRyLI.js} +1 -1
- package/web-shell/assets/{chunk-727SXJPM-cDu-ge-q.js → chunk-727SXJPM-CFokiv61.js} +1 -1
- package/web-shell/assets/{chunk-AQP2D5EJ-BKdJwxXK.js → chunk-AQP2D5EJ-DS2Oxf6L.js} +1 -1
- package/web-shell/assets/{chunk-FMBD7UC4-DnuxqwMu.js → chunk-FMBD7UC4-D2NkHD3B.js} +1 -1
- package/web-shell/assets/{chunk-ND2GUHAM-C4fZNPv0.js → chunk-ND2GUHAM-BsT_UC5B.js} +1 -1
- package/web-shell/assets/{chunk-QZHKN3VN-Cf4XWOmz.js → chunk-QZHKN3VN-tnJo3zln.js} +1 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-CyBPzWud.js +1 -0
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-CyBPzWud.js +1 -0
- package/web-shell/assets/{cose-bilkent-S5V4N54A-C82mFiqj.js → cose-bilkent-S5V4N54A-BTMa6DAZ.js} +1 -1
- package/web-shell/assets/{dagre-BM42HDAG-Df8KACER.js → dagre-BM42HDAG-ujGX7Owg.js} +1 -1
- package/web-shell/assets/{diagram-2AECGRRQ-EzNs7s_2.js → diagram-2AECGRRQ-fU4-dbPa.js} +1 -1
- package/web-shell/assets/{diagram-5GNKFQAL-BRLNvreg.js → diagram-5GNKFQAL-Bdm-TYSA.js} +1 -1
- package/web-shell/assets/{diagram-KO2AKTUF-2HLYHRjC.js → diagram-KO2AKTUF-Bkhz85Z9.js} +1 -1
- package/web-shell/assets/{diagram-LMA3HP47-DeH0NzSp.js → diagram-LMA3HP47-Bzu3q26p.js} +1 -1
- package/web-shell/assets/{diagram-OG6HWLK6-k5Gn47-G.js → diagram-OG6HWLK6-CZrXbG5Q.js} +1 -1
- package/web-shell/assets/{erDiagram-TEJ5UH35-gPHFo79f.js → erDiagram-TEJ5UH35-BjozEAYu.js} +1 -1
- package/web-shell/assets/{flowDiagram-I6XJVG4X-DYBOiTRW.js → flowDiagram-I6XJVG4X-B3a2I8c-.js} +1 -1
- package/web-shell/assets/{ganttDiagram-6RSMTGT7-cxjAuic9.js → ganttDiagram-6RSMTGT7-CIMn9fNm.js} +1 -1
- package/web-shell/assets/{gitGraphDiagram-PVQCEYII-3nPqpmCP.js → gitGraphDiagram-PVQCEYII-DlFy9KRx.js} +1 -1
- package/web-shell/assets/{index-Cl8d-1bK.js → index-BODUAzQA.js} +1 -1
- package/web-shell/assets/index-C54DNMF7.js +1209 -0
- package/web-shell/assets/index-lWqBfc78.css +5 -0
- package/web-shell/assets/{infoDiagram-5YYISTIA-Dph21pR5.js → infoDiagram-5YYISTIA-BmKjQgCy.js} +1 -1
- package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-Cjg1hSaG.js → ishikawaDiagram-YF4QCWOH-BrQEMZz2.js} +1 -1
- package/web-shell/assets/{journeyDiagram-JHISSGLW-CR-IzvnU.js → journeyDiagram-JHISSGLW-D-2r7Xrt.js} +1 -1
- package/web-shell/assets/{kanban-definition-UN3LZRKU-BYmuybuC.js → kanban-definition-UN3LZRKU-CndsFHCX.js} +1 -1
- package/web-shell/assets/{linear-CngEEoy8.js → linear-D-IwNnKx.js} +1 -1
- package/web-shell/assets/{mermaid.core-G6fbZRPf.js → mermaid.core-4ll09sri.js} +5 -5
- package/web-shell/assets/{mindmap-definition-RKZ34NQL-BtnqnUwJ.js → mindmap-definition-RKZ34NQL-maMRIxjo.js} +1 -1
- package/web-shell/assets/{pieDiagram-4H26LBE5-XTq6UHIA.js → pieDiagram-4H26LBE5-aunUDhrJ.js} +1 -1
- package/web-shell/assets/{quadrantDiagram-W4KKPZXB-D1J5PrsS.js → quadrantDiagram-W4KKPZXB-D3K0P1NZ.js} +1 -1
- package/web-shell/assets/{requirementDiagram-4Y6WPE33-CLcBUy3t.js → requirementDiagram-4Y6WPE33-CX2X9HRc.js} +1 -1
- package/web-shell/assets/{sankeyDiagram-5OEKKPKP-iwKV02_6.js → sankeyDiagram-5OEKKPKP-CDroWk7l.js} +1 -1
- package/web-shell/assets/{sequenceDiagram-3UESZ5HK-7NFYQcEX.js → sequenceDiagram-3UESZ5HK-DTk-2b16.js} +1 -1
- package/web-shell/assets/{stateDiagram-AJRCARHV-Bvm4Wih6.js → stateDiagram-AJRCARHV-Cud64hQr.js} +1 -1
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-g-uUpecT.js +1 -0
- package/web-shell/assets/{timeline-definition-PNZ67QCA-B4FZFE9O.js → timeline-definition-PNZ67QCA-DfD5okf_.js} +1 -1
- package/web-shell/assets/{vennDiagram-CIIHVFJN-CvMBpmtL.js → vennDiagram-CIIHVFJN-BYl8ay25.js} +1 -1
- package/web-shell/assets/{wardley-L42UT6IY-E3ag2327.js → wardley-L42UT6IY-BZFAt10J.js} +1 -1
- package/web-shell/assets/{wardleyDiagram-YWT4CUSO-BEXWlgxC.js → wardleyDiagram-YWT4CUSO-BIWn0GA7.js} +1 -1
- package/web-shell/assets/{xychartDiagram-2RQKCTM6-CICK05gI.js → xychartDiagram-2RQKCTM6-1_H4xblT.js} +1 -1
- package/web-shell/index.html +2 -2
- package/web-shell/assets/channel-4N2UIFcG.js +0 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-Q4dYOtsh.js +0 -1
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-Q4dYOtsh.js +0 -1
- package/web-shell/assets/index-B7jzUZ_s.css +0 -5
- package/web-shell/assets/index-gE8OWwj_.js +0 -1197
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-xXU_zO2Z.js +0 -1
- package/chunks/{chunk-D7WXIW7H.js → chunk-H24SOJIQ.js} +3 -3
- package/chunks/{chunk-QZJY47IE.js → chunk-PEJWA3QQ.js} +5 -5
- package/chunks/{dist-HMU6CYS4.js → dist-XBJVSWS2.js} +1 -1
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
shouldSuppressRememberErrorDetails,
|
|
15
15
|
workspaceMemoryFailureCode,
|
|
16
16
|
workspaceMemoryFailureDiagnostics
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-6KWPAL2Y.js";
|
|
18
18
|
import {
|
|
19
19
|
openQwenAsrRealtimeStream,
|
|
20
20
|
openVoiceStream,
|
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
import {
|
|
24
24
|
SetupGithubError,
|
|
25
25
|
collectSessionData,
|
|
26
|
+
createTranscriptMessageUpdate,
|
|
26
27
|
generateExportFilename,
|
|
27
28
|
normalizeSessionData,
|
|
28
29
|
setupGithub,
|
|
@@ -30,17 +31,21 @@ import {
|
|
|
30
31
|
toJson,
|
|
31
32
|
toJsonl,
|
|
32
33
|
toMarkdown
|
|
33
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-CNXESX7W.js";
|
|
34
35
|
import {
|
|
35
36
|
OBSERVED_CONTACT_MAX_FRESH_WITHIN_SECONDS,
|
|
36
37
|
ObservedChannelContactStore
|
|
37
38
|
} from "./chunk-4K7VDKAD.js";
|
|
39
|
+
import "./chunk-RXXCWIIT.js";
|
|
38
40
|
import "./chunk-RS7MT2QG.js";
|
|
39
|
-
import "./chunk-NNFK277W.js";
|
|
40
41
|
import "./chunk-H2XVO6NE.js";
|
|
41
42
|
import "./chunk-QHTIBUWB.js";
|
|
42
43
|
import "./chunk-QTERJVPZ.js";
|
|
43
|
-
import "./chunk-
|
|
44
|
+
import "./chunk-3Z43GZUQ.js";
|
|
45
|
+
import {
|
|
46
|
+
createSingleWorkspaceRegistry,
|
|
47
|
+
createWorkspaceSessionOwnerIndex
|
|
48
|
+
} from "./chunk-UGYMA4EI.js";
|
|
44
49
|
import {
|
|
45
50
|
CAPABILITIES_SCHEMA_VERSION,
|
|
46
51
|
CLIENT_ID_HEADER,
|
|
@@ -65,6 +70,7 @@ import {
|
|
|
65
70
|
createBridgeFileSystemAdapter,
|
|
66
71
|
createBuildWorkspaceCtx,
|
|
67
72
|
createClientMcpServerProvider,
|
|
73
|
+
createManagedScratchDirectory,
|
|
68
74
|
createMutationGate,
|
|
69
75
|
createRateLimiter,
|
|
70
76
|
denyBrowserOriginCors,
|
|
@@ -76,6 +82,7 @@ import {
|
|
|
76
82
|
installAccessLogMiddleware,
|
|
77
83
|
isBrowserAutomationMcpAvailable,
|
|
78
84
|
isDeepHealthQuery,
|
|
85
|
+
isScratchRootCompatible,
|
|
79
86
|
parseAllowOriginPatterns,
|
|
80
87
|
parseAndValidateWorkspaceClientId,
|
|
81
88
|
parseClientIdHeader,
|
|
@@ -96,29 +103,29 @@ import {
|
|
|
96
103
|
setRateLimiter,
|
|
97
104
|
unsafeRevealSecret,
|
|
98
105
|
validateMcpRuntimeServerName
|
|
99
|
-
} from "./chunk-
|
|
106
|
+
} from "./chunk-5G3ZVADU.js";
|
|
100
107
|
import {
|
|
101
108
|
isLoopbackBind
|
|
102
109
|
} from "./chunk-RXFQM6FQ.js";
|
|
103
110
|
import {
|
|
104
111
|
createDaemonStatusProvider
|
|
105
|
-
} from "./chunk-
|
|
112
|
+
} from "./chunk-Z4CVMZDO.js";
|
|
106
113
|
import "./chunk-LXXMOYPL.js";
|
|
107
|
-
import "./chunk-
|
|
114
|
+
import "./chunk-OBGWF32G.js";
|
|
108
115
|
import "./chunk-E5Z2AVNV.js";
|
|
109
116
|
import {
|
|
110
117
|
createWorkspaceProvidersStatusProvider
|
|
111
|
-
} from "./chunk-
|
|
118
|
+
} from "./chunk-4I7Z3D2K.js";
|
|
112
119
|
import {
|
|
113
120
|
getAuthTypeFromEnv,
|
|
114
121
|
resolveCliGenerationConfig
|
|
115
|
-
} from "./chunk-
|
|
122
|
+
} from "./chunk-AIAHTIQX.js";
|
|
116
123
|
import {
|
|
117
124
|
snapshotProcessEnv
|
|
118
|
-
} from "./chunk-
|
|
125
|
+
} from "./chunk-7Z3BQV36.js";
|
|
119
126
|
import {
|
|
120
127
|
createWorkspaceSkillsStatusProvider
|
|
121
|
-
} from "./chunk-
|
|
128
|
+
} from "./chunk-ISOHMBTV.js";
|
|
122
129
|
import "./chunk-2W3OOD4W.js";
|
|
123
130
|
import {
|
|
124
131
|
EMPTY_WORKSPACE_VOICE_UPDATE_ERROR,
|
|
@@ -133,14 +140,14 @@ import {
|
|
|
133
140
|
validateWorkspaceSkillName,
|
|
134
141
|
validateWorkspaceVoiceState,
|
|
135
142
|
voiceSettingsScopeToWire
|
|
136
|
-
} from "./chunk-
|
|
143
|
+
} from "./chunk-VMK4GQ7U.js";
|
|
137
144
|
import {
|
|
138
145
|
PermissionRulesValidationError,
|
|
139
146
|
buildPermissionSettings,
|
|
140
147
|
isPermissionRuleType,
|
|
141
148
|
normalizePermissionRules,
|
|
142
149
|
readPermissionRuleSet
|
|
143
|
-
} from "./chunk-
|
|
150
|
+
} from "./chunk-RXIGY3Z7.js";
|
|
144
151
|
import {
|
|
145
152
|
assertVoiceBaseUrlNetworkAllowed,
|
|
146
153
|
isStreamingVoiceModel,
|
|
@@ -148,12 +155,12 @@ import {
|
|
|
148
155
|
resolveVoiceTranscriptionConfig,
|
|
149
156
|
sanitizeVoiceErrorMessage,
|
|
150
157
|
transcribeVoiceAudio
|
|
151
|
-
} from "./chunk-
|
|
158
|
+
} from "./chunk-4WI3O5SO.js";
|
|
152
159
|
import {
|
|
153
160
|
isVoiceEnabled,
|
|
154
161
|
isVoiceMode,
|
|
155
162
|
readVoiceModel
|
|
156
|
-
} from "./chunk-
|
|
163
|
+
} from "./chunk-TSHDJIHT.js";
|
|
157
164
|
import "./chunk-QLJUC7TG.js";
|
|
158
165
|
import {
|
|
159
166
|
WorkspacePermissionRulesSessionRequiredError,
|
|
@@ -164,30 +171,16 @@ import {
|
|
|
164
171
|
import {
|
|
165
172
|
createTotalSessionAdmissionController
|
|
166
173
|
} from "./chunk-VYPFXUCB.js";
|
|
167
|
-
import {
|
|
168
|
-
createSingleWorkspaceRegistry,
|
|
169
|
-
createWorkspaceSessionOwnerIndex
|
|
170
|
-
} from "./chunk-UGYMA4EI.js";
|
|
171
174
|
import "./chunk-GRC5HGPI.js";
|
|
172
|
-
import {
|
|
173
|
-
daemonObservedContactsPath,
|
|
174
|
-
loadChannelsConfig
|
|
175
|
-
} from "./chunk-4BRH6FP5.js";
|
|
176
|
-
import "./chunk-G6LRTI62.js";
|
|
177
|
-
import "./chunk-57OAHC2Y.js";
|
|
178
|
-
import {
|
|
179
|
-
parseChannelWebhookConfigLenient
|
|
180
|
-
} from "./chunk-QD6BRERJ.js";
|
|
181
|
-
import "./chunk-6ZBPS62S.js";
|
|
182
|
-
import "./chunk-V6WHFGST.js";
|
|
183
175
|
import {
|
|
184
176
|
SessionArtifactAuthorizationError,
|
|
185
177
|
SessionArtifactValidationError,
|
|
186
178
|
createAcpSessionBridge,
|
|
187
179
|
parseSessionSource
|
|
188
|
-
} from "./chunk-
|
|
180
|
+
} from "./chunk-6KTYB3BL.js";
|
|
189
181
|
import {
|
|
190
182
|
EVENT_SCHEMA_VERSION,
|
|
183
|
+
EventBus,
|
|
191
184
|
SubscriberLimitExceededError
|
|
192
185
|
} from "./chunk-6RLROE6G.js";
|
|
193
186
|
import "./chunk-COH43MRJ.js";
|
|
@@ -225,12 +218,38 @@ import {
|
|
|
225
218
|
WorkspaceInitSymlinkError,
|
|
226
219
|
WorkspaceMismatchError
|
|
227
220
|
} from "./chunk-UH3WSE5L.js";
|
|
228
|
-
import "./chunk-
|
|
221
|
+
import "./chunk-WBL3FJEU.js";
|
|
222
|
+
import {
|
|
223
|
+
daemonObservedContactsPath,
|
|
224
|
+
loadChannelsConfig
|
|
225
|
+
} from "./chunk-TQOHIH3J.js";
|
|
226
|
+
import "./chunk-KXFNYTHD.js";
|
|
227
|
+
import "./chunk-57OAHC2Y.js";
|
|
228
|
+
import {
|
|
229
|
+
parseChannelWebhookConfigLenient
|
|
230
|
+
} from "./chunk-GHRSKGHF.js";
|
|
231
|
+
import "./chunk-6ZBPS62S.js";
|
|
232
|
+
import "./chunk-V6WHFGST.js";
|
|
233
|
+
import "./chunk-XP4OZD4C.js";
|
|
229
234
|
import {
|
|
230
235
|
STATUS_SCHEMA_VERSION,
|
|
231
236
|
createIdleWorkspaceMemoryStatus,
|
|
232
237
|
mapDomainErrorToErrorKind
|
|
233
|
-
} from "./chunk-
|
|
238
|
+
} from "./chunk-2M6SP3YW.js";
|
|
239
|
+
import {
|
|
240
|
+
MAX_REGISTERED_WORKSPACES,
|
|
241
|
+
WorkspaceDisplayNameValidationError,
|
|
242
|
+
WorkspaceRegistrationStoreCommittedError,
|
|
243
|
+
WorkspaceRegistrationStoreLimitError,
|
|
244
|
+
normalizeWorkspaceDisplayName,
|
|
245
|
+
workspaceRegistrationId
|
|
246
|
+
} from "./chunk-2DGTZXPP.js";
|
|
247
|
+
import {
|
|
248
|
+
MAX_WORKSPACE_PATH_LENGTH,
|
|
249
|
+
canonicalizeWorkspace,
|
|
250
|
+
canonicalizeWorkspaces,
|
|
251
|
+
translateAndCheckAbsoluteWorkspacePath
|
|
252
|
+
} from "./chunk-2RFKHEXL.js";
|
|
234
253
|
import {
|
|
235
254
|
MAX_CHANNEL_STARTUP_FAILURES,
|
|
236
255
|
MAX_CHANNEL_STARTUP_FAILURE_CHANNEL_LENGTH,
|
|
@@ -246,7 +265,7 @@ import {
|
|
|
246
265
|
import {
|
|
247
266
|
redactLogCredentials
|
|
248
267
|
} from "./chunk-M5GB774H.js";
|
|
249
|
-
import "./chunk-
|
|
268
|
+
import "./chunk-5HBA2Z7V.js";
|
|
250
269
|
import "./chunk-T2NCM2ET.js";
|
|
251
270
|
import {
|
|
252
271
|
sanitizeLogText
|
|
@@ -261,38 +280,23 @@ import {
|
|
|
261
280
|
getWritableScopes,
|
|
262
281
|
loadSettings,
|
|
263
282
|
validateSettingValue
|
|
264
|
-
} from "./chunk-
|
|
283
|
+
} from "./chunk-ERCSSQY3.js";
|
|
265
284
|
import "./chunk-RKUWKYED.js";
|
|
266
285
|
import {
|
|
267
286
|
SUPPORTED_LANGUAGES,
|
|
268
287
|
detectSystemLanguage,
|
|
269
288
|
resolveLanguageSetting,
|
|
270
289
|
resolveSupportedLanguage
|
|
271
|
-
} from "./chunk-
|
|
272
|
-
import "./chunk-
|
|
290
|
+
} from "./chunk-LX4HOTPK.js";
|
|
291
|
+
import "./chunk-VO6WUB5V.js";
|
|
273
292
|
import "./chunk-GOXKNSDZ.js";
|
|
274
|
-
import "./chunk-QRUIS3DN.js";
|
|
275
|
-
import {
|
|
276
|
-
MAX_REGISTERED_WORKSPACES,
|
|
277
|
-
WorkspaceDisplayNameValidationError,
|
|
278
|
-
WorkspaceRegistrationStoreCommittedError,
|
|
279
|
-
WorkspaceRegistrationStoreLimitError,
|
|
280
|
-
normalizeWorkspaceDisplayName,
|
|
281
|
-
workspaceRegistrationId
|
|
282
|
-
} from "./chunk-76OFFG6L.js";
|
|
283
|
-
import {
|
|
284
|
-
MAX_WORKSPACE_PATH_LENGTH,
|
|
285
|
-
canonicalizeWorkspace,
|
|
286
|
-
canonicalizeWorkspaces,
|
|
287
|
-
translateAndCheckAbsoluteWorkspacePath
|
|
288
|
-
} from "./chunk-2RFKHEXL.js";
|
|
289
|
-
import "./chunk-5HBA2Z7V.js";
|
|
290
293
|
import "./chunk-IDS7MSUP.js";
|
|
291
|
-
import "./chunk-
|
|
294
|
+
import "./chunk-QRUIS3DN.js";
|
|
295
|
+
import "./chunk-54ABO2GD.js";
|
|
292
296
|
import "./chunk-VJNBRRZG.js";
|
|
293
297
|
import {
|
|
294
298
|
getWorkspaceTrustStatus
|
|
295
|
-
} from "./chunk-
|
|
299
|
+
} from "./chunk-DZDM2LCO.js";
|
|
296
300
|
import "./chunk-ALGGS7UH.js";
|
|
297
301
|
import {
|
|
298
302
|
isWithinRoot as isWithinRoot2
|
|
@@ -343,10 +347,12 @@ import {
|
|
|
343
347
|
fetchGitDiffHunksForFile,
|
|
344
348
|
fetchGitLog,
|
|
345
349
|
getGitWorkingTreeStatus,
|
|
350
|
+
getSubagentSessionDir,
|
|
346
351
|
glob,
|
|
347
352
|
loadIgnoreRules,
|
|
348
353
|
loadUsageHistoryWithLive,
|
|
349
354
|
parseInstallSource,
|
|
355
|
+
readAgentMeta,
|
|
350
356
|
readWorktreeSession,
|
|
351
357
|
redactUrlCredentials,
|
|
352
358
|
resolveBranchName,
|
|
@@ -358,7 +364,7 @@ import {
|
|
|
358
364
|
writeWorkspaceContextFile,
|
|
359
365
|
writeWorktreeSession,
|
|
360
366
|
writeWorktreeSessionMarker
|
|
361
|
-
} from "./chunk-
|
|
367
|
+
} from "./chunk-QPYT2PMU.js";
|
|
362
368
|
import "./chunk-T4TZQJ7W.js";
|
|
363
369
|
import "./chunk-H6XPXXMH.js";
|
|
364
370
|
import "./chunk-5M6IDOMF.js";
|
|
@@ -366,6 +372,7 @@ import "./chunk-T2L47JJK.js";
|
|
|
366
372
|
import "./chunk-GPSKDNEE.js";
|
|
367
373
|
import "./chunk-X6N25LXS.js";
|
|
368
374
|
import "./chunk-E2UVIFI2.js";
|
|
375
|
+
import "./chunk-5IDR6XE4.js";
|
|
369
376
|
import {
|
|
370
377
|
MAX_JOBS,
|
|
371
378
|
nextDurableFireMs
|
|
@@ -385,7 +392,6 @@ import {
|
|
|
385
392
|
} from "./chunk-KHOVYUHX.js";
|
|
386
393
|
import "./chunk-SZRN75WQ.js";
|
|
387
394
|
import "./chunk-6PVPNMXU.js";
|
|
388
|
-
import "./chunk-PIHKWN7M.js";
|
|
389
395
|
import "./chunk-CPBF7KYF.js";
|
|
390
396
|
import "./chunk-NABLFI57.js";
|
|
391
397
|
import "./chunk-QBUDF33N.js";
|
|
@@ -399,10 +405,6 @@ import "./chunk-6AM5D4ME.js";
|
|
|
399
405
|
import "./chunk-JCW2R7WC.js";
|
|
400
406
|
import "./chunk-57FIIFJN.js";
|
|
401
407
|
import "./chunk-HTO4JFDZ.js";
|
|
402
|
-
import "./chunk-XVNQMZ2I.js";
|
|
403
|
-
import "./chunk-CR3C7WXL.js";
|
|
404
|
-
import "./chunk-FODK6UMO.js";
|
|
405
|
-
import "./chunk-GLNBDYUX.js";
|
|
406
408
|
import {
|
|
407
409
|
QwenOAuth2Client,
|
|
408
410
|
QwenOAuthPollError,
|
|
@@ -411,12 +413,15 @@ import {
|
|
|
411
413
|
isDeviceAuthorizationSuccess,
|
|
412
414
|
isDeviceTokenPending,
|
|
413
415
|
isDeviceTokenSuccess
|
|
414
|
-
} from "./chunk-
|
|
416
|
+
} from "./chunk-7UOLRSUW.js";
|
|
415
417
|
import "./chunk-JESCGQM3.js";
|
|
416
|
-
import "./chunk-
|
|
417
|
-
import "./chunk-
|
|
418
|
+
import "./chunk-JJEBXTZW.js";
|
|
419
|
+
import "./chunk-B3QY5TAE.js";
|
|
420
|
+
import "./chunk-XVNQMZ2I.js";
|
|
421
|
+
import "./chunk-CR3C7WXL.js";
|
|
422
|
+
import "./chunk-FODK6UMO.js";
|
|
423
|
+
import "./chunk-GLNBDYUX.js";
|
|
418
424
|
import "./chunk-DJ2GSRLV.js";
|
|
419
|
-
import "./chunk-5I5BM454.js";
|
|
420
425
|
import {
|
|
421
426
|
addDaemonRequestAttribute,
|
|
422
427
|
decodeBufferWithEncodingInfo,
|
|
@@ -425,15 +430,17 @@ import {
|
|
|
425
430
|
hashDaemonWorkspace,
|
|
426
431
|
isBinaryFile,
|
|
427
432
|
isWithinRoot,
|
|
433
|
+
parseLineTolerant,
|
|
434
|
+
read,
|
|
428
435
|
recordDaemonBridgeError,
|
|
429
436
|
recordDaemonError,
|
|
430
437
|
recordDaemonHttpRequest,
|
|
431
438
|
recordDaemonHttpResponse,
|
|
432
439
|
withDaemonRequestSpan
|
|
433
|
-
} from "./chunk-
|
|
440
|
+
} from "./chunk-IGAR75ZK.js";
|
|
434
441
|
import "./chunk-VGC4I5JJ.js";
|
|
435
442
|
import "./chunk-4K56OJFJ.js";
|
|
436
|
-
import "./chunk-
|
|
443
|
+
import "./chunk-CBOQ3HY7.js";
|
|
437
444
|
import "./chunk-A4UCTEB5.js";
|
|
438
445
|
import "./chunk-XWRJCPHC.js";
|
|
439
446
|
import "./chunk-QNLNLENL.js";
|
|
@@ -443,9 +450,9 @@ import {
|
|
|
443
450
|
import_websocket_server
|
|
444
451
|
} from "./chunk-TYAMGABM.js";
|
|
445
452
|
import "./chunk-FCMNKVXT.js";
|
|
446
|
-
import "./chunk-
|
|
453
|
+
import "./chunk-RCUEYZDE.js";
|
|
447
454
|
import "./chunk-HTR4WV6U.js";
|
|
448
|
-
import "./chunk-
|
|
455
|
+
import "./chunk-BULDBTYC.js";
|
|
449
456
|
import "./chunk-U7ZFW55U.js";
|
|
450
457
|
import "./chunk-NPQDJGKU.js";
|
|
451
458
|
import "./chunk-YM3SZTH4.js";
|
|
@@ -650,9 +657,9 @@ async function findExistingAncestor(absolute) {
|
|
|
650
657
|
let current = absolute;
|
|
651
658
|
const tailParts = [];
|
|
652
659
|
for (let i = 0; i < MAX_ANCESTOR_HOPS; i++) {
|
|
653
|
-
let
|
|
660
|
+
let stat3 = null;
|
|
654
661
|
try {
|
|
655
|
-
|
|
662
|
+
stat3 = await fsp.stat(current);
|
|
656
663
|
} catch (err) {
|
|
657
664
|
const code = err?.code;
|
|
658
665
|
if (code === "ENOENT" || code === "ENOTDIR") {
|
|
@@ -660,8 +667,8 @@ async function findExistingAncestor(absolute) {
|
|
|
660
667
|
throw err;
|
|
661
668
|
}
|
|
662
669
|
}
|
|
663
|
-
if (
|
|
664
|
-
if (tailParts.length > 0 && !
|
|
670
|
+
if (stat3) {
|
|
671
|
+
if (tailParts.length > 0 && !stat3.isDirectory()) {
|
|
665
672
|
throw new FsError(
|
|
666
673
|
"parse_error",
|
|
667
674
|
`path component is not a directory: ${absolute}`,
|
|
@@ -734,7 +741,7 @@ async function resolveWithinWorkspace(input, boundWorkspaces, intent) {
|
|
|
734
741
|
boundCanonicals
|
|
735
742
|
);
|
|
736
743
|
if (boundCanonical !== void 0) {
|
|
737
|
-
const finalPathIsSymlink = await fsp.lstat(absolute).then((
|
|
744
|
+
const finalPathIsSymlink = await fsp.lstat(absolute).then((stat3) => stat3.isSymbolicLink()).catch((lstatErr) => {
|
|
738
745
|
if (lstatErr.code === "ENOENT" || lstatErr.code === "ENOTDIR") {
|
|
739
746
|
return false;
|
|
740
747
|
}
|
|
@@ -1225,8 +1232,8 @@ var WorkspaceFileSystemImpl = class {
|
|
|
1225
1232
|
const toRead = Math.min(maxBytes, available);
|
|
1226
1233
|
buf = Buffer.allocUnsafe(toRead);
|
|
1227
1234
|
if (toRead > 0) {
|
|
1228
|
-
const
|
|
1229
|
-
buf =
|
|
1235
|
+
const read2 = await fh.read(buf, 0, toRead, offset);
|
|
1236
|
+
buf = read2.bytesRead === toRead ? buf : buf.subarray(0, read2.bytesRead);
|
|
1230
1237
|
}
|
|
1231
1238
|
const afterRead = await fh.stat();
|
|
1232
1239
|
assertSameFile(st, afterRead, p, "read");
|
|
@@ -1767,17 +1774,17 @@ var WorkspaceFileSystemImpl = class {
|
|
|
1767
1774
|
* for their `sendFsError` serializer.
|
|
1768
1775
|
*/
|
|
1769
1776
|
recordAndWrap(err, intent, input) {
|
|
1770
|
-
const
|
|
1777
|
+
const fs6 = wrapAsFsError(err);
|
|
1771
1778
|
this.deps.audit.recordDenied(this.deps.ctx, {
|
|
1772
1779
|
intent,
|
|
1773
1780
|
input,
|
|
1774
|
-
errorKind:
|
|
1775
|
-
hint:
|
|
1781
|
+
errorKind: fs6.kind,
|
|
1782
|
+
hint: fs6.hint,
|
|
1776
1783
|
// Quote the underlying OS / FsError message so audit
|
|
1777
1784
|
// consumers debugging a production incident can see the
|
|
1778
1785
|
// actual cause (errno text, byte counts, glob pattern,
|
|
1779
1786
|
// etc.) rather than just `errorKind` + `hint`.
|
|
1780
|
-
message:
|
|
1787
|
+
message: fs6.message,
|
|
1781
1788
|
// For glob denials (parse_error pattern rejection,
|
|
1782
1789
|
// catastrophic walk failures) the input IS the pattern
|
|
1783
1790
|
// already; surfacing it on the dedicated `pattern` field
|
|
@@ -1786,7 +1793,7 @@ var WorkspaceFileSystemImpl = class {
|
|
|
1786
1793
|
// branching on intent.
|
|
1787
1794
|
pattern: intent === "glob" ? input : void 0
|
|
1788
1795
|
});
|
|
1789
|
-
return
|
|
1796
|
+
return fs6;
|
|
1790
1797
|
}
|
|
1791
1798
|
};
|
|
1792
1799
|
var CONTENT_HASH_RE = /^sha256:[0-9a-f]{64}$/;
|
|
@@ -1894,9 +1901,9 @@ async function readStableRegularFileBuffer(p, pre) {
|
|
|
1894
1901
|
const out = Buffer.alloc(opened.size);
|
|
1895
1902
|
let offset = 0;
|
|
1896
1903
|
while (offset < opened.size) {
|
|
1897
|
-
const
|
|
1898
|
-
if (
|
|
1899
|
-
offset +=
|
|
1904
|
+
const read2 = await fh.read(out, offset, opened.size - offset, offset);
|
|
1905
|
+
if (read2.bytesRead === 0) break;
|
|
1906
|
+
offset += read2.bytesRead;
|
|
1900
1907
|
}
|
|
1901
1908
|
const afterRead = await fh.stat();
|
|
1902
1909
|
assertSameFile(opened, afterRead, p, "read");
|
|
@@ -2151,15 +2158,15 @@ async function hashRegularFileAtPath(p, pre) {
|
|
|
2151
2158
|
const buf = Buffer.allocUnsafe(64 * 1024);
|
|
2152
2159
|
let offset = 0;
|
|
2153
2160
|
while (offset < opened.size) {
|
|
2154
|
-
const
|
|
2161
|
+
const read2 = await fh.read(
|
|
2155
2162
|
buf,
|
|
2156
2163
|
0,
|
|
2157
2164
|
Math.min(buf.length, opened.size - offset),
|
|
2158
2165
|
offset
|
|
2159
2166
|
);
|
|
2160
|
-
if (
|
|
2161
|
-
hash.update(buf.subarray(0,
|
|
2162
|
-
offset +=
|
|
2167
|
+
if (read2.bytesRead === 0) break;
|
|
2168
|
+
hash.update(buf.subarray(0, read2.bytesRead));
|
|
2169
|
+
offset += read2.bytesRead;
|
|
2163
2170
|
}
|
|
2164
2171
|
} finally {
|
|
2165
2172
|
await fh.close();
|
|
@@ -2523,12 +2530,12 @@ __name(applyReadHeaders, "applyReadHeaders");
|
|
|
2523
2530
|
function sendFsError(res, err, route) {
|
|
2524
2531
|
applyReadHeaders(res);
|
|
2525
2532
|
if (isFsError(err)) {
|
|
2526
|
-
const
|
|
2527
|
-
res.status(
|
|
2528
|
-
errorKind:
|
|
2529
|
-
error:
|
|
2530
|
-
hint:
|
|
2531
|
-
status:
|
|
2533
|
+
const fs6 = err;
|
|
2534
|
+
res.status(fs6.status).json({
|
|
2535
|
+
errorKind: fs6.kind,
|
|
2536
|
+
error: fs6.message,
|
|
2537
|
+
hint: fs6.hint,
|
|
2538
|
+
status: fs6.status
|
|
2532
2539
|
});
|
|
2533
2540
|
return;
|
|
2534
2541
|
}
|
|
@@ -2630,13 +2637,13 @@ async function handleGetFile(req, res, deps) {
|
|
|
2630
2637
|
});
|
|
2631
2638
|
return;
|
|
2632
2639
|
}
|
|
2633
|
-
const
|
|
2640
|
+
const fs6 = factory.forRequest({
|
|
2634
2641
|
originatorClientId: clientId ?? void 0,
|
|
2635
2642
|
route: ROUTE2
|
|
2636
2643
|
});
|
|
2637
2644
|
try {
|
|
2638
|
-
const resolved = await
|
|
2639
|
-
const out = await
|
|
2645
|
+
const resolved = await fs6.resolve(queryPath, "read");
|
|
2646
|
+
const out = await fs6.readText(resolved, { maxBytes, line, limit });
|
|
2640
2647
|
const returnedBytes = Buffer.byteLength(out.content, "utf-8");
|
|
2641
2648
|
applyReadHeaders(res);
|
|
2642
2649
|
res.status(200).json({
|
|
@@ -2690,13 +2697,13 @@ async function handleGetFileBytes(req, res, deps) {
|
|
|
2690
2697
|
});
|
|
2691
2698
|
return;
|
|
2692
2699
|
}
|
|
2693
|
-
const
|
|
2700
|
+
const fs6 = factory.forRequest({
|
|
2694
2701
|
originatorClientId: clientId ?? void 0,
|
|
2695
2702
|
route: ROUTE2
|
|
2696
2703
|
});
|
|
2697
2704
|
try {
|
|
2698
|
-
const resolved = await
|
|
2699
|
-
const out = await
|
|
2705
|
+
const resolved = await fs6.resolve(queryPath, "read");
|
|
2706
|
+
const out = await fs6.readBytesWindow(resolved, {
|
|
2700
2707
|
offset: offset ?? 0,
|
|
2701
2708
|
maxBytes: maxBytes ?? DEFAULT_FILE_BYTES_MAX_BYTES
|
|
2702
2709
|
});
|
|
@@ -2724,13 +2731,13 @@ async function handleGetStat(req, res, deps) {
|
|
|
2724
2731
|
if (clientId === null) return;
|
|
2725
2732
|
const queryPath = requireStringQuery(res, req.query["path"], "path", ROUTE2);
|
|
2726
2733
|
if (queryPath === null) return;
|
|
2727
|
-
const
|
|
2734
|
+
const fs6 = factory.forRequest({
|
|
2728
2735
|
originatorClientId: clientId ?? void 0,
|
|
2729
2736
|
route: ROUTE2
|
|
2730
2737
|
});
|
|
2731
2738
|
try {
|
|
2732
|
-
const resolved = await
|
|
2733
|
-
const st = await
|
|
2739
|
+
const resolved = await fs6.resolve(queryPath, "stat");
|
|
2740
|
+
const st = await fs6.stat(resolved);
|
|
2734
2741
|
applyReadHeaders(res);
|
|
2735
2742
|
res.status(200).json({
|
|
2736
2743
|
kind: "stat",
|
|
@@ -2753,13 +2760,13 @@ async function handleGetList(req, res, deps) {
|
|
|
2753
2760
|
const queryPath = requireStringQuery(res, req.query["path"], "path", ROUTE2);
|
|
2754
2761
|
if (queryPath === null) return;
|
|
2755
2762
|
const includeIgnored = parseBoolFlag(req.query["includeIgnored"]);
|
|
2756
|
-
const
|
|
2763
|
+
const fs6 = factory.forRequest({
|
|
2757
2764
|
originatorClientId: clientId ?? void 0,
|
|
2758
2765
|
route: ROUTE2
|
|
2759
2766
|
});
|
|
2760
2767
|
try {
|
|
2761
|
-
const resolved = await
|
|
2762
|
-
const entries = await
|
|
2768
|
+
const resolved = await fs6.resolve(queryPath, "list");
|
|
2769
|
+
const entries = await fs6.list(resolved, {
|
|
2763
2770
|
includeIgnored,
|
|
2764
2771
|
maxEntries: MAX_LIST_ENTRIES + 1
|
|
2765
2772
|
});
|
|
@@ -2812,15 +2819,15 @@ async function handleGetGlob(req, res, deps) {
|
|
|
2812
2819
|
}
|
|
2813
2820
|
const cwdRaw = req.query["cwd"];
|
|
2814
2821
|
const cwdString = typeof cwdRaw === "string" && cwdRaw.length > 0 ? cwdRaw : void 0;
|
|
2815
|
-
const
|
|
2822
|
+
const fs6 = factory.forRequest({
|
|
2816
2823
|
originatorClientId: clientId ?? void 0,
|
|
2817
2824
|
route: ROUTE2
|
|
2818
2825
|
});
|
|
2819
2826
|
const start = performance.now();
|
|
2820
2827
|
try {
|
|
2821
|
-
const cwdResolved = cwdString ? await
|
|
2828
|
+
const cwdResolved = cwdString ? await fs6.resolve(cwdString, "list") : void 0;
|
|
2822
2829
|
const cap = maxResults ?? DEFAULT_GLOB_MAX_RESULTS;
|
|
2823
|
-
const probe = await
|
|
2830
|
+
const probe = await fs6.glob(pattern, {
|
|
2824
2831
|
cwd: cwdResolved,
|
|
2825
2832
|
includeIgnored,
|
|
2826
2833
|
maxResults: cap + 1
|
|
@@ -2994,7 +3001,7 @@ function validateClientId(clientId, deps, res) {
|
|
|
2994
3001
|
}
|
|
2995
3002
|
__name(validateClientId, "validateClientId");
|
|
2996
3003
|
function createSetupGithubFileOps(factory, route, originatorClientId) {
|
|
2997
|
-
const
|
|
3004
|
+
const fs6 = factory.forRequest({
|
|
2998
3005
|
route,
|
|
2999
3006
|
...originatorClientId ? { originatorClientId } : {}
|
|
3000
3007
|
});
|
|
@@ -3017,14 +3024,14 @@ function createSetupGithubFileOps(factory, route, originatorClientId) {
|
|
|
3017
3024
|
]);
|
|
3018
3025
|
},
|
|
3019
3026
|
async writeTextFile(_gitRepoRoot, relativePath, content) {
|
|
3020
|
-
const resolved = await
|
|
3021
|
-
const out = await
|
|
3027
|
+
const resolved = await fs6.resolve(relativePath, "write");
|
|
3028
|
+
const out = await fs6.writeTextOverwrite(resolved, content);
|
|
3022
3029
|
return { sizeBytes: out.sizeBytes };
|
|
3023
3030
|
},
|
|
3024
3031
|
async readTextFile(_gitRepoRoot, relativePath) {
|
|
3025
3032
|
try {
|
|
3026
|
-
const resolved = await
|
|
3027
|
-
const out = await
|
|
3033
|
+
const resolved = await fs6.resolve(relativePath, "read");
|
|
3034
|
+
const out = await fs6.readText(resolved);
|
|
3028
3035
|
return out.content;
|
|
3029
3036
|
} catch (error2) {
|
|
3030
3037
|
if (isFsError(error2) && error2.kind === "path_not_found") {
|
|
@@ -3045,15 +3052,15 @@ async function ensureDirectoryWithoutSymlink(root, segments) {
|
|
|
3045
3052
|
checkedSegments.push(segment);
|
|
3046
3053
|
const label = `Workspace path "${checkedSegments.join("/")}"`;
|
|
3047
3054
|
try {
|
|
3048
|
-
const
|
|
3049
|
-
if (
|
|
3055
|
+
const stat3 = await fsp3.lstat(current);
|
|
3056
|
+
if (stat3.isSymbolicLink()) {
|
|
3050
3057
|
throw new SetupGithubError(
|
|
3051
3058
|
"github_setup_invalid_workspace",
|
|
3052
3059
|
`${label} must not be a symlink.`,
|
|
3053
3060
|
400
|
|
3054
3061
|
);
|
|
3055
3062
|
}
|
|
3056
|
-
if (!
|
|
3063
|
+
if (!stat3.isDirectory()) {
|
|
3057
3064
|
throw new SetupGithubError(
|
|
3058
3065
|
"github_setup_invalid_workspace",
|
|
3059
3066
|
`${label} must be a directory.`,
|
|
@@ -3090,15 +3097,15 @@ async function ensureDirectoryWithoutSymlink(root, segments) {
|
|
|
3090
3097
|
}
|
|
3091
3098
|
__name(ensureDirectoryWithoutSymlink, "ensureDirectoryWithoutSymlink");
|
|
3092
3099
|
async function assertDirectoryWithoutSymlink(target, label) {
|
|
3093
|
-
const
|
|
3094
|
-
if (
|
|
3100
|
+
const stat3 = await fsp3.lstat(target);
|
|
3101
|
+
if (stat3.isSymbolicLink()) {
|
|
3095
3102
|
throw new SetupGithubError(
|
|
3096
3103
|
"github_setup_invalid_workspace",
|
|
3097
3104
|
`${label} must not be a symlink.`,
|
|
3098
3105
|
400
|
|
3099
3106
|
);
|
|
3100
3107
|
}
|
|
3101
|
-
if (!
|
|
3108
|
+
if (!stat3.isDirectory()) {
|
|
3102
3109
|
throw new SetupGithubError(
|
|
3103
3110
|
"github_setup_invalid_workspace",
|
|
3104
3111
|
`${label} must be a directory.`,
|
|
@@ -4739,12 +4746,12 @@ async function collectWorkspaceMemoryStatus(boundWorkspace) {
|
|
|
4739
4746
|
for (const filename of filenames) {
|
|
4740
4747
|
const candidate = path8.join(globalDir, filename);
|
|
4741
4748
|
try {
|
|
4742
|
-
const
|
|
4743
|
-
if (
|
|
4749
|
+
const stat3 = await fs.stat(candidate);
|
|
4750
|
+
if (stat3.isFile()) {
|
|
4744
4751
|
files.push({
|
|
4745
4752
|
absolutePath: candidate,
|
|
4746
4753
|
scope: "global",
|
|
4747
|
-
bytes:
|
|
4754
|
+
bytes: stat3.size
|
|
4748
4755
|
});
|
|
4749
4756
|
}
|
|
4750
4757
|
} catch (err) {
|
|
@@ -4788,12 +4795,12 @@ async function walkWorkspaceForMemory(start, filenames, errors) {
|
|
|
4788
4795
|
for (const filename of filenames) {
|
|
4789
4796
|
const candidate = path8.join(start, filename);
|
|
4790
4797
|
try {
|
|
4791
|
-
const
|
|
4792
|
-
if (
|
|
4798
|
+
const stat3 = await fs.stat(candidate);
|
|
4799
|
+
if (stat3.isFile()) {
|
|
4793
4800
|
out.push({
|
|
4794
4801
|
absolutePath: candidate,
|
|
4795
4802
|
scope: "workspace",
|
|
4796
|
-
bytes:
|
|
4803
|
+
bytes: stat3.size
|
|
4797
4804
|
});
|
|
4798
4805
|
}
|
|
4799
4806
|
} catch (err) {
|
|
@@ -9045,7 +9052,7 @@ var AcpDispatcher = class {
|
|
|
9045
9052
|
);
|
|
9046
9053
|
return;
|
|
9047
9054
|
}
|
|
9048
|
-
const
|
|
9055
|
+
const fs6 = this.fsFactory.forRequest({
|
|
9049
9056
|
originatorClientId: conn.clientId,
|
|
9050
9057
|
route: `ACP ${method}`
|
|
9051
9058
|
});
|
|
@@ -9097,8 +9104,8 @@ var AcpDispatcher = class {
|
|
|
9097
9104
|
);
|
|
9098
9105
|
return;
|
|
9099
9106
|
}
|
|
9100
|
-
const resolved = await
|
|
9101
|
-
const out = await
|
|
9107
|
+
const resolved = await fs6.resolve(p, "read");
|
|
9108
|
+
const out = await fs6.readText(resolved, { maxBytes, line, limit });
|
|
9102
9109
|
this.replyConn(conn, id, {
|
|
9103
9110
|
path: p,
|
|
9104
9111
|
content: out.content,
|
|
@@ -9120,7 +9127,7 @@ var AcpDispatcher = class {
|
|
|
9120
9127
|
conn.sendConn(error(id, RPC.INVALID_PARAMS, "`path` required"));
|
|
9121
9128
|
return;
|
|
9122
9129
|
}
|
|
9123
|
-
const
|
|
9130
|
+
const fs6 = this.fsFactory.forRequest({
|
|
9124
9131
|
originatorClientId: conn.clientId,
|
|
9125
9132
|
route: `ACP ${method}`
|
|
9126
9133
|
});
|
|
@@ -9156,8 +9163,8 @@ var AcpDispatcher = class {
|
|
|
9156
9163
|
);
|
|
9157
9164
|
return;
|
|
9158
9165
|
}
|
|
9159
|
-
const resolved = await
|
|
9160
|
-
const buf = await
|
|
9166
|
+
const resolved = await fs6.resolve(p, "read");
|
|
9167
|
+
const buf = await fs6.readBytesWindow(resolved, { offset, maxBytes });
|
|
9161
9168
|
this.replyConn(conn, id, { path: p, ...buf });
|
|
9162
9169
|
return;
|
|
9163
9170
|
}
|
|
@@ -9175,12 +9182,12 @@ var AcpDispatcher = class {
|
|
|
9175
9182
|
conn.sendConn(error(id, RPC.INVALID_PARAMS, "`path` required"));
|
|
9176
9183
|
return;
|
|
9177
9184
|
}
|
|
9178
|
-
const
|
|
9185
|
+
const fs6 = this.fsFactory.forRequest({
|
|
9179
9186
|
originatorClientId: conn.clientId,
|
|
9180
9187
|
route: `ACP ${method}`
|
|
9181
9188
|
});
|
|
9182
|
-
const resolved = await
|
|
9183
|
-
const result = await
|
|
9189
|
+
const resolved = await fs6.resolve(p, "read");
|
|
9190
|
+
const result = await fs6.stat(resolved);
|
|
9184
9191
|
this.replyConn(conn, id, { path: p, ...result });
|
|
9185
9192
|
return;
|
|
9186
9193
|
}
|
|
@@ -9198,13 +9205,13 @@ var AcpDispatcher = class {
|
|
|
9198
9205
|
conn.sendConn(error(id, RPC.INVALID_PARAMS, "`path` required"));
|
|
9199
9206
|
return;
|
|
9200
9207
|
}
|
|
9201
|
-
const
|
|
9208
|
+
const fs6 = this.fsFactory.forRequest({
|
|
9202
9209
|
originatorClientId: conn.clientId,
|
|
9203
9210
|
route: `ACP ${method}`
|
|
9204
9211
|
});
|
|
9205
|
-
const resolved = await
|
|
9212
|
+
const resolved = await fs6.resolve(p, "read");
|
|
9206
9213
|
const MAX_LIST = 2e3;
|
|
9207
|
-
const entries = await
|
|
9214
|
+
const entries = await fs6.list(resolved, { maxEntries: MAX_LIST + 1 });
|
|
9208
9215
|
const truncated = entries.length > MAX_LIST;
|
|
9209
9216
|
this.replyConn(conn, id, {
|
|
9210
9217
|
path: p,
|
|
@@ -9229,7 +9236,7 @@ var AcpDispatcher = class {
|
|
|
9229
9236
|
);
|
|
9230
9237
|
return;
|
|
9231
9238
|
}
|
|
9232
|
-
const
|
|
9239
|
+
const fs6 = this.fsFactory.forRequest({
|
|
9233
9240
|
originatorClientId: conn.clientId,
|
|
9234
9241
|
route: `ACP ${method}`
|
|
9235
9242
|
});
|
|
@@ -9249,7 +9256,7 @@ var AcpDispatcher = class {
|
|
|
9249
9256
|
);
|
|
9250
9257
|
return;
|
|
9251
9258
|
}
|
|
9252
|
-
const matches = await
|
|
9259
|
+
const matches = await fs6.glob(pattern, {
|
|
9253
9260
|
maxResults: maxResults + 1
|
|
9254
9261
|
});
|
|
9255
9262
|
const truncated = matches.length > maxResults;
|
|
@@ -9281,11 +9288,11 @@ var AcpDispatcher = class {
|
|
|
9281
9288
|
);
|
|
9282
9289
|
return;
|
|
9283
9290
|
}
|
|
9284
|
-
const
|
|
9291
|
+
const fs6 = this.fsFactory.forRequest({
|
|
9285
9292
|
originatorClientId: conn.clientId,
|
|
9286
9293
|
route: `ACP ${method}`
|
|
9287
9294
|
});
|
|
9288
|
-
const resolved = await
|
|
9295
|
+
const resolved = await fs6.resolve(p, "write");
|
|
9289
9296
|
if (Buffer.byteLength(params["content"], "utf8") > 10 * 1024 * 1024) {
|
|
9290
9297
|
if (id !== void 0)
|
|
9291
9298
|
conn.sendConn(
|
|
@@ -9293,7 +9300,7 @@ var AcpDispatcher = class {
|
|
|
9293
9300
|
);
|
|
9294
9301
|
return;
|
|
9295
9302
|
}
|
|
9296
|
-
await
|
|
9303
|
+
await fs6.writeTextOverwrite(resolved, params["content"]);
|
|
9297
9304
|
this.replyConn(conn, id, { ok: true, path: p });
|
|
9298
9305
|
return;
|
|
9299
9306
|
}
|
|
@@ -9322,12 +9329,12 @@ var AcpDispatcher = class {
|
|
|
9322
9329
|
);
|
|
9323
9330
|
return;
|
|
9324
9331
|
}
|
|
9325
|
-
const
|
|
9332
|
+
const fs6 = this.fsFactory.forRequest({
|
|
9326
9333
|
originatorClientId: conn.clientId,
|
|
9327
9334
|
route: `ACP ${method}`
|
|
9328
9335
|
});
|
|
9329
|
-
const resolved = await
|
|
9330
|
-
const result = await
|
|
9336
|
+
const resolved = await fs6.resolve(p, "write");
|
|
9337
|
+
const result = await fs6.edit(
|
|
9331
9338
|
resolved,
|
|
9332
9339
|
params["oldText"],
|
|
9333
9340
|
params["newText"]
|
|
@@ -17518,13 +17525,13 @@ async function handlePostFileWrite(req, res, deps) {
|
|
|
17518
17525
|
req
|
|
17519
17526
|
);
|
|
17520
17527
|
if (originatorClientId === null) return;
|
|
17521
|
-
const
|
|
17528
|
+
const fs6 = factory.forRequest({
|
|
17522
17529
|
originatorClientId,
|
|
17523
17530
|
route: ROUTE2
|
|
17524
17531
|
});
|
|
17525
17532
|
try {
|
|
17526
|
-
const resolved = await
|
|
17527
|
-
const out = await
|
|
17533
|
+
const resolved = await fs6.resolve(queryPath, "write");
|
|
17534
|
+
const out = await fs6.writeTextAtomic(resolved, content, {
|
|
17528
17535
|
mode,
|
|
17529
17536
|
...expectedHash ? { expectedHash } : {},
|
|
17530
17537
|
...bom !== void 0 ? { bom } : {},
|
|
@@ -17577,13 +17584,13 @@ async function handlePostFileEdit(req, res, deps) {
|
|
|
17577
17584
|
req
|
|
17578
17585
|
);
|
|
17579
17586
|
if (originatorClientId === null) return;
|
|
17580
|
-
const
|
|
17587
|
+
const fs6 = factory.forRequest({
|
|
17581
17588
|
originatorClientId,
|
|
17582
17589
|
route: ROUTE2
|
|
17583
17590
|
});
|
|
17584
17591
|
try {
|
|
17585
|
-
const resolved = await
|
|
17586
|
-
const out = await
|
|
17592
|
+
const resolved = await fs6.resolve(queryPath, "edit");
|
|
17593
|
+
const out = await fs6.editAtomic(resolved, oldText, newText, {
|
|
17587
17594
|
expectedHash
|
|
17588
17595
|
});
|
|
17589
17596
|
applyReadHeaders(res);
|
|
@@ -17911,6 +17918,18 @@ var legacySessionTelemetryRoutes = [
|
|
|
17911
17918
|
attribution: "handler_resolved",
|
|
17912
17919
|
route: "GET /session/:id/tasks"
|
|
17913
17920
|
},
|
|
17921
|
+
{
|
|
17922
|
+
method: "GET",
|
|
17923
|
+
path: "/session/:id/subagents/:toolCallId",
|
|
17924
|
+
attribution: "handler_resolved",
|
|
17925
|
+
route: "GET /session/:id/subagents/:toolCallId"
|
|
17926
|
+
},
|
|
17927
|
+
{
|
|
17928
|
+
method: "POST",
|
|
17929
|
+
path: "/session/:id/subagents/:toolCallId/cancel",
|
|
17930
|
+
attribution: "handler_resolved",
|
|
17931
|
+
route: "POST /session/:id/subagents/:toolCallId/cancel"
|
|
17932
|
+
},
|
|
17914
17933
|
{
|
|
17915
17934
|
method: "GET",
|
|
17916
17935
|
path: "/session/:id/lsp",
|
|
@@ -18593,7 +18612,7 @@ __name(registerPermissionRoutes, "registerPermissionRoutes");
|
|
|
18593
18612
|
// packages/cli/src/serve/routes/session.ts
|
|
18594
18613
|
init_esbuild_shims();
|
|
18595
18614
|
import * as crypto3 from "node:crypto";
|
|
18596
|
-
import * as
|
|
18615
|
+
import * as fs4 from "node:fs";
|
|
18597
18616
|
import * as path10 from "node:path";
|
|
18598
18617
|
|
|
18599
18618
|
// packages/cli/src/serve/server/prompt-deadline.ts
|
|
@@ -19199,6 +19218,714 @@ async function exportSessionTranscript(params) {
|
|
|
19199
19218
|
}
|
|
19200
19219
|
__name(exportSessionTranscript, "exportSessionTranscript");
|
|
19201
19220
|
|
|
19221
|
+
// packages/cli/src/serve/virtual-subagent-sessions.ts
|
|
19222
|
+
init_esbuild_shims();
|
|
19223
|
+
import * as fs3 from "node:fs/promises";
|
|
19224
|
+
import { createReadStream } from "node:fs";
|
|
19225
|
+
import readline from "node:readline";
|
|
19226
|
+
var PREFIX = "subagent.";
|
|
19227
|
+
var POLL_INTERVAL_MS = 250;
|
|
19228
|
+
var TARGET_RETENTION_MS = 6e4;
|
|
19229
|
+
async function readFirstUserText(filePath) {
|
|
19230
|
+
const stream = createReadStream(filePath);
|
|
19231
|
+
const lines = readline.createInterface({
|
|
19232
|
+
input: stream,
|
|
19233
|
+
crlfDelay: Infinity
|
|
19234
|
+
});
|
|
19235
|
+
try {
|
|
19236
|
+
for await (const line of lines) {
|
|
19237
|
+
const trimmed = line.trim();
|
|
19238
|
+
if (!trimmed) continue;
|
|
19239
|
+
for (const record of parseLineTolerant(trimmed, filePath)) {
|
|
19240
|
+
if (record.type !== "user") continue;
|
|
19241
|
+
return record.message?.parts?.find(
|
|
19242
|
+
(part) => typeof part.text === "string"
|
|
19243
|
+
)?.text;
|
|
19244
|
+
}
|
|
19245
|
+
}
|
|
19246
|
+
return void 0;
|
|
19247
|
+
} catch (error2) {
|
|
19248
|
+
if (error2.code === "ENOENT") return void 0;
|
|
19249
|
+
throw error2;
|
|
19250
|
+
} finally {
|
|
19251
|
+
lines.close();
|
|
19252
|
+
stream.destroy();
|
|
19253
|
+
}
|
|
19254
|
+
}
|
|
19255
|
+
__name(readFirstUserText, "readFirstUserText");
|
|
19256
|
+
function asRecord(value) {
|
|
19257
|
+
return typeof value === "object" && value !== null ? value : void 0;
|
|
19258
|
+
}
|
|
19259
|
+
__name(asRecord, "asRecord");
|
|
19260
|
+
function finiteNonNegative(value) {
|
|
19261
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : void 0;
|
|
19262
|
+
}
|
|
19263
|
+
__name(finiteNonNegative, "finiteNonNegative");
|
|
19264
|
+
function normalizeTaskStatus(status) {
|
|
19265
|
+
if (typeof status !== "string") return void 0;
|
|
19266
|
+
if (status === "success") return "completed";
|
|
19267
|
+
if (status === "error") return "failed";
|
|
19268
|
+
if (status === "background") return "running";
|
|
19269
|
+
return status;
|
|
19270
|
+
}
|
|
19271
|
+
__name(normalizeTaskStatus, "normalizeTaskStatus");
|
|
19272
|
+
function durationBetween(start, end) {
|
|
19273
|
+
if (!end) return void 0;
|
|
19274
|
+
const startTime = Date.parse(start);
|
|
19275
|
+
const endTime = Date.parse(end);
|
|
19276
|
+
return Number.isFinite(startTime) && Number.isFinite(endTime) ? Math.max(0, endTime - startTime) : void 0;
|
|
19277
|
+
}
|
|
19278
|
+
__name(durationBetween, "durationBetween");
|
|
19279
|
+
function findToolCallMetrics(records, toolCallId) {
|
|
19280
|
+
const toolResult = records.find(
|
|
19281
|
+
(record) => record.toolCallResult?.callId === toolCallId
|
|
19282
|
+
)?.toolCallResult;
|
|
19283
|
+
const display = asRecord(toolResult?.resultDisplay);
|
|
19284
|
+
const summary = asRecord(display?.["executionSummary"]);
|
|
19285
|
+
return {
|
|
19286
|
+
status: normalizeTaskStatus(display?.["status"]) ?? normalizeTaskStatus(toolResult?.status),
|
|
19287
|
+
durationMs: finiteNonNegative(summary?.["totalDurationMs"]),
|
|
19288
|
+
totalTokens: finiteNonNegative(summary?.["totalTokens"]) ?? finiteNonNegative(display?.["tokenCount"]),
|
|
19289
|
+
inputTokens: finiteNonNegative(summary?.["inputTokens"]),
|
|
19290
|
+
outputTokens: finiteNonNegative(summary?.["outputTokens"]),
|
|
19291
|
+
cachedTokens: finiteNonNegative(summary?.["cachedTokens"])
|
|
19292
|
+
};
|
|
19293
|
+
}
|
|
19294
|
+
__name(findToolCallMetrics, "findToolCallMetrics");
|
|
19295
|
+
function encodePart(value) {
|
|
19296
|
+
return Buffer.from(value, "utf8").toString("base64url");
|
|
19297
|
+
}
|
|
19298
|
+
__name(encodePart, "encodePart");
|
|
19299
|
+
function decodePart(value) {
|
|
19300
|
+
try {
|
|
19301
|
+
return Buffer.from(value, "base64url").toString("utf8");
|
|
19302
|
+
} catch {
|
|
19303
|
+
return void 0;
|
|
19304
|
+
}
|
|
19305
|
+
}
|
|
19306
|
+
__name(decodePart, "decodePart");
|
|
19307
|
+
function isValidVirtualSessionPart(value) {
|
|
19308
|
+
return /^[a-zA-Z0-9_-]{1,500}$/.test(value);
|
|
19309
|
+
}
|
|
19310
|
+
__name(isValidVirtualSessionPart, "isValidVirtualSessionPart");
|
|
19311
|
+
function createVirtualSubagentSessionId(parentSessionId, agentId) {
|
|
19312
|
+
if (!isValidVirtualSessionPart(parentSessionId) || !isValidVirtualSessionPart(agentId)) {
|
|
19313
|
+
throw new Error("Virtual subagent session ids require valid id parts");
|
|
19314
|
+
}
|
|
19315
|
+
return `${PREFIX}${encodePart(parentSessionId)}.${encodePart(agentId)}`;
|
|
19316
|
+
}
|
|
19317
|
+
__name(createVirtualSubagentSessionId, "createVirtualSubagentSessionId");
|
|
19318
|
+
function parseVirtualSubagentSessionId(sessionId) {
|
|
19319
|
+
if (!sessionId.startsWith(PREFIX) || sessionId.length > 2e3) {
|
|
19320
|
+
return void 0;
|
|
19321
|
+
}
|
|
19322
|
+
const parts = sessionId.slice(PREFIX.length).split(".");
|
|
19323
|
+
if (parts.length !== 2) return void 0;
|
|
19324
|
+
const parentSessionId = decodePart(parts[0]);
|
|
19325
|
+
const agentId = decodePart(parts[1]);
|
|
19326
|
+
if (!parentSessionId || !agentId || !isValidVirtualSessionPart(parentSessionId) || !isValidVirtualSessionPart(agentId)) {
|
|
19327
|
+
return void 0;
|
|
19328
|
+
}
|
|
19329
|
+
return { parentSessionId, agentId };
|
|
19330
|
+
}
|
|
19331
|
+
__name(parseVirtualSubagentSessionId, "parseVirtualSubagentSessionId");
|
|
19332
|
+
function replayCursorState(sessionId, position, leafUuid, startTime, lastUpdated) {
|
|
19333
|
+
return {
|
|
19334
|
+
v: 1,
|
|
19335
|
+
sessionId,
|
|
19336
|
+
fileIdentity: { dev: 0, ino: 0 },
|
|
19337
|
+
snapshotSize: position,
|
|
19338
|
+
position,
|
|
19339
|
+
leafUuid,
|
|
19340
|
+
startTime,
|
|
19341
|
+
lastUpdated
|
|
19342
|
+
};
|
|
19343
|
+
}
|
|
19344
|
+
__name(replayCursorState, "replayCursorState");
|
|
19345
|
+
var VirtualSubagentTarget = class _VirtualSubagentTarget {
|
|
19346
|
+
constructor(sessionId, parentSessionId, task, workspaceCwd, onExpired) {
|
|
19347
|
+
this.sessionId = sessionId;
|
|
19348
|
+
this.parentSessionId = parentSessionId;
|
|
19349
|
+
this.task = task;
|
|
19350
|
+
this.workspaceCwd = workspaceCwd;
|
|
19351
|
+
this.onExpired = onExpired;
|
|
19352
|
+
}
|
|
19353
|
+
static {
|
|
19354
|
+
__name(this, "VirtualSubagentTarget");
|
|
19355
|
+
}
|
|
19356
|
+
bus = new EventBus(1024, 8);
|
|
19357
|
+
events = [];
|
|
19358
|
+
snapshotDelivered = false;
|
|
19359
|
+
offset = 0;
|
|
19360
|
+
transcriptIdentity;
|
|
19361
|
+
streamOffset = 0;
|
|
19362
|
+
streamIdentity;
|
|
19363
|
+
streamReady = false;
|
|
19364
|
+
canonicalThroughTimestamp = 0;
|
|
19365
|
+
completedStreamRounds = /* @__PURE__ */ new Set();
|
|
19366
|
+
streamedRounds = /* @__PURE__ */ new Set();
|
|
19367
|
+
streamRunIds = /* @__PURE__ */ new Set();
|
|
19368
|
+
legacyStreamedSinceCanonical = false;
|
|
19369
|
+
replayState;
|
|
19370
|
+
initialized = false;
|
|
19371
|
+
refreshPromise = Promise.resolve();
|
|
19372
|
+
snapshotPromise = Promise.resolve();
|
|
19373
|
+
pollTimer;
|
|
19374
|
+
subscribers = 0;
|
|
19375
|
+
retentionTimer;
|
|
19376
|
+
updateStatus(status) {
|
|
19377
|
+
const wasRunning = this.task.status === "running";
|
|
19378
|
+
this.task.status = status;
|
|
19379
|
+
if (status !== "running" && this.pollTimer) {
|
|
19380
|
+
clearInterval(this.pollTimer);
|
|
19381
|
+
this.pollTimer = void 0;
|
|
19382
|
+
}
|
|
19383
|
+
if (wasRunning && status !== "running") {
|
|
19384
|
+
void this.refreshLive().catch(() => void 0);
|
|
19385
|
+
}
|
|
19386
|
+
}
|
|
19387
|
+
rememberEvent(event) {
|
|
19388
|
+
if (event && !this.snapshotDelivered) this.events.push(event);
|
|
19389
|
+
}
|
|
19390
|
+
resetCanonicalState() {
|
|
19391
|
+
this.offset = 0;
|
|
19392
|
+
this.replayState = void 0;
|
|
19393
|
+
this.canonicalThroughTimestamp = 0;
|
|
19394
|
+
this.completedStreamRounds.clear();
|
|
19395
|
+
this.streamRunIds.clear();
|
|
19396
|
+
this.streamedRounds.clear();
|
|
19397
|
+
this.legacyStreamedSinceCanonical = false;
|
|
19398
|
+
}
|
|
19399
|
+
resetStreamState() {
|
|
19400
|
+
this.streamOffset = 0;
|
|
19401
|
+
this.completedStreamRounds.clear();
|
|
19402
|
+
this.streamRunIds.clear();
|
|
19403
|
+
this.streamedRounds.clear();
|
|
19404
|
+
this.legacyStreamedSinceCanonical = false;
|
|
19405
|
+
}
|
|
19406
|
+
async readNewRecords(endOffset) {
|
|
19407
|
+
let handle;
|
|
19408
|
+
try {
|
|
19409
|
+
handle = await fs3.open(this.task.outputFile, "r");
|
|
19410
|
+
const stat3 = await handle.stat();
|
|
19411
|
+
const identity = `${stat3.dev}:${stat3.ino}`;
|
|
19412
|
+
if (this.transcriptIdentity !== void 0 && this.transcriptIdentity !== identity || stat3.size < this.offset) {
|
|
19413
|
+
this.resetCanonicalState();
|
|
19414
|
+
}
|
|
19415
|
+
this.transcriptIdentity = identity;
|
|
19416
|
+
const size = Math.min(stat3.size, endOffset ?? stat3.size);
|
|
19417
|
+
if (size <= this.offset) return [];
|
|
19418
|
+
const bytes = Buffer.alloc(size - this.offset);
|
|
19419
|
+
const { bytesRead } = await handle.read(
|
|
19420
|
+
bytes,
|
|
19421
|
+
0,
|
|
19422
|
+
bytes.length,
|
|
19423
|
+
this.offset
|
|
19424
|
+
);
|
|
19425
|
+
const chunk = bytes.subarray(0, bytesRead);
|
|
19426
|
+
const lastNewline = chunk.lastIndexOf(10);
|
|
19427
|
+
if (lastNewline < 0) return [];
|
|
19428
|
+
const complete = chunk.subarray(0, lastNewline + 1);
|
|
19429
|
+
this.offset += complete.length;
|
|
19430
|
+
return complete.toString("utf8").split("\n").flatMap((line) => {
|
|
19431
|
+
const trimmed = line.trim();
|
|
19432
|
+
return trimmed ? parseLineTolerant(trimmed, this.task.outputFile) : [];
|
|
19433
|
+
});
|
|
19434
|
+
} catch (error2) {
|
|
19435
|
+
if (error2.code === "ENOENT") {
|
|
19436
|
+
if (this.transcriptIdentity !== void 0) {
|
|
19437
|
+
this.transcriptIdentity = void 0;
|
|
19438
|
+
this.resetCanonicalState();
|
|
19439
|
+
}
|
|
19440
|
+
return [];
|
|
19441
|
+
}
|
|
19442
|
+
throw error2;
|
|
19443
|
+
} finally {
|
|
19444
|
+
await handle?.close();
|
|
19445
|
+
}
|
|
19446
|
+
}
|
|
19447
|
+
async readStreamUpdates(endOffset) {
|
|
19448
|
+
const replayingExisting = !this.streamReady;
|
|
19449
|
+
this.streamReady = true;
|
|
19450
|
+
const filePath = `${this.task.outputFile}.stream`;
|
|
19451
|
+
let handle;
|
|
19452
|
+
try {
|
|
19453
|
+
handle = await fs3.open(filePath, "r");
|
|
19454
|
+
const stat3 = await handle.stat();
|
|
19455
|
+
const identity = `${stat3.dev}:${stat3.ino}`;
|
|
19456
|
+
if (this.streamIdentity !== void 0 && this.streamIdentity !== identity) {
|
|
19457
|
+
this.resetStreamState();
|
|
19458
|
+
}
|
|
19459
|
+
this.streamIdentity = identity;
|
|
19460
|
+
if (stat3.size < this.streamOffset) this.resetStreamState();
|
|
19461
|
+
const size = Math.min(stat3.size, endOffset ?? stat3.size);
|
|
19462
|
+
if (size <= this.streamOffset) return;
|
|
19463
|
+
const bytes = Buffer.alloc(size - this.streamOffset);
|
|
19464
|
+
const { bytesRead } = await handle.read(
|
|
19465
|
+
bytes,
|
|
19466
|
+
0,
|
|
19467
|
+
bytes.length,
|
|
19468
|
+
this.streamOffset
|
|
19469
|
+
);
|
|
19470
|
+
const chunk = bytes.subarray(0, bytesRead);
|
|
19471
|
+
const lastNewline = chunk.lastIndexOf(10);
|
|
19472
|
+
if (lastNewline < 0) return;
|
|
19473
|
+
const complete = chunk.subarray(0, lastNewline + 1);
|
|
19474
|
+
this.streamOffset += complete.length;
|
|
19475
|
+
const records = complete.toString("utf8").split("\n").flatMap((line) => {
|
|
19476
|
+
const trimmed = line.trim();
|
|
19477
|
+
return trimmed ? parseLineTolerant(trimmed, filePath) : [];
|
|
19478
|
+
});
|
|
19479
|
+
for (const record of records) {
|
|
19480
|
+
if (record.v !== 1 || typeof record.text !== "string" || typeof record.timestamp !== "number") {
|
|
19481
|
+
continue;
|
|
19482
|
+
}
|
|
19483
|
+
const roundKey = typeof record.runId === "string" && typeof record.round === "number" ? `${record.runId}:${record.round}` : void 0;
|
|
19484
|
+
if (typeof record.runId === "string") {
|
|
19485
|
+
this.streamRunIds.add(record.runId);
|
|
19486
|
+
}
|
|
19487
|
+
if ((roundKey ? this.completedStreamRounds.has(roundKey) : record.timestamp <= this.canonicalThroughTimestamp) || replayingExisting && typeof record.round !== "number") {
|
|
19488
|
+
continue;
|
|
19489
|
+
}
|
|
19490
|
+
const event = this.bus.publish({
|
|
19491
|
+
type: "session_update",
|
|
19492
|
+
data: createTranscriptMessageUpdate({
|
|
19493
|
+
role: "assistant",
|
|
19494
|
+
text: record.text,
|
|
19495
|
+
timestamp: record.timestamp,
|
|
19496
|
+
...record.thought ? { thought: true } : {}
|
|
19497
|
+
})
|
|
19498
|
+
});
|
|
19499
|
+
this.rememberEvent(event);
|
|
19500
|
+
if (roundKey) this.streamedRounds.add(roundKey);
|
|
19501
|
+
else this.legacyStreamedSinceCanonical = true;
|
|
19502
|
+
}
|
|
19503
|
+
for (const completed of this.completedStreamRounds) {
|
|
19504
|
+
const runId = completed.slice(0, completed.lastIndexOf(":"));
|
|
19505
|
+
if (!this.streamRunIds.has(runId)) {
|
|
19506
|
+
this.completedStreamRounds.delete(completed);
|
|
19507
|
+
}
|
|
19508
|
+
}
|
|
19509
|
+
} catch (error2) {
|
|
19510
|
+
if (error2.code !== "ENOENT") throw error2;
|
|
19511
|
+
this.streamIdentity = void 0;
|
|
19512
|
+
this.streamOffset = 0;
|
|
19513
|
+
this.streamRunIds.clear();
|
|
19514
|
+
this.streamedRounds.clear();
|
|
19515
|
+
this.legacyStreamedSinceCanonical = false;
|
|
19516
|
+
} finally {
|
|
19517
|
+
await handle?.close();
|
|
19518
|
+
}
|
|
19519
|
+
}
|
|
19520
|
+
refreshOnce = /* @__PURE__ */ __name(async (endOffset) => {
|
|
19521
|
+
let records = await this.readNewRecords(endOffset);
|
|
19522
|
+
if (records.length === 0) {
|
|
19523
|
+
this.initialized = true;
|
|
19524
|
+
return;
|
|
19525
|
+
}
|
|
19526
|
+
for (const record of records) {
|
|
19527
|
+
if (record.type === "assistant" && (record.usageMetadata !== void 0 || record.message?.parts?.some((part) => typeof part.text === "string"))) {
|
|
19528
|
+
if (typeof record.agentRunId === "string" && typeof record.agentRound === "number") {
|
|
19529
|
+
this.completedStreamRounds.add(
|
|
19530
|
+
`${record.agentRunId}:${record.agentRound}`
|
|
19531
|
+
);
|
|
19532
|
+
}
|
|
19533
|
+
const timestamp = Date.parse(record.timestamp);
|
|
19534
|
+
if (Number.isFinite(timestamp)) {
|
|
19535
|
+
this.canonicalThroughTimestamp = Math.max(
|
|
19536
|
+
this.canonicalThroughTimestamp,
|
|
19537
|
+
timestamp
|
|
19538
|
+
);
|
|
19539
|
+
}
|
|
19540
|
+
}
|
|
19541
|
+
}
|
|
19542
|
+
if (this.streamedRounds.size > 0 || this.legacyStreamedSinceCanonical) {
|
|
19543
|
+
records = records.filter((record) => {
|
|
19544
|
+
const roundKey = typeof record.agentRunId === "string" && typeof record.agentRound === "number" ? `${record.agentRunId}:${record.agentRound}` : void 0;
|
|
19545
|
+
if (roundKey && this.streamedRounds.delete(roundKey)) return false;
|
|
19546
|
+
if (!this.legacyStreamedSinceCanonical || record.type !== "assistant" || record.message?.parts?.some((part) => part.functionCall)) {
|
|
19547
|
+
return true;
|
|
19548
|
+
}
|
|
19549
|
+
this.legacyStreamedSinceCanonical = false;
|
|
19550
|
+
return false;
|
|
19551
|
+
});
|
|
19552
|
+
if (records.length === 0) {
|
|
19553
|
+
this.initialized = true;
|
|
19554
|
+
return;
|
|
19555
|
+
}
|
|
19556
|
+
}
|
|
19557
|
+
const startTime = records[0]?.timestamp ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
19558
|
+
const lastUpdated = records[records.length - 1]?.timestamp ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
19559
|
+
const page = {
|
|
19560
|
+
sessionId: this.sessionId,
|
|
19561
|
+
filePath: this.task.outputFile,
|
|
19562
|
+
records,
|
|
19563
|
+
gaps: [],
|
|
19564
|
+
hasMore: true,
|
|
19565
|
+
replay: this.replayState,
|
|
19566
|
+
startTime,
|
|
19567
|
+
lastUpdated,
|
|
19568
|
+
nextCursorState: replayCursorState(
|
|
19569
|
+
this.sessionId,
|
|
19570
|
+
this.offset,
|
|
19571
|
+
records[records.length - 1]?.uuid ?? "",
|
|
19572
|
+
startTime,
|
|
19573
|
+
lastUpdated
|
|
19574
|
+
)
|
|
19575
|
+
};
|
|
19576
|
+
let nextReplayState;
|
|
19577
|
+
const replay = await replayTranscriptRecordPage({
|
|
19578
|
+
sessionId: this.sessionId,
|
|
19579
|
+
page,
|
|
19580
|
+
encodeCursor: /* @__PURE__ */ __name((state) => {
|
|
19581
|
+
nextReplayState = state.replay;
|
|
19582
|
+
return "virtual-subagent-replay";
|
|
19583
|
+
}, "encodeCursor")
|
|
19584
|
+
});
|
|
19585
|
+
this.replayState = nextReplayState;
|
|
19586
|
+
const inputs = replay.updates.map((update) => ({
|
|
19587
|
+
type: "session_update",
|
|
19588
|
+
data: update
|
|
19589
|
+
}));
|
|
19590
|
+
const published = this.initialized ? inputs.flatMap((input) => {
|
|
19591
|
+
const event = this.bus.publish(input);
|
|
19592
|
+
return event ? [event] : [];
|
|
19593
|
+
}) : this.bus.seedReplayEvents(inputs);
|
|
19594
|
+
if (!this.snapshotDelivered) this.events.push(...published);
|
|
19595
|
+
this.initialized = true;
|
|
19596
|
+
}, "refreshOnce");
|
|
19597
|
+
refreshAt(bounds) {
|
|
19598
|
+
return this.refreshOnce(bounds?.transcript).then(async () => {
|
|
19599
|
+
if (this.task.status === "running") {
|
|
19600
|
+
await this.readStreamUpdates(bounds?.stream);
|
|
19601
|
+
}
|
|
19602
|
+
});
|
|
19603
|
+
}
|
|
19604
|
+
enqueueRefresh(work) {
|
|
19605
|
+
const result = this.refreshPromise.catch(() => void 0).then(work);
|
|
19606
|
+
this.refreshPromise = result.then(
|
|
19607
|
+
() => void 0,
|
|
19608
|
+
() => void 0
|
|
19609
|
+
);
|
|
19610
|
+
return result;
|
|
19611
|
+
}
|
|
19612
|
+
refreshLive() {
|
|
19613
|
+
return this.enqueueRefresh(() => this.refreshAt());
|
|
19614
|
+
}
|
|
19615
|
+
async captureReadBounds() {
|
|
19616
|
+
const size = /* @__PURE__ */ __name(async (filePath) => {
|
|
19617
|
+
try {
|
|
19618
|
+
return (await fs3.stat(filePath)).size;
|
|
19619
|
+
} catch (error2) {
|
|
19620
|
+
if (error2.code === "ENOENT") return 0;
|
|
19621
|
+
throw error2;
|
|
19622
|
+
}
|
|
19623
|
+
}, "size");
|
|
19624
|
+
const [transcript, stream] = await Promise.all([
|
|
19625
|
+
size(this.task.outputFile),
|
|
19626
|
+
size(`${this.task.outputFile}.stream`)
|
|
19627
|
+
]);
|
|
19628
|
+
return { transcript, stream };
|
|
19629
|
+
}
|
|
19630
|
+
async createSnapshotOnce() {
|
|
19631
|
+
if (!this.snapshotDelivered) {
|
|
19632
|
+
await this.refreshLive();
|
|
19633
|
+
const snapshot = [...this.events];
|
|
19634
|
+
this.events.length = 0;
|
|
19635
|
+
this.snapshotDelivered = true;
|
|
19636
|
+
return { events: snapshot, lastEventId: this.bus.lastEventId };
|
|
19637
|
+
}
|
|
19638
|
+
return this.enqueueRefresh(async () => {
|
|
19639
|
+
const bounds = await this.captureReadBounds();
|
|
19640
|
+
const target = new _VirtualSubagentTarget(
|
|
19641
|
+
this.sessionId,
|
|
19642
|
+
this.parentSessionId,
|
|
19643
|
+
this.task,
|
|
19644
|
+
this.workspaceCwd,
|
|
19645
|
+
() => void 0
|
|
19646
|
+
);
|
|
19647
|
+
await target.refreshAt(bounds);
|
|
19648
|
+
await this.refreshAt(bounds);
|
|
19649
|
+
return {
|
|
19650
|
+
events: [...target.events],
|
|
19651
|
+
lastEventId: this.bus.lastEventId
|
|
19652
|
+
};
|
|
19653
|
+
});
|
|
19654
|
+
}
|
|
19655
|
+
createSnapshot() {
|
|
19656
|
+
const snapshot = this.snapshotPromise.then(() => this.createSnapshotOnce());
|
|
19657
|
+
this.snapshotPromise = snapshot.then(
|
|
19658
|
+
() => void 0,
|
|
19659
|
+
() => void 0
|
|
19660
|
+
);
|
|
19661
|
+
return snapshot;
|
|
19662
|
+
}
|
|
19663
|
+
async load(clientId) {
|
|
19664
|
+
const snapshot = await this.createSnapshot();
|
|
19665
|
+
if (this.subscribers === 0) this.scheduleRetention();
|
|
19666
|
+
return {
|
|
19667
|
+
sessionId: this.sessionId,
|
|
19668
|
+
workspaceCwd: this.workspaceCwd,
|
|
19669
|
+
attached: true,
|
|
19670
|
+
...clientId ? { clientId } : {},
|
|
19671
|
+
createdAt: new Date(this.task.startTime).toISOString(),
|
|
19672
|
+
hasActivePrompt: this.task.status === "running",
|
|
19673
|
+
state: {},
|
|
19674
|
+
compactedReplay: snapshot.events,
|
|
19675
|
+
liveJournal: [],
|
|
19676
|
+
historyHasMore: false,
|
|
19677
|
+
lastEventId: snapshot.lastEventId
|
|
19678
|
+
};
|
|
19679
|
+
}
|
|
19680
|
+
async *iterate(opts) {
|
|
19681
|
+
if (this.retentionTimer) {
|
|
19682
|
+
clearTimeout(this.retentionTimer);
|
|
19683
|
+
this.retentionTimer = void 0;
|
|
19684
|
+
}
|
|
19685
|
+
this.subscribers++;
|
|
19686
|
+
try {
|
|
19687
|
+
await this.refreshLive();
|
|
19688
|
+
if (!this.snapshotDelivered) {
|
|
19689
|
+
this.events.length = 0;
|
|
19690
|
+
this.snapshotDelivered = true;
|
|
19691
|
+
}
|
|
19692
|
+
if (this.task.status === "running" && !this.pollTimer) {
|
|
19693
|
+
this.pollTimer = setInterval(() => {
|
|
19694
|
+
void this.refreshLive().catch(() => void 0);
|
|
19695
|
+
}, POLL_INTERVAL_MS);
|
|
19696
|
+
this.pollTimer.unref();
|
|
19697
|
+
}
|
|
19698
|
+
yield* this.bus.subscribe(opts);
|
|
19699
|
+
} finally {
|
|
19700
|
+
this.subscribers--;
|
|
19701
|
+
if (this.subscribers === 0) {
|
|
19702
|
+
if (this.pollTimer) clearInterval(this.pollTimer);
|
|
19703
|
+
this.pollTimer = void 0;
|
|
19704
|
+
this.scheduleRetention();
|
|
19705
|
+
}
|
|
19706
|
+
}
|
|
19707
|
+
}
|
|
19708
|
+
subscribe(opts) {
|
|
19709
|
+
return {
|
|
19710
|
+
[Symbol.asyncIterator]: () => this.iterate(opts)
|
|
19711
|
+
};
|
|
19712
|
+
}
|
|
19713
|
+
scheduleRetention() {
|
|
19714
|
+
if (this.retentionTimer) clearTimeout(this.retentionTimer);
|
|
19715
|
+
this.retentionTimer = setTimeout(this.onExpired, TARGET_RETENTION_MS);
|
|
19716
|
+
this.retentionTimer.unref();
|
|
19717
|
+
}
|
|
19718
|
+
};
|
|
19719
|
+
var VirtualSubagentSessions = class {
|
|
19720
|
+
static {
|
|
19721
|
+
__name(this, "VirtualSubagentSessions");
|
|
19722
|
+
}
|
|
19723
|
+
targets = /* @__PURE__ */ new Map();
|
|
19724
|
+
async findTask(runtime, parentSessionId, predicate) {
|
|
19725
|
+
const status = await runtime.bridge.getSessionTasksStatus(parentSessionId);
|
|
19726
|
+
const task = status.tasks.find(
|
|
19727
|
+
(candidate) => candidate.kind === "agent" && typeof candidate.outputFile === "string" && predicate(candidate)
|
|
19728
|
+
);
|
|
19729
|
+
if (task?.kind === "agent" && task.outputFile) {
|
|
19730
|
+
return {
|
|
19731
|
+
id: task.id,
|
|
19732
|
+
title: task.label,
|
|
19733
|
+
outputFile: task.outputFile,
|
|
19734
|
+
status: task.status,
|
|
19735
|
+
startTime: task.startTime,
|
|
19736
|
+
durationMs: task.stats?.durationMs ?? (task.endTime === void 0 ? void 0 : Math.max(0, task.endTime - task.startTime)),
|
|
19737
|
+
totalTokens: task.stats?.totalTokens
|
|
19738
|
+
};
|
|
19739
|
+
}
|
|
19740
|
+
const runtimeDir = runtime.env.effectiveEnv?.["QWEN_RUNTIME_DIR"];
|
|
19741
|
+
const projectDir = Storage.runWithRuntimeBaseDir(
|
|
19742
|
+
runtimeDir,
|
|
19743
|
+
runtime.workspaceCwd,
|
|
19744
|
+
() => new Storage(runtime.workspaceCwd).getProjectDir()
|
|
19745
|
+
);
|
|
19746
|
+
const sessionDir = getSubagentSessionDir(projectDir, parentSessionId);
|
|
19747
|
+
let names;
|
|
19748
|
+
try {
|
|
19749
|
+
names = await fs3.readdir(sessionDir);
|
|
19750
|
+
} catch (error2) {
|
|
19751
|
+
if (error2.code === "ENOENT") return void 0;
|
|
19752
|
+
throw error2;
|
|
19753
|
+
}
|
|
19754
|
+
for (const name of names) {
|
|
19755
|
+
if (!name.endsWith(".meta.json")) continue;
|
|
19756
|
+
const metaPath = `${sessionDir}/${name}`;
|
|
19757
|
+
const meta = readAgentMeta(metaPath);
|
|
19758
|
+
if (!meta || !predicate({
|
|
19759
|
+
kind: "agent",
|
|
19760
|
+
id: meta.agentId,
|
|
19761
|
+
toolUseId: meta.toolUseId,
|
|
19762
|
+
outputFile: metaPath.slice(0, -".meta.json".length) + ".jsonl"
|
|
19763
|
+
})) {
|
|
19764
|
+
continue;
|
|
19765
|
+
}
|
|
19766
|
+
return {
|
|
19767
|
+
id: meta.agentId,
|
|
19768
|
+
title: meta.description || meta.agentType,
|
|
19769
|
+
outputFile: metaPath.slice(0, -".meta.json".length) + ".jsonl",
|
|
19770
|
+
status: meta.status ?? "completed",
|
|
19771
|
+
startTime: Number.isFinite(Date.parse(meta.createdAt)) ? Date.parse(meta.createdAt) : Date.now(),
|
|
19772
|
+
durationMs: durationBetween(meta.createdAt, meta.lastUpdatedAt)
|
|
19773
|
+
};
|
|
19774
|
+
}
|
|
19775
|
+
return void 0;
|
|
19776
|
+
}
|
|
19777
|
+
async findLegacyTaskByToolCall(runtime, parentSessionId, toolCallId) {
|
|
19778
|
+
const runtimeDir = runtime.env.effectiveEnv?.["QWEN_RUNTIME_DIR"];
|
|
19779
|
+
const projectDir = Storage.runWithRuntimeBaseDir(
|
|
19780
|
+
runtimeDir,
|
|
19781
|
+
runtime.workspaceCwd,
|
|
19782
|
+
() => new Storage(runtime.workspaceCwd).getProjectDir()
|
|
19783
|
+
);
|
|
19784
|
+
const parentRecords = await read(
|
|
19785
|
+
`${projectDir}/chats/${parentSessionId}.jsonl`
|
|
19786
|
+
);
|
|
19787
|
+
let root;
|
|
19788
|
+
for (const record of parentRecords) {
|
|
19789
|
+
for (const part of record.message?.parts ?? []) {
|
|
19790
|
+
const call = part.functionCall;
|
|
19791
|
+
if (call?.id !== toolCallId || call.name !== "agent") continue;
|
|
19792
|
+
const args = call.args;
|
|
19793
|
+
root = {
|
|
19794
|
+
timestamp: Date.parse(record.timestamp),
|
|
19795
|
+
...typeof args?.["description"] === "string" ? { description: args["description"] } : {},
|
|
19796
|
+
...typeof args?.["prompt"] === "string" ? { prompt: args["prompt"] } : {},
|
|
19797
|
+
...typeof args?.["subagent_type"] === "string" ? { agentType: args["subagent_type"] } : {}
|
|
19798
|
+
};
|
|
19799
|
+
break;
|
|
19800
|
+
}
|
|
19801
|
+
if (root) break;
|
|
19802
|
+
}
|
|
19803
|
+
if (!root) return void 0;
|
|
19804
|
+
const sessionDir = getSubagentSessionDir(projectDir, parentSessionId);
|
|
19805
|
+
let names;
|
|
19806
|
+
try {
|
|
19807
|
+
names = await fs3.readdir(sessionDir);
|
|
19808
|
+
} catch (error2) {
|
|
19809
|
+
if (error2.code === "ENOENT") return void 0;
|
|
19810
|
+
throw error2;
|
|
19811
|
+
}
|
|
19812
|
+
const candidates = [];
|
|
19813
|
+
for (const name of names) {
|
|
19814
|
+
if (!name.endsWith(".meta.json")) continue;
|
|
19815
|
+
const metaPath = `${sessionDir}/${name}`;
|
|
19816
|
+
const meta = readAgentMeta(metaPath);
|
|
19817
|
+
if (!meta) continue;
|
|
19818
|
+
const outputFile = metaPath.slice(0, -".meta.json".length) + ".jsonl";
|
|
19819
|
+
const launchPrompt = await readFirstUserText(outputFile);
|
|
19820
|
+
let score = 0;
|
|
19821
|
+
if (root.prompt && launchPrompt === root.prompt) score += 8;
|
|
19822
|
+
if (root.description && meta.description === root.description) score += 4;
|
|
19823
|
+
if (root.agentType && meta.agentType === root.agentType) score += 2;
|
|
19824
|
+
const startTime = Date.parse(meta.createdAt);
|
|
19825
|
+
const delta = Math.abs(startTime - root.timestamp);
|
|
19826
|
+
if (Number.isFinite(delta) && delta <= 6e4) score += 1;
|
|
19827
|
+
if (score === 0) continue;
|
|
19828
|
+
candidates.push({
|
|
19829
|
+
id: meta.agentId,
|
|
19830
|
+
title: meta.description || meta.agentType,
|
|
19831
|
+
outputFile,
|
|
19832
|
+
status: meta.status ?? "completed",
|
|
19833
|
+
startTime: Number.isFinite(startTime) ? startTime : Date.now(),
|
|
19834
|
+
durationMs: durationBetween(meta.createdAt, meta.lastUpdatedAt),
|
|
19835
|
+
score,
|
|
19836
|
+
delta
|
|
19837
|
+
});
|
|
19838
|
+
}
|
|
19839
|
+
candidates.sort((a, b) => b.score - a.score || a.delta - b.delta);
|
|
19840
|
+
const selected = candidates[0];
|
|
19841
|
+
if (!selected) return void 0;
|
|
19842
|
+
const metrics = findToolCallMetrics(parentRecords, toolCallId);
|
|
19843
|
+
return {
|
|
19844
|
+
...selected,
|
|
19845
|
+
status: metrics.status ?? selected.status,
|
|
19846
|
+
durationMs: metrics.durationMs ?? selected.durationMs,
|
|
19847
|
+
totalTokens: metrics.totalTokens ?? selected.totalTokens,
|
|
19848
|
+
inputTokens: metrics.inputTokens ?? selected.inputTokens,
|
|
19849
|
+
outputTokens: metrics.outputTokens ?? selected.outputTokens,
|
|
19850
|
+
cachedTokens: metrics.cachedTokens ?? selected.cachedTokens
|
|
19851
|
+
};
|
|
19852
|
+
}
|
|
19853
|
+
async readParentToolCallMetrics(runtime, parentSessionId, toolCallId) {
|
|
19854
|
+
const runtimeDir = runtime.env.effectiveEnv?.["QWEN_RUNTIME_DIR"];
|
|
19855
|
+
const projectDir = Storage.runWithRuntimeBaseDir(
|
|
19856
|
+
runtimeDir,
|
|
19857
|
+
runtime.workspaceCwd,
|
|
19858
|
+
() => new Storage(runtime.workspaceCwd).getProjectDir()
|
|
19859
|
+
);
|
|
19860
|
+
const records = await read(
|
|
19861
|
+
`${projectDir}/chats/${parentSessionId}.jsonl`
|
|
19862
|
+
);
|
|
19863
|
+
return findToolCallMetrics(records, toolCallId);
|
|
19864
|
+
}
|
|
19865
|
+
async resolve(runtime, parentSessionId, toolCallId) {
|
|
19866
|
+
let task = await this.findTask(
|
|
19867
|
+
runtime,
|
|
19868
|
+
parentSessionId,
|
|
19869
|
+
(candidate) => candidate.toolUseId === toolCallId || candidate.id.endsWith(`-${toolCallId}`)
|
|
19870
|
+
);
|
|
19871
|
+
const metrics = task && task.status !== "running" ? await this.readParentToolCallMetrics(
|
|
19872
|
+
runtime,
|
|
19873
|
+
parentSessionId,
|
|
19874
|
+
toolCallId
|
|
19875
|
+
) : void 0;
|
|
19876
|
+
task ??= await this.findLegacyTaskByToolCall(
|
|
19877
|
+
runtime,
|
|
19878
|
+
parentSessionId,
|
|
19879
|
+
toolCallId
|
|
19880
|
+
);
|
|
19881
|
+
if (!task) return void 0;
|
|
19882
|
+
const sessionId = createVirtualSubagentSessionId(parentSessionId, task.id);
|
|
19883
|
+
const status = task.status;
|
|
19884
|
+
this.targets.get(`${runtime.workspaceId}:${sessionId}`)?.updateStatus(status);
|
|
19885
|
+
return {
|
|
19886
|
+
sessionId,
|
|
19887
|
+
taskId: task.id,
|
|
19888
|
+
title: task.title,
|
|
19889
|
+
status,
|
|
19890
|
+
durationMs: metrics?.durationMs ?? task.durationMs,
|
|
19891
|
+
totalTokens: metrics?.totalTokens ?? task.totalTokens,
|
|
19892
|
+
inputTokens: metrics?.inputTokens ?? task.inputTokens,
|
|
19893
|
+
outputTokens: metrics?.outputTokens ?? task.outputTokens,
|
|
19894
|
+
cachedTokens: metrics?.cachedTokens ?? task.cachedTokens
|
|
19895
|
+
};
|
|
19896
|
+
}
|
|
19897
|
+
async getTarget(runtime, sessionId) {
|
|
19898
|
+
const targetKey = `${runtime.workspaceId}:${sessionId}`;
|
|
19899
|
+
const cached = this.targets.get(targetKey);
|
|
19900
|
+
if (cached) return cached;
|
|
19901
|
+
const key = parseVirtualSubagentSessionId(sessionId);
|
|
19902
|
+
if (!key) return void 0;
|
|
19903
|
+
const task = await this.findTask(
|
|
19904
|
+
runtime,
|
|
19905
|
+
key.parentSessionId,
|
|
19906
|
+
(candidate) => candidate.id === key.agentId
|
|
19907
|
+
);
|
|
19908
|
+
if (!task) return void 0;
|
|
19909
|
+
const existing = this.targets.get(targetKey);
|
|
19910
|
+
if (existing) return existing;
|
|
19911
|
+
const target = new VirtualSubagentTarget(
|
|
19912
|
+
sessionId,
|
|
19913
|
+
key.parentSessionId,
|
|
19914
|
+
task,
|
|
19915
|
+
runtime.workspaceCwd,
|
|
19916
|
+
() => this.targets.delete(targetKey)
|
|
19917
|
+
);
|
|
19918
|
+
this.targets.set(targetKey, target);
|
|
19919
|
+
return target;
|
|
19920
|
+
}
|
|
19921
|
+
async load(runtime, sessionId, clientId) {
|
|
19922
|
+
return (await this.getTarget(runtime, sessionId))?.load(clientId);
|
|
19923
|
+
}
|
|
19924
|
+
async subscribe(runtime, sessionId, opts) {
|
|
19925
|
+
return (await this.getTarget(runtime, sessionId))?.subscribe(opts);
|
|
19926
|
+
}
|
|
19927
|
+
};
|
|
19928
|
+
|
|
19202
19929
|
// packages/cli/src/serve/routes/session.ts
|
|
19203
19930
|
var WORKSPACE_TRANSCRIPT_RESPONSE_MAX_BYTES = 32 * 1024 * 1024;
|
|
19204
19931
|
var WORKSPACE_TRANSCRIPT_CURSOR_MAX_BYTES = 64 * 1024;
|
|
@@ -19261,8 +19988,8 @@ function isReadOnlyWorkspaceInspection(runtime) {
|
|
|
19261
19988
|
return !runtime.primary && !runtime.trusted;
|
|
19262
19989
|
}
|
|
19263
19990
|
__name(isReadOnlyWorkspaceInspection, "isReadOnlyWorkspaceInspection");
|
|
19264
|
-
function runWorkspaceInspectionWithLogPolicy(runtime,
|
|
19265
|
-
return isReadOnlyWorkspaceInspection(runtime) ? runWithoutDebugLogSession(
|
|
19991
|
+
function runWorkspaceInspectionWithLogPolicy(runtime, read2) {
|
|
19992
|
+
return isReadOnlyWorkspaceInspection(runtime) ? runWithoutDebugLogSession(read2) : read2();
|
|
19266
19993
|
}
|
|
19267
19994
|
__name(runWorkspaceInspectionWithLogPolicy, "runWorkspaceInspectionWithLogPolicy");
|
|
19268
19995
|
function requireSessionArtifactClientId(clientId, res) {
|
|
@@ -19425,7 +20152,8 @@ function registerSessionRoutes(app, deps) {
|
|
|
19425
20152
|
sendBridgeError: sendBridgeError2,
|
|
19426
20153
|
daemonLog,
|
|
19427
20154
|
promptDeadlineMs,
|
|
19428
|
-
sessionShellCommandEnabled
|
|
20155
|
+
sessionShellCommandEnabled,
|
|
20156
|
+
virtualSubagentSessions
|
|
19429
20157
|
} = deps;
|
|
19430
20158
|
const LANGUAGE_CODES = deps.languageCodes;
|
|
19431
20159
|
const transcriptCursorMasterKey = crypto3.randomBytes(32);
|
|
@@ -20194,6 +20922,55 @@ function registerSessionRoutes(app, deps) {
|
|
|
20194
20922
|
const restoreSessionHandler = /* @__PURE__ */ __name((action) => async (req, res) => {
|
|
20195
20923
|
const sessionId = requireSessionId(req, res);
|
|
20196
20924
|
if (!sessionId) return;
|
|
20925
|
+
const virtualKey = parseVirtualSubagentSessionId(sessionId);
|
|
20926
|
+
if (virtualKey) {
|
|
20927
|
+
const route2 = `POST /session/:id/${action}`;
|
|
20928
|
+
if (action !== "load") {
|
|
20929
|
+
res.status(400).json({
|
|
20930
|
+
error: `Virtual subagent sessions do not support ${action}`,
|
|
20931
|
+
code: "unsupported_action",
|
|
20932
|
+
sessionId
|
|
20933
|
+
});
|
|
20934
|
+
return;
|
|
20935
|
+
}
|
|
20936
|
+
if (!virtualSubagentSessions) {
|
|
20937
|
+
res.status(404).json({
|
|
20938
|
+
error: `No session with id "${sessionId}"`,
|
|
20939
|
+
code: "session_not_found",
|
|
20940
|
+
sessionId
|
|
20941
|
+
});
|
|
20942
|
+
return;
|
|
20943
|
+
}
|
|
20944
|
+
const runtime2 = requireSessionRuntime({
|
|
20945
|
+
sessionId: virtualKey.parentSessionId,
|
|
20946
|
+
route: route2,
|
|
20947
|
+
res,
|
|
20948
|
+
workspaceRegistry,
|
|
20949
|
+
daemonLog
|
|
20950
|
+
});
|
|
20951
|
+
if (!runtime2) return;
|
|
20952
|
+
const clientId2 = parseClientIdHeader(req, res);
|
|
20953
|
+
if (clientId2 === null) return;
|
|
20954
|
+
try {
|
|
20955
|
+
const session = await virtualSubagentSessions.load(
|
|
20956
|
+
runtime2,
|
|
20957
|
+
sessionId,
|
|
20958
|
+
clientId2
|
|
20959
|
+
);
|
|
20960
|
+
if (!session) {
|
|
20961
|
+
res.status(404).json({
|
|
20962
|
+
error: "Subagent session not found",
|
|
20963
|
+
code: "session_not_found",
|
|
20964
|
+
sessionId
|
|
20965
|
+
});
|
|
20966
|
+
return;
|
|
20967
|
+
}
|
|
20968
|
+
res.status(200).json(session);
|
|
20969
|
+
} catch (err) {
|
|
20970
|
+
sendBridgeError2(res, err, { route: route2, sessionId });
|
|
20971
|
+
}
|
|
20972
|
+
return;
|
|
20973
|
+
}
|
|
20197
20974
|
const body = safeBody(req);
|
|
20198
20975
|
const route = `POST /session/:id/${action}`;
|
|
20199
20976
|
let resolvedRuntime;
|
|
@@ -20283,7 +21060,7 @@ function registerSessionRoutes(app, deps) {
|
|
|
20283
21060
|
path10.join(workspaceCwd, ".qwen", "worktrees")
|
|
20284
21061
|
];
|
|
20285
21062
|
try {
|
|
20286
|
-
realTarget =
|
|
21063
|
+
realTarget = fs4.realpathSync(sidecar.worktreePath);
|
|
20287
21064
|
let repoTop = null;
|
|
20288
21065
|
try {
|
|
20289
21066
|
repoTop = await new GitWorktreeService(
|
|
@@ -20296,7 +21073,7 @@ function registerSessionRoutes(app, deps) {
|
|
|
20296
21073
|
}
|
|
20297
21074
|
const contained = candidateRoots.some((root) => {
|
|
20298
21075
|
try {
|
|
20299
|
-
const realRoot =
|
|
21076
|
+
const realRoot = fs4.realpathSync(root);
|
|
20300
21077
|
const rel = path10.relative(realRoot, realTarget);
|
|
20301
21078
|
return !rel.startsWith("..") && !path10.isAbsolute(rel);
|
|
20302
21079
|
} catch {
|
|
@@ -20351,6 +21128,112 @@ function registerSessionRoutes(app, deps) {
|
|
|
20351
21128
|
}, "restoreSessionHandler");
|
|
20352
21129
|
app.post("/session/:id/load", mutate(), restoreSessionHandler("load"));
|
|
20353
21130
|
app.post("/session/:id/resume", mutate(), restoreSessionHandler("resume"));
|
|
21131
|
+
app.get("/session/:id/subagents/:toolCallId", async (req, res) => {
|
|
21132
|
+
const route = "GET /session/:id/subagents/:toolCallId";
|
|
21133
|
+
const sessionId = requireSessionId(req, res);
|
|
21134
|
+
if (!sessionId) return;
|
|
21135
|
+
if (!virtualSubagentSessions) {
|
|
21136
|
+
res.status(404).json({
|
|
21137
|
+
error: `No session with id "${sessionId}"`,
|
|
21138
|
+
code: "session_not_found",
|
|
21139
|
+
sessionId
|
|
21140
|
+
});
|
|
21141
|
+
return;
|
|
21142
|
+
}
|
|
21143
|
+
const toolCallId = req.params["toolCallId"];
|
|
21144
|
+
if (!toolCallId || toolCallId.length > 500) {
|
|
21145
|
+
res.status(400).json({
|
|
21146
|
+
error: "`toolCallId` must be a non-empty tool call id",
|
|
21147
|
+
code: "invalid_tool_call_id"
|
|
21148
|
+
});
|
|
21149
|
+
return;
|
|
21150
|
+
}
|
|
21151
|
+
const runtime = requireSessionRuntime({
|
|
21152
|
+
sessionId,
|
|
21153
|
+
route,
|
|
21154
|
+
res,
|
|
21155
|
+
workspaceRegistry,
|
|
21156
|
+
daemonLog
|
|
21157
|
+
});
|
|
21158
|
+
if (!runtime) return;
|
|
21159
|
+
try {
|
|
21160
|
+
const resolved = await virtualSubagentSessions.resolve(
|
|
21161
|
+
runtime,
|
|
21162
|
+
sessionId,
|
|
21163
|
+
toolCallId
|
|
21164
|
+
);
|
|
21165
|
+
if (!resolved) {
|
|
21166
|
+
res.status(404).json({
|
|
21167
|
+
error: "Subagent session not found",
|
|
21168
|
+
code: "session_not_found",
|
|
21169
|
+
sessionId,
|
|
21170
|
+
toolCallId
|
|
21171
|
+
});
|
|
21172
|
+
return;
|
|
21173
|
+
}
|
|
21174
|
+
res.status(200).set("Cache-Control", "no-store").json(resolved);
|
|
21175
|
+
} catch (err) {
|
|
21176
|
+
sendBridgeError2(res, err, { route, sessionId });
|
|
21177
|
+
}
|
|
21178
|
+
});
|
|
21179
|
+
app.post(
|
|
21180
|
+
"/session/:id/subagents/:toolCallId/cancel",
|
|
21181
|
+
mutate(),
|
|
21182
|
+
async (req, res) => {
|
|
21183
|
+
const route = "POST /session/:id/subagents/:toolCallId/cancel";
|
|
21184
|
+
const sessionId = requireSessionId(req, res);
|
|
21185
|
+
if (!sessionId) return;
|
|
21186
|
+
if (!virtualSubagentSessions) {
|
|
21187
|
+
res.status(404).json({
|
|
21188
|
+
error: `No session with id "${sessionId}"`,
|
|
21189
|
+
code: "session_not_found",
|
|
21190
|
+
sessionId
|
|
21191
|
+
});
|
|
21192
|
+
return;
|
|
21193
|
+
}
|
|
21194
|
+
const toolCallId = req.params["toolCallId"];
|
|
21195
|
+
if (!toolCallId || toolCallId.length > 500) {
|
|
21196
|
+
res.status(400).json({
|
|
21197
|
+
error: "`toolCallId` must be a non-empty tool call id",
|
|
21198
|
+
code: "invalid_tool_call_id"
|
|
21199
|
+
});
|
|
21200
|
+
return;
|
|
21201
|
+
}
|
|
21202
|
+
const runtime = requireSessionRuntime({
|
|
21203
|
+
sessionId,
|
|
21204
|
+
route,
|
|
21205
|
+
res,
|
|
21206
|
+
workspaceRegistry,
|
|
21207
|
+
daemonLog
|
|
21208
|
+
});
|
|
21209
|
+
if (!runtime) return;
|
|
21210
|
+
try {
|
|
21211
|
+
const resolved = await virtualSubagentSessions.resolve(
|
|
21212
|
+
runtime,
|
|
21213
|
+
sessionId,
|
|
21214
|
+
toolCallId
|
|
21215
|
+
);
|
|
21216
|
+
if (!resolved) {
|
|
21217
|
+
res.status(404).json({
|
|
21218
|
+
error: "Subagent session not found",
|
|
21219
|
+
code: "session_not_found",
|
|
21220
|
+
sessionId,
|
|
21221
|
+
toolCallId
|
|
21222
|
+
});
|
|
21223
|
+
return;
|
|
21224
|
+
}
|
|
21225
|
+
res.status(200).json(
|
|
21226
|
+
await runtime.bridge.cancelSessionTask(
|
|
21227
|
+
sessionId,
|
|
21228
|
+
resolved.taskId,
|
|
21229
|
+
"agent"
|
|
21230
|
+
)
|
|
21231
|
+
);
|
|
21232
|
+
} catch (err) {
|
|
21233
|
+
sendBridgeError2(res, err, { route, sessionId });
|
|
21234
|
+
}
|
|
21235
|
+
}
|
|
21236
|
+
);
|
|
20354
21237
|
app.post(
|
|
20355
21238
|
"/session/:id/branch",
|
|
20356
21239
|
mutate(),
|
|
@@ -20650,6 +21533,28 @@ function registerSessionRoutes(app, deps) {
|
|
|
20650
21533
|
});
|
|
20651
21534
|
app.get(
|
|
20652
21535
|
"/session/:id/context",
|
|
21536
|
+
(req, res, next) => {
|
|
21537
|
+
const sessionId = req.params["id"];
|
|
21538
|
+
const key = sessionId ? parseVirtualSubagentSessionId(sessionId) : void 0;
|
|
21539
|
+
if (!sessionId || !key) {
|
|
21540
|
+
next();
|
|
21541
|
+
return;
|
|
21542
|
+
}
|
|
21543
|
+
const runtime = requireSessionRuntime({
|
|
21544
|
+
sessionId: key.parentSessionId,
|
|
21545
|
+
route: "GET /session/:id/context",
|
|
21546
|
+
res,
|
|
21547
|
+
workspaceRegistry,
|
|
21548
|
+
daemonLog
|
|
21549
|
+
});
|
|
21550
|
+
if (!runtime) return;
|
|
21551
|
+
res.status(200).json({
|
|
21552
|
+
v: 1,
|
|
21553
|
+
sessionId,
|
|
21554
|
+
workspaceCwd: runtime.workspaceCwd,
|
|
21555
|
+
state: {}
|
|
21556
|
+
});
|
|
21557
|
+
},
|
|
20653
21558
|
withOwnerReadSession(
|
|
20654
21559
|
"GET /session/:id/context",
|
|
20655
21560
|
async (_req, res, sessionId, runtime) => {
|
|
@@ -20681,6 +21586,28 @@ function registerSessionRoutes(app, deps) {
|
|
|
20681
21586
|
);
|
|
20682
21587
|
app.get(
|
|
20683
21588
|
"/session/:id/supported-commands",
|
|
21589
|
+
(req, res, next) => {
|
|
21590
|
+
const sessionId = req.params["id"];
|
|
21591
|
+
const key = sessionId ? parseVirtualSubagentSessionId(sessionId) : void 0;
|
|
21592
|
+
if (!sessionId || !key) {
|
|
21593
|
+
next();
|
|
21594
|
+
return;
|
|
21595
|
+
}
|
|
21596
|
+
const runtime = requireSessionRuntime({
|
|
21597
|
+
sessionId: key.parentSessionId,
|
|
21598
|
+
route: "GET /session/:id/supported-commands",
|
|
21599
|
+
res,
|
|
21600
|
+
workspaceRegistry,
|
|
21601
|
+
daemonLog
|
|
21602
|
+
});
|
|
21603
|
+
if (!runtime) return;
|
|
21604
|
+
res.status(200).json({
|
|
21605
|
+
v: 1,
|
|
21606
|
+
sessionId,
|
|
21607
|
+
availableCommands: [],
|
|
21608
|
+
availableSkills: []
|
|
21609
|
+
});
|
|
21610
|
+
},
|
|
20684
21611
|
withOwnerReadSession(
|
|
20685
21612
|
"GET /session/:id/supported-commands",
|
|
20686
21613
|
async (_req, res, sessionId, runtime) => {
|
|
@@ -21077,6 +22004,29 @@ function registerSessionRoutes(app, deps) {
|
|
|
21077
22004
|
app.post(
|
|
21078
22005
|
"/session/:id/heartbeat",
|
|
21079
22006
|
mutate(),
|
|
22007
|
+
(req, res, next) => {
|
|
22008
|
+
const sessionId = req.params["id"];
|
|
22009
|
+
const key = sessionId ? parseVirtualSubagentSessionId(sessionId) : void 0;
|
|
22010
|
+
if (!sessionId || !key) {
|
|
22011
|
+
next();
|
|
22012
|
+
return;
|
|
22013
|
+
}
|
|
22014
|
+
const runtime = requireSessionRuntime({
|
|
22015
|
+
sessionId: key.parentSessionId,
|
|
22016
|
+
route: "POST /session/:id/heartbeat",
|
|
22017
|
+
res,
|
|
22018
|
+
workspaceRegistry,
|
|
22019
|
+
daemonLog
|
|
22020
|
+
});
|
|
22021
|
+
if (!runtime) return;
|
|
22022
|
+
const clientId = parseClientIdHeader(req, res);
|
|
22023
|
+
if (clientId === null) return;
|
|
22024
|
+
res.status(200).json({
|
|
22025
|
+
sessionId,
|
|
22026
|
+
...clientId ? { clientId } : {},
|
|
22027
|
+
lastSeenAt: Date.now()
|
|
22028
|
+
});
|
|
22029
|
+
},
|
|
21080
22030
|
withOwnerMutableSession(
|
|
21081
22031
|
"POST /session/:id/heartbeat",
|
|
21082
22032
|
(req, res, sessionId, runtime) => {
|
|
@@ -21093,6 +22043,25 @@ function registerSessionRoutes(app, deps) {
|
|
|
21093
22043
|
app.post(
|
|
21094
22044
|
"/session/:id/detach",
|
|
21095
22045
|
mutate(),
|
|
22046
|
+
(req, res, next) => {
|
|
22047
|
+
const sessionId = req.params["id"];
|
|
22048
|
+
const key = sessionId ? parseVirtualSubagentSessionId(sessionId) : void 0;
|
|
22049
|
+
if (!sessionId || !key) {
|
|
22050
|
+
next();
|
|
22051
|
+
return;
|
|
22052
|
+
}
|
|
22053
|
+
const runtime = requireSessionRuntime({
|
|
22054
|
+
sessionId: key.parentSessionId,
|
|
22055
|
+
route: "POST /session/:id/detach",
|
|
22056
|
+
res,
|
|
22057
|
+
workspaceRegistry,
|
|
22058
|
+
daemonLog
|
|
22059
|
+
});
|
|
22060
|
+
if (!runtime) return;
|
|
22061
|
+
const clientId = parseClientIdHeader(req, res);
|
|
22062
|
+
if (clientId === null) return;
|
|
22063
|
+
res.status(204).end();
|
|
22064
|
+
},
|
|
21096
22065
|
withOwnerMutableSession(
|
|
21097
22066
|
"POST /session/:id/detach",
|
|
21098
22067
|
async (req, res, sessionId, runtime) => {
|
|
@@ -23481,7 +24450,9 @@ function createServeFeatures(deps) {
|
|
|
23481
24450
|
channelControlAvailable,
|
|
23482
24451
|
sessionShellCommandEnabled,
|
|
23483
24452
|
multiWorkspaceSessionsEnabled,
|
|
24453
|
+
dynamicWorkspaceRegistrationAvailable,
|
|
23484
24454
|
persistentWorkspaceRegistrationAvailable,
|
|
24455
|
+
scratchWorkspaceRegistrationAvailable,
|
|
23485
24456
|
workspaceRuntimeRemovalAvailable
|
|
23486
24457
|
} = deps;
|
|
23487
24458
|
const env = deps.env ?? process.env;
|
|
@@ -23515,7 +24486,9 @@ function createServeFeatures(deps) {
|
|
|
23515
24486
|
channelReloadAvailable: channelReloadAvailable(),
|
|
23516
24487
|
channelControlAvailable,
|
|
23517
24488
|
multiWorkspaceSessionsEnabled: multiWorkspaceSessionsEnabled(),
|
|
24489
|
+
dynamicWorkspaceRegistrationAvailable,
|
|
23518
24490
|
persistentWorkspaceRegistrationAvailable,
|
|
24491
|
+
scratchWorkspaceRegistrationAvailable: scratchWorkspaceRegistrationAvailable(),
|
|
23519
24492
|
workspaceRuntimeRemovalAvailable,
|
|
23520
24493
|
acpHttpEnabled: resolveAcpHttpEnabled(),
|
|
23521
24494
|
clientMcpOverWsEnabled: opts.clientMcpOverWs === true,
|
|
@@ -24853,7 +25826,7 @@ data: ${dataJson}
|
|
|
24853
25826
|
__name(formatSseFrame, "formatSseFrame");
|
|
24854
25827
|
function registerSseEventsRoutes(app, deps) {
|
|
24855
25828
|
const { workspaceRegistry, daemonLog, sendBridgeError: sendBridgeError2, writerIdleTimeoutMs } = deps;
|
|
24856
|
-
app.get("/session/:id/events", (req, res) => {
|
|
25829
|
+
app.get("/session/:id/events", async (req, res) => {
|
|
24857
25830
|
const sessionId = req.params["id"];
|
|
24858
25831
|
const lastEventId = parseLastEventId(req.headers["last-event-id"]);
|
|
24859
25832
|
const maxQueued = parseMaxQueuedQuery(req.query["maxQueued"], res);
|
|
@@ -24861,8 +25834,9 @@ function registerSseEventsRoutes(app, deps) {
|
|
|
24861
25834
|
let iter;
|
|
24862
25835
|
const abort = new AbortController();
|
|
24863
25836
|
try {
|
|
25837
|
+
const virtualKey = parseVirtualSubagentSessionId(sessionId);
|
|
24864
25838
|
const runtime = requireSessionRuntime({
|
|
24865
|
-
sessionId,
|
|
25839
|
+
sessionId: virtualKey?.parentSessionId ?? sessionId,
|
|
24866
25840
|
route: "GET /session/:id/events",
|
|
24867
25841
|
res,
|
|
24868
25842
|
workspaceRegistry,
|
|
@@ -24870,12 +25844,24 @@ function registerSseEventsRoutes(app, deps) {
|
|
|
24870
25844
|
});
|
|
24871
25845
|
if (!runtime) return;
|
|
24872
25846
|
const snapshot = req.query["snapshot"] === "1";
|
|
24873
|
-
const iterable =
|
|
25847
|
+
const iterable = virtualKey ? await deps.virtualSubagentSessions?.subscribe(runtime, sessionId, {
|
|
25848
|
+
signal: abort.signal,
|
|
25849
|
+
lastEventId,
|
|
25850
|
+
...maxQueued !== void 0 ? { maxQueued } : {}
|
|
25851
|
+
}) : runtime.bridge.subscribeEvents(sessionId, {
|
|
24874
25852
|
signal: abort.signal,
|
|
24875
25853
|
lastEventId,
|
|
24876
25854
|
...maxQueued !== void 0 ? { maxQueued } : {},
|
|
24877
25855
|
...snapshot ? { snapshot: true } : {}
|
|
24878
25856
|
});
|
|
25857
|
+
if (!iterable) {
|
|
25858
|
+
res.status(404).json({
|
|
25859
|
+
error: "Subagent session not found",
|
|
25860
|
+
code: "session_not_found",
|
|
25861
|
+
sessionId
|
|
25862
|
+
});
|
|
25863
|
+
return;
|
|
25864
|
+
}
|
|
24879
25865
|
iter = iterable[Symbol.asyncIterator]();
|
|
24880
25866
|
} catch (err) {
|
|
24881
25867
|
if (err instanceof SubscriberLimitExceededError) {
|
|
@@ -26029,7 +27015,7 @@ __name(registerWorkspaceQualifiedLifecycleRoutes, "registerWorkspaceQualifiedLif
|
|
|
26029
27015
|
|
|
26030
27016
|
// packages/cli/src/serve/routes/workspace-management.ts
|
|
26031
27017
|
init_esbuild_shims();
|
|
26032
|
-
import { readdir, stat } from "node:fs/promises";
|
|
27018
|
+
import { readdir as readdir2, stat as stat2 } from "node:fs/promises";
|
|
26033
27019
|
import { realpathSync as realpathSync2 } from "node:fs";
|
|
26034
27020
|
import { basename as basename4, dirname as dirname4, isAbsolute as isAbsolute7, join as join8, resolve as resolve4, sep as sep3 } from "node:path";
|
|
26035
27021
|
var MAX_PATH_SUGGESTIONS = 50;
|
|
@@ -26039,6 +27025,7 @@ function registerWorkspaceManagementRoutes(app, deps) {
|
|
|
26039
27025
|
mutate,
|
|
26040
27026
|
safeBody: safeBody2,
|
|
26041
27027
|
createWorkspaceRuntime,
|
|
27028
|
+
managedScratchRoot,
|
|
26042
27029
|
workspaceRegistrationStore,
|
|
26043
27030
|
getAcpHandle,
|
|
26044
27031
|
runtimeRemoval
|
|
@@ -26046,6 +27033,7 @@ function registerWorkspaceManagementRoutes(app, deps) {
|
|
|
26046
27033
|
const inFlight = /* @__PURE__ */ new Map();
|
|
26047
27034
|
let sealed = false;
|
|
26048
27035
|
let activeOperations = 0;
|
|
27036
|
+
let pendingScratchCreations = 0;
|
|
26049
27037
|
const idleWaiters = /* @__PURE__ */ new Set();
|
|
26050
27038
|
const operationStarted = /* @__PURE__ */ __name(() => {
|
|
26051
27039
|
activeOperations++;
|
|
@@ -26087,6 +27075,135 @@ function registerWorkspaceManagementRoutes(app, deps) {
|
|
|
26087
27075
|
runtime.displayName = storedDisplayName;
|
|
26088
27076
|
}
|
|
26089
27077
|
}, "restorePersistedDisplayName");
|
|
27078
|
+
const projectedWorkspaceCount = /* @__PURE__ */ __name(() => {
|
|
27079
|
+
const cwdSet = new Set(
|
|
27080
|
+
workspaceRegistry.listManaged().map((runtime) => runtime.workspaceCwd)
|
|
27081
|
+
);
|
|
27082
|
+
for (const [cwd, operation] of inFlight) {
|
|
27083
|
+
if (operation === "addition") cwdSet.add(cwd);
|
|
27084
|
+
}
|
|
27085
|
+
return cwdSet.size + pendingScratchCreations;
|
|
27086
|
+
}, "projectedWorkspaceCount");
|
|
27087
|
+
const createScratchWorkspace = /* @__PURE__ */ __name(async (res) => {
|
|
27088
|
+
if (!createWorkspaceRuntime || !managedScratchRoot || !runtimeRemoval) {
|
|
27089
|
+
res.status(501).json({
|
|
27090
|
+
error: "Scratch workspace registration is not available",
|
|
27091
|
+
code: "scratch_not_available"
|
|
27092
|
+
});
|
|
27093
|
+
return;
|
|
27094
|
+
}
|
|
27095
|
+
if (sealed) {
|
|
27096
|
+
sendSealed(res);
|
|
27097
|
+
return;
|
|
27098
|
+
}
|
|
27099
|
+
if (workspaceRegistry.listManaged().some(
|
|
27100
|
+
(runtime2) => !isScratchRootCompatible(
|
|
27101
|
+
runtime2.workspaceCwd,
|
|
27102
|
+
managedScratchRoot.canonicalRoot
|
|
27103
|
+
)
|
|
27104
|
+
) || [...inFlight].some(
|
|
27105
|
+
([cwd, operation]) => operation === "addition" && !isScratchRootCompatible(cwd, managedScratchRoot.canonicalRoot)
|
|
27106
|
+
)) {
|
|
27107
|
+
res.status(409).json({
|
|
27108
|
+
error: "Managed scratch root conflicts with a registered workspace",
|
|
27109
|
+
code: "scratch_root_conflict"
|
|
27110
|
+
});
|
|
27111
|
+
return;
|
|
27112
|
+
}
|
|
27113
|
+
if (projectedWorkspaceCount() >= MAX_REGISTERED_WORKSPACES) {
|
|
27114
|
+
res.status(409).json({
|
|
27115
|
+
error: "Workspace registration limit reached",
|
|
27116
|
+
code: "workspace_limit_reached"
|
|
27117
|
+
});
|
|
27118
|
+
return;
|
|
27119
|
+
}
|
|
27120
|
+
pendingScratchCreations++;
|
|
27121
|
+
operationStarted();
|
|
27122
|
+
let reservationHeld = true;
|
|
27123
|
+
let canonical;
|
|
27124
|
+
let runtime;
|
|
27125
|
+
let registered = false;
|
|
27126
|
+
try {
|
|
27127
|
+
canonical = await createManagedScratchDirectory(managedScratchRoot);
|
|
27128
|
+
if (sealed) {
|
|
27129
|
+
sendSealed(res);
|
|
27130
|
+
return;
|
|
27131
|
+
}
|
|
27132
|
+
pendingScratchCreations--;
|
|
27133
|
+
reservationHeld = false;
|
|
27134
|
+
inFlight.set(canonical, "addition");
|
|
27135
|
+
const boundCwds = workspaceRegistry.listManaged().map((entry) => entry.workspaceCwd);
|
|
27136
|
+
for (const [cwd, operation] of inFlight) {
|
|
27137
|
+
if (operation === "addition" && cwd !== canonical) boundCwds.push(cwd);
|
|
27138
|
+
}
|
|
27139
|
+
if (boundCwds.some(
|
|
27140
|
+
(cwd) => !isScratchRootCompatible(cwd, managedScratchRoot.canonicalRoot) || isWithinRoot(canonical, cwd) || isWithinRoot(cwd, canonical)
|
|
27141
|
+
)) {
|
|
27142
|
+
res.status(409).json({
|
|
27143
|
+
error: "Workspace path nests with an existing workspace",
|
|
27144
|
+
code: "workspace_nested"
|
|
27145
|
+
});
|
|
27146
|
+
return;
|
|
27147
|
+
}
|
|
27148
|
+
if (sealed) {
|
|
27149
|
+
sendSealed(res);
|
|
27150
|
+
return;
|
|
27151
|
+
}
|
|
27152
|
+
runtime = await createWorkspaceRuntime(canonical, {
|
|
27153
|
+
provenance: "managed-scratch"
|
|
27154
|
+
});
|
|
27155
|
+
if (runtime.workspaceCwd !== canonical || runtime.primary || !runtime.trusted) {
|
|
27156
|
+
throw new Error(
|
|
27157
|
+
"Scratch runtime violated the managed runtime contract"
|
|
27158
|
+
);
|
|
27159
|
+
}
|
|
27160
|
+
if (sealed) {
|
|
27161
|
+
sendSealed(res);
|
|
27162
|
+
return;
|
|
27163
|
+
}
|
|
27164
|
+
workspaceRegistry.add(runtime);
|
|
27165
|
+
registered = true;
|
|
27166
|
+
try {
|
|
27167
|
+
await runtimeRemoval.runtimeAdded?.(runtime);
|
|
27168
|
+
} catch (err) {
|
|
27169
|
+
try {
|
|
27170
|
+
writeStderrLine(
|
|
27171
|
+
`qwen serve: workspace runtime adapter notification failed after registry add: ${err instanceof Error ? err.message : String(err)}`
|
|
27172
|
+
);
|
|
27173
|
+
} catch {
|
|
27174
|
+
}
|
|
27175
|
+
}
|
|
27176
|
+
res.status(201).json({
|
|
27177
|
+
id: runtime.workspaceId,
|
|
27178
|
+
cwd: runtime.workspaceCwd,
|
|
27179
|
+
primary: false,
|
|
27180
|
+
trusted: true,
|
|
27181
|
+
persisted: false
|
|
27182
|
+
});
|
|
27183
|
+
} catch (err) {
|
|
27184
|
+
writeStderrLine(
|
|
27185
|
+
`qwen serve: scratch workspace registration failed: ${err instanceof Error ? err.message : String(err)}${canonical ? `; retained directory: ${canonical}` : ""}`
|
|
27186
|
+
);
|
|
27187
|
+
if (!res.headersSent) {
|
|
27188
|
+
res.status(500).json({
|
|
27189
|
+
error: "Failed to register scratch workspace",
|
|
27190
|
+
code: "runtime_creation_failed"
|
|
27191
|
+
});
|
|
27192
|
+
}
|
|
27193
|
+
} finally {
|
|
27194
|
+
if (runtime && !registered) {
|
|
27195
|
+
await runtimeRemoval.disposeRuntime(runtime, "workspace_removed").catch(() => {
|
|
27196
|
+
try {
|
|
27197
|
+
runtime?.bridge.killAllSync();
|
|
27198
|
+
} catch {
|
|
27199
|
+
}
|
|
27200
|
+
});
|
|
27201
|
+
}
|
|
27202
|
+
if (reservationHeld) pendingScratchCreations--;
|
|
27203
|
+
if (canonical) inFlight.delete(canonical);
|
|
27204
|
+
operationFinished();
|
|
27205
|
+
}
|
|
27206
|
+
}, "createScratchWorkspace");
|
|
26090
27207
|
app.get(
|
|
26091
27208
|
"/workspace-path-suggestions",
|
|
26092
27209
|
async (req, res) => {
|
|
@@ -26120,7 +27237,7 @@ function registerWorkspaceManagementRoutes(app, deps) {
|
|
|
26120
27237
|
const suggestions = [];
|
|
26121
27238
|
let truncated = false;
|
|
26122
27239
|
try {
|
|
26123
|
-
const entries = await
|
|
27240
|
+
const entries = await readdir2(dir, { withFileTypes: true });
|
|
26124
27241
|
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
26125
27242
|
for (const entry of entries) {
|
|
26126
27243
|
if (entry.name.startsWith(".") && !filter.startsWith(".")) continue;
|
|
@@ -26130,7 +27247,7 @@ function registerWorkspaceManagementRoutes(app, deps) {
|
|
|
26130
27247
|
let isDir = entry.isDirectory();
|
|
26131
27248
|
if (!isDir && entry.isSymbolicLink()) {
|
|
26132
27249
|
try {
|
|
26133
|
-
isDir = (await
|
|
27250
|
+
isDir = (await stat2(join8(dir, entry.name))).isDirectory();
|
|
26134
27251
|
} catch {
|
|
26135
27252
|
continue;
|
|
26136
27253
|
}
|
|
@@ -26158,6 +27275,17 @@ function registerWorkspaceManagementRoutes(app, deps) {
|
|
|
26158
27275
|
mutate({ strict: true }),
|
|
26159
27276
|
async (req, res) => {
|
|
26160
27277
|
const body = safeBody2(req);
|
|
27278
|
+
if ("kind" in body) {
|
|
27279
|
+
if (body["kind"] !== "scratch" || "cwd" in body || "persist" in body || Object.keys(body).some((key) => key !== "kind")) {
|
|
27280
|
+
res.status(400).json({
|
|
27281
|
+
error: 'Scratch workspace requests must be exactly { kind: "scratch" }',
|
|
27282
|
+
code: "invalid_workspace_request"
|
|
27283
|
+
});
|
|
27284
|
+
return;
|
|
27285
|
+
}
|
|
27286
|
+
await createScratchWorkspace(res);
|
|
27287
|
+
return;
|
|
27288
|
+
}
|
|
26161
27289
|
const cwd = body["cwd"];
|
|
26162
27290
|
const persist = body["persist"] ?? false;
|
|
26163
27291
|
const hasDisplayName = Object.hasOwn(body, "displayName");
|
|
@@ -26227,12 +27355,19 @@ function registerWorkspaceManagementRoutes(app, deps) {
|
|
|
26227
27355
|
});
|
|
26228
27356
|
return;
|
|
26229
27357
|
}
|
|
27358
|
+
if (managedScratchRoot && !isScratchRootCompatible(canonical, managedScratchRoot.canonicalRoot)) {
|
|
27359
|
+
res.status(409).json({
|
|
27360
|
+
error: "Workspace path conflicts with the managed scratch root",
|
|
27361
|
+
code: "scratch_root_conflict"
|
|
27362
|
+
});
|
|
27363
|
+
return;
|
|
27364
|
+
}
|
|
26230
27365
|
if (sealed) {
|
|
26231
27366
|
sendSealed(res);
|
|
26232
27367
|
return;
|
|
26233
27368
|
}
|
|
26234
27369
|
try {
|
|
26235
|
-
const s = await
|
|
27370
|
+
const s = await stat2(canonical);
|
|
26236
27371
|
if (!s.isDirectory()) {
|
|
26237
27372
|
res.status(400).json({
|
|
26238
27373
|
error: "Path is not a directory",
|
|
@@ -26411,13 +27546,7 @@ function registerWorkspaceManagementRoutes(app, deps) {
|
|
|
26411
27546
|
return;
|
|
26412
27547
|
}
|
|
26413
27548
|
}
|
|
26414
|
-
|
|
26415
|
-
workspaceRegistry.listManaged().map((runtime) => runtime.workspaceCwd)
|
|
26416
|
-
);
|
|
26417
|
-
for (const [cwd2, operation] of inFlight) {
|
|
26418
|
-
if (operation === "addition") projectedWorkspaceCwds.add(cwd2);
|
|
26419
|
-
}
|
|
26420
|
-
if (projectedWorkspaceCwds.size >= MAX_REGISTERED_WORKSPACES) {
|
|
27549
|
+
if (projectedWorkspaceCount() >= MAX_REGISTERED_WORKSPACES) {
|
|
26421
27550
|
res.status(409).json({
|
|
26422
27551
|
error: "Workspace registration limit reached",
|
|
26423
27552
|
code: "workspace_limit_reached"
|
|
@@ -26428,7 +27557,9 @@ function registerWorkspaceManagementRoutes(app, deps) {
|
|
|
26428
27557
|
operationStarted();
|
|
26429
27558
|
let persistenceFailed = false;
|
|
26430
27559
|
try {
|
|
26431
|
-
const runtime = await createWorkspaceRuntime(canonical
|
|
27560
|
+
const runtime = await createWorkspaceRuntime(canonical, {
|
|
27561
|
+
provenance: "existing"
|
|
27562
|
+
});
|
|
26432
27563
|
if (!persist && displayName !== void 0) {
|
|
26433
27564
|
runtime.displayName = displayName;
|
|
26434
27565
|
}
|
|
@@ -27039,7 +28170,7 @@ __name(registerWorkspaceManagementRoutes, "registerWorkspaceManagementRoutes");
|
|
|
27039
28170
|
|
|
27040
28171
|
// packages/cli/src/serve/routes/workspace-git.ts
|
|
27041
28172
|
init_esbuild_shims();
|
|
27042
|
-
import * as
|
|
28173
|
+
import * as fs5 from "node:fs";
|
|
27043
28174
|
import * as path14 from "node:path";
|
|
27044
28175
|
function registerWorkspaceGitRoutes(app, deps) {
|
|
27045
28176
|
app.get("/workspace/git", async (_req, res) => {
|
|
@@ -27066,8 +28197,8 @@ function registerWorkspaceQualifiedGitRoutes(app, deps) {
|
|
|
27066
28197
|
let gitCwd = runtime.workspaceCwd;
|
|
27067
28198
|
if (typeof rawCwd === "string" && rawCwd.length > 0) {
|
|
27068
28199
|
try {
|
|
27069
|
-
const resolved =
|
|
27070
|
-
const root =
|
|
28200
|
+
const resolved = fs5.realpathSync(path14.resolve(rawCwd));
|
|
28201
|
+
const root = fs5.realpathSync(runtime.workspaceCwd);
|
|
27071
28202
|
const rel = path14.relative(root, resolved);
|
|
27072
28203
|
if (!rel.startsWith("..") && !path14.isAbsolute(rel)) {
|
|
27073
28204
|
gitCwd = resolved;
|
|
@@ -29115,7 +30246,16 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
29115
30246
|
}, "channelReloadAvailable"),
|
|
29116
30247
|
sessionShellCommandEnabled,
|
|
29117
30248
|
multiWorkspaceSessionsEnabled: /* @__PURE__ */ __name(() => workspaceRegistry.list().length > 1, "multiWorkspaceSessionsEnabled"),
|
|
30249
|
+
dynamicWorkspaceRegistrationAvailable: deps.createWorkspaceRuntime !== void 0,
|
|
29118
30250
|
persistentWorkspaceRegistrationAvailable: deps.workspaceRegistrationStore !== void 0,
|
|
30251
|
+
// Scratch creation is advertised only while every managed runtime still
|
|
30252
|
+
// respects the root boundary and a complete disposal owner is present.
|
|
30253
|
+
scratchWorkspaceRegistrationAvailable: /* @__PURE__ */ __name(() => deps.createWorkspaceRuntime !== void 0 && deps.managedScratchRoot !== void 0 && deps.workspaceRuntimeRemoval !== void 0 && workspaceRegistry.listManaged().every(
|
|
30254
|
+
(runtime) => isScratchRootCompatible(
|
|
30255
|
+
runtime.workspaceCwd,
|
|
30256
|
+
deps.managedScratchRoot.canonicalRoot
|
|
30257
|
+
)
|
|
30258
|
+
), "scratchWorkspaceRegistrationAvailable"),
|
|
29119
30259
|
workspaceRuntimeRemovalAvailable: deps.workspaceRuntimeRemoval !== void 0,
|
|
29120
30260
|
...primaryEffectiveEnv ? { env: primaryEffectiveEnv } : {}
|
|
29121
30261
|
});
|
|
@@ -29522,6 +30662,7 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
29522
30662
|
mutate,
|
|
29523
30663
|
safeBody,
|
|
29524
30664
|
createWorkspaceRuntime: deps.createWorkspaceRuntime,
|
|
30665
|
+
managedScratchRoot: deps.managedScratchRoot,
|
|
29525
30666
|
workspaceRegistrationStore: deps.workspaceRegistrationStore,
|
|
29526
30667
|
getAcpHandle: /* @__PURE__ */ __name(() => acpHandleRef.current, "getAcpHandle"),
|
|
29527
30668
|
runtimeRemoval: deps.workspaceRuntimeRemoval
|
|
@@ -29625,6 +30766,7 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
29625
30766
|
allowPrivateAuthBaseUrl: opts.allowPrivateAuthBaseUrl === true,
|
|
29626
30767
|
installAuthProvider: deps.installAuthProvider
|
|
29627
30768
|
});
|
|
30769
|
+
const virtualSubagentSessions = new VirtualSubagentSessions();
|
|
29628
30770
|
registerSessionRoutes(app, {
|
|
29629
30771
|
boundWorkspace: primaryBoundWorkspace,
|
|
29630
30772
|
bridge: primaryBridge,
|
|
@@ -29635,7 +30777,8 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
29635
30777
|
daemonLog,
|
|
29636
30778
|
promptDeadlineMs: opts.promptDeadlineMs,
|
|
29637
30779
|
sessionShellCommandEnabled,
|
|
29638
|
-
languageCodes
|
|
30780
|
+
languageCodes,
|
|
30781
|
+
virtualSubagentSessions
|
|
29639
30782
|
});
|
|
29640
30783
|
registerWorkspaceMcpControlRoutes(app, {
|
|
29641
30784
|
boundWorkspace: primaryBoundWorkspace,
|
|
@@ -29801,7 +30944,8 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
29801
30944
|
workspaceRegistry,
|
|
29802
30945
|
daemonLog,
|
|
29803
30946
|
writerIdleTimeoutMs: opts.writerIdleTimeoutMs,
|
|
29804
|
-
sendBridgeError: sendBridgeError2
|
|
30947
|
+
sendBridgeError: sendBridgeError2,
|
|
30948
|
+
virtualSubagentSessions
|
|
29805
30949
|
});
|
|
29806
30950
|
acpHandleRef.current = mountAcpHttp(app, primaryBridge, {
|
|
29807
30951
|
boundWorkspace: primaryBoundWorkspace,
|