@qwen-code/qwen-code 0.21.8 → 0.21.9
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/README.md +2 -1
- package/bundled/qc-helper/docs/configuration/settings.md +32 -30
- package/bundled/qc-helper/docs/extension/introduction.md +15 -1
- package/bundled/qc-helper/docs/features/code-review.md +2 -0
- package/bundled/qc-helper/docs/qwen-serve-deploy-local.md +1 -1
- package/bundled/qc-helper/docs/qwen-serve.md +42 -39
- package/bundled/review/SKILL.md +11 -7
- package/chunks/{MaxSizedBox-7PM6BGJ5.js → MaxSizedBox-6BZANW7X.js} +9 -9
- package/chunks/{StandaloneSessionPicker-3UQHM7GV.js → StandaloneSessionPicker-VDC5KE7T.js} +28 -25
- package/chunks/{acpAgent-5UWLFV6V.js → acpAgent-F2NSBCUF.js} +1433 -706
- package/chunks/{agent-624T2BLO.js → agent-VOHJOEBB.js} +8 -8
- package/chunks/{agent-headless-2EE5J2KX.js → agent-headless-J5NFOPHP.js} +8 -8
- package/chunks/{bridge-JENKGFFP.js → bridge-NQIZZLAS.js} +13 -13
- package/chunks/{channel-management-service-DDWUPHMU.js → channel-management-service-PHELKOW2.js} +4 -4
- package/chunks/{channel-settings-store-SA6JZSPH.js → channel-settings-store-VIY2OENO.js} +17 -15
- package/chunks/{channel-worker-group-E67EN3RV.js → channel-worker-group-MSHT6CWR.js} +6 -6
- package/chunks/{channel-worker-manager-SW4C45CF.js → channel-worker-manager-XXD3GDSK.js} +6 -6
- package/chunks/{channel-worker-supervisor-5SRD24FG.js → channel-worker-supervisor-IVSDIMI4.js} +4 -4
- package/chunks/{chunk-S3Y3GBFD.js → chunk-23VQTELM.js} +2 -2
- package/chunks/{chunk-XZKQT2B2.js → chunk-3WDYBTTI.js} +5 -5
- package/chunks/{chunk-YEF7XEO2.js → chunk-3XVDTHBJ.js} +3 -3
- package/chunks/{chunk-IBYULW65.js → chunk-46YJDYCU.js} +145 -10
- package/chunks/chunk-4JRM2BSM.js +48 -0
- package/chunks/{chunk-L4N6TIP7.js → chunk-4TRQPFDP.js} +4 -2
- package/chunks/{chunk-5ZGR6RKJ.js → chunk-4XQNB3KN.js} +3 -3
- package/chunks/chunk-5EJZE3FP.js +140 -0
- package/chunks/{chunk-XHD7CRP2.js → chunk-5RBDAGC6.js} +2 -2
- package/chunks/{chunk-KJZ26VBX.js → chunk-67EWJE77.js} +1 -1
- package/chunks/{chunk-TE3ZAJE7.js → chunk-6Q5ABMTU.js} +1 -1
- package/chunks/{chunk-U5SLIG7E.js → chunk-7AEPJGL4.js} +1 -1
- package/chunks/{chunk-OHKJVAKG.js → chunk-7GOYZQPR.js} +20 -1977
- package/chunks/{chunk-3SE7J4DR.js → chunk-7S4JBJLU.js} +3 -3
- package/chunks/{chunk-TKSZJ5BV.js → chunk-AKJQSWV4.js} +3 -3
- package/chunks/{chunk-E4ZBKMSF.js → chunk-ATMO54WE.js} +6 -6
- package/chunks/{chunk-KKDVZLGL.js → chunk-BAMN6XSD.js} +1 -1
- package/chunks/{chunk-IUQ52YJK.js → chunk-BIRWP6LU.js} +1 -1
- package/chunks/{chunk-AKA24BGO.js → chunk-BT6GQIEJ.js} +1 -1
- package/chunks/{chunk-ZCLLJARV.js → chunk-BZP4QPNK.js} +10 -10
- package/chunks/{chunk-2M5N3DHY.js → chunk-CMOBWHWW.js} +1 -1
- package/chunks/{chunk-WV5J6Q6N.js → chunk-D7BXVKSF.js} +1 -1
- package/chunks/{chunk-NLREQJFK.js → chunk-DA4HRSBW.js} +15 -0
- package/chunks/{chunk-GOEVOFQI.js → chunk-DH5YXSIF.js} +3 -3
- package/chunks/{chunk-DIWZNWZT.js → chunk-DX3RGJMS.js} +13 -2
- package/chunks/{chunk-PLFATELK.js → chunk-DZUO626D.js} +1 -1
- package/chunks/{chunk-NGYI5EF5.js → chunk-E2FPSSKP.js} +8 -8
- package/chunks/{chunk-ZPLALRXZ.js → chunk-FBMCDU63.js} +4 -137
- package/chunks/{chunk-2ILAOM2I.js → chunk-FCLHHEUK.js} +17 -16
- package/chunks/{chunk-SNRT2TJJ.js → chunk-G2TX5ZXC.js} +3 -3
- package/chunks/{chunk-C5VWPTGT.js → chunk-GAKGOXTC.js} +1 -1
- package/chunks/{chunk-QQWD7LZV.js → chunk-HADWBW5R.js} +4 -4
- package/chunks/{chunk-77QVBFCU.js → chunk-HZGBKOX3.js} +3 -3
- package/chunks/{chunk-RPWVIXDB.js → chunk-I5VM3SKY.js} +4 -4
- package/chunks/{chunk-7VUERJHS.js → chunk-II6G3EY6.js} +325 -104
- package/chunks/{chunk-FN6YXJOP.js → chunk-IOEZE2YT.js} +1 -1
- package/chunks/chunk-JUWS2Z5K.js +1995 -0
- package/chunks/{chunk-VXZ5HAOV.js → chunk-K4ADGWHU.js} +1 -1
- package/chunks/{chunk-YOM7DEGB.js → chunk-KSAFZ5TA.js} +2 -2
- package/chunks/{chunk-KAQCJO6Y.js → chunk-KTKYGS2P.js} +35 -9
- package/chunks/{chunk-GBDINRIL.js → chunk-KTQGGPGV.js} +3 -3
- package/chunks/{chunk-6M26GBKX.js → chunk-L2AFWWJE.js} +42 -3
- package/chunks/{chunk-QXVSWG66.js → chunk-LHEC5V6G.js} +2 -2
- package/chunks/{chunk-J26HHFI5.js → chunk-LP2QGNSP.js} +32 -2
- package/chunks/{chunk-HWX5HPUG.js → chunk-LZZLUCRS.js} +108 -11
- package/chunks/{chunk-KTJFU7RT.js → chunk-MFDYOYZZ.js} +2 -2
- package/chunks/{chunk-3WNQOYHQ.js → chunk-MHP476D3.js} +74 -31
- package/chunks/{chunk-Y4TETC74.js → chunk-MTCYGTWH.js} +4 -4
- package/chunks/{chunk-EN2TKTFH.js → chunk-NV3F44FL.js} +6 -2
- package/chunks/{chunk-BF52U4XJ.js → chunk-OGDIJKHK.js} +1 -1
- package/chunks/{chunk-7DVT4LVV.js → chunk-OGNFHGIG.js} +3 -3
- package/chunks/{chunk-IYES5WOT.js → chunk-P2FK2HBV.js} +2 -2
- package/chunks/{chunk-2M4K4KYS.js → chunk-P3RBMQ4P.js} +4 -4
- package/chunks/{chunk-FYAXKJK7.js → chunk-P4ZEZSJZ.js} +692 -106
- package/chunks/{chunk-UFALT4LK.js → chunk-PBRVUF5B.js} +1 -1
- package/chunks/{chunk-LKRMNRSN.js → chunk-PDPFQ2FO.js} +2 -0
- package/chunks/{chunk-6TR7CFXH.js → chunk-PNBBJOCP.js} +1 -1
- package/chunks/{chunk-M3STHEMM.js → chunk-PVOGHGSF.js} +5 -5
- package/chunks/{chunk-4WU6NY7F.js → chunk-QSNSL4R4.js} +2 -2
- package/chunks/{chunk-DQSDACD2.js → chunk-RBHQXGDK.js} +1 -1
- package/chunks/{chunk-ZHA242R4.js → chunk-RVSTTOJ4.js} +2 -2
- package/chunks/{chunk-EIVICVHM.js → chunk-SCAZZ3Q4.js} +4 -4
- package/chunks/{chunk-BF224XHL.js → chunk-T5RLUXWJ.js} +2 -2
- package/chunks/{chunk-B52AWKBB.js → chunk-T6HEQR2Q.js} +16 -5
- package/chunks/{chunk-FWBXMANW.js → chunk-THIKWITR.js} +3 -3
- package/chunks/{chunk-WG6542MA.js → chunk-TQCYNLNJ.js} +1 -1
- package/chunks/chunk-TQOF5KBL.js +71 -0
- package/chunks/{chunk-NPUXXRJI.js → chunk-TZ6KJ44L.js} +1 -1
- package/chunks/{chunk-YHJFF7KH.js → chunk-UJUM2SRN.js} +147 -47
- package/chunks/{chunk-4ALIARFY.js → chunk-UYAUA63Q.js} +1 -1
- package/chunks/chunk-VFMASYQA.js +389 -0
- package/chunks/chunk-VGHZT6JR.js +51 -0
- package/chunks/{chunk-ZWBUH5UP.js → chunk-VKJ4KTPJ.js} +1 -1
- package/chunks/{chunk-QGHSP65Z.js → chunk-VNNWAZSI.js} +2 -2
- package/chunks/{chunk-757GB46F.js → chunk-W3FSZSF2.js} +1 -1
- package/chunks/{chunk-GQCEQPYQ.js → chunk-WGK4TSB7.js} +3 -3
- package/chunks/{chunk-PG62DFWD.js → chunk-WP5VOXF7.js} +6 -127
- package/chunks/{chunk-NVRDQFCX.js → chunk-XTY5DN4Y.js} +1 -1
- package/chunks/{chunk-GXSNGY5M.js → chunk-XX7QFP34.js} +1677 -1307
- package/chunks/{chunk-3PY4LPJF.js → chunk-YGT2AUJ7.js} +84 -4
- package/chunks/{chunk-4DU3NCHG.js → chunk-YTFDX4PR.js} +8 -3
- package/chunks/{chunk-OA4JVLSA.js → chunk-Z7VOMGDC.js} +22 -1
- package/chunks/{chunk-DX5W5AON.js → chunk-ZBXGWQ4S.js} +3 -3
- package/chunks/chunk-ZLBIFIMV.js +1099 -0
- package/chunks/{chunk-HA3SAB64.js → chunk-ZOSTTOUJ.js} +1 -1
- package/chunks/{chunk-VWMUDKLC.js → chunk-ZTQSOV56.js} +4 -4
- package/chunks/{computer-use-ESQYJ3JY.js → computer-use-PMZ7ICGY.js} +8 -8
- package/chunks/{config-utils-XQHBJP7G.js → config-utils-ULCSRMWD.js} +4 -4
- package/chunks/{contextCommand-CX3YF4ZE.js → contextCommand-GEZU7YHE.js} +11 -10
- package/chunks/{core-runtime-DIAU7JMG.js → core-runtime-HRJI2MN6.js} +8 -8
- package/chunks/{create-sub-session-HDPD6HOA.js → create-sub-session-VBNVI4YU.js} +9 -9
- package/chunks/{daemon-VZBGJUNL.js → daemon-POSQPD3G.js} +115 -7
- package/chunks/{daemon-status-provider-H6O4UQ4F.js → daemon-status-provider-N4CRQKFI.js} +18 -18
- package/chunks/{daemon-trust-policy-BNUXG6MT.js → daemon-trust-policy-BHO3JUHM.js} +16 -14
- package/chunks/{daemon-trust-policy-monitor-E4EQ7GF4.js → daemon-trust-policy-monitor-YEKJ2726.js} +16 -14
- package/chunks/{deferred-core-runtime-CBMSHPAU.js → deferred-core-runtime-SH57E3J3.js} +8 -8
- package/chunks/{dist-KVISB2O2.js → dist-3NTTUAHT.js} +1 -1
- package/chunks/{dist-RCH3I7SS.js → dist-6BMOAE3Z.js} +2 -2
- package/chunks/{dist-IRL7WA5Z.js → dist-B2CGTW6T.js} +1 -1
- package/chunks/{dist-TUSWNE2I.js → dist-EWW3J4HQ.js} +1 -1
- package/chunks/{dist-HIACTZEK.js → dist-EZE3V3Q7.js} +1 -1
- package/chunks/{dist-EEEQGCZA.js → dist-J47AXBZC.js} +1 -1
- package/chunks/{dist-MKX5OSFF.js → dist-OTUO3AS2.js} +4 -1088
- package/chunks/{dist-MBF3I5MX.js → dist-Z3CS4OVP.js} +1 -1
- package/chunks/{earlyInputCapture-UIOP7OIN.js → earlyInputCapture-B2JJ2HME.js} +8 -8
- package/chunks/{edit-ITMZYFKA.js → edit-7FTXENAN.js} +10 -8
- package/chunks/{enter-worktree-S4PL5UV6.js → enter-worktree-JPHV2PBG.js} +8 -8
- package/chunks/{enterPlanMode-YV52NNJT.js → enterPlanMode-CGBJ3AHJ.js} +8 -8
- package/chunks/{environment-NGOWPRZV.js → environment-LXASZAHD.js} +11 -11
- package/chunks/{errors-BU26DTDX.js → errors-XIGVT2AD.js} +10 -10
- package/chunks/{exit-worktree-XRM6LH5F.js → exit-worktree-DKSGXW65.js} +8 -8
- package/chunks/{exitPlanMode-ZLI5F7KR.js → exitPlanMode-THFL2HYN.js} +8 -8
- package/chunks/{fast-path-UJWORIED.js → fast-path-4NXAT5UL.js} +4 -3
- package/chunks/{fast-path-settings-37WQD5B2.js → fast-path-settings-RPAVBD7P.js} +2 -2
- package/chunks/{gemini-ZSKNDUMU.js → gemini-B3N6FACU.js} +56 -60
- package/chunks/{geminiContentGenerator-YGEXOEKD.js → geminiContentGenerator-YYFE2HIE.js} +1 -1
- package/chunks/{glob-7KZG44BR.js → glob-BPHSCFJP.js} +8 -8
- package/chunks/{grep-6ZFC7RJ5.js → grep-ROZIRFLU.js} +8 -8
- package/chunks/{handleAutoUpdate-KSEL3TQS.js → handleAutoUpdate-WV6SPZQB.js} +13 -12
- package/chunks/{i18n-ZIUXBW5V.js → i18n-YWJWPQKD.js} +13 -11
- package/chunks/{image-gen-AUIZJJNK.js → image-gen-SISRZ6FS.js} +1 -1
- package/chunks/{initializer-7AHY3N6Q.js → initializer-66OAD6GO.js} +16 -14
- package/chunks/{installationInfo-VGBXMYLY.js → installationInfo-3YUGIP36.js} +9 -9
- package/chunks/{list-PSFKQHLB.js → list-VEYR66XB.js} +19 -17
- package/chunks/{loadedSettingsAdapter-FTMRCTOF.js → loadedSettingsAdapter-V2JCPCYD.js} +16 -14
- package/chunks/{loggingContentGenerator-MZAN52UV.js → loggingContentGenerator-RBLNDREC.js} +6 -6
- package/chunks/main-PXAUXNF2.js +8 -0
- package/chunks/{managed-npm-update-O4NHK45X.js → managed-npm-update-C5ID5R4R.js} +9 -9
- package/chunks/{mcp-6CFP2AYQ.js → mcp-OZ54NZJQ.js} +16 -14
- package/chunks/{monitor-DAKD6OU4.js → monitor-7Y4TVFTK.js} +18 -14
- package/chunks/{nonInteractiveCli-RC7VIUZL.js → nonInteractiveCli-QEK4LHAC.js} +51 -49
- package/chunks/{notebook-edit-474DPMRL.js → notebook-edit-OG35EBGY.js} +9 -8
- package/chunks/{openaiContentGenerator-2NFY2MWO.js → openaiContentGenerator-443BNRPJ.js} +5 -5
- package/chunks/{pidfile-KBFVDNQP.js → pidfile-ZK4OLRZA.js} +8 -8
- package/chunks/{processUtils-6GRYH4Y3.js → processUtils-4YGB4RUZ.js} +2 -2
- package/chunks/{qwenContentGenerator-KAHU6IZY.js → qwenContentGenerator-D5C2LCSZ.js} +9 -9
- package/chunks/{qwenOAuth2-RRQTCP4W.js → qwenOAuth2-Z4YQBMYN.js} +1 -1
- package/chunks/{read-file-3M6WXDXP.js → read-file-EXTJLWMU.js} +4 -4
- package/chunks/{resumeHistoryUtils-D6TAY3HX.js → resumeHistoryUtils-UPCGRJUL.js} +13 -12
- package/chunks/{ripGrep-PLPENT3E.js → ripGrep-QBVIRCU4.js} +8 -8
- package/chunks/{run-qwen-serve-ZAFIJKJC.js → run-qwen-serve-ZYGJNE3E.js} +169 -68
- package/chunks/{runtime-ZED7CYOZ.js → runtime-BZZ4LWCP.js} +21 -19
- package/chunks/{scheduler-MD3AL2W5.js → scheduler-YNQNOU2E.js} +135 -15
- package/chunks/{sdk-exporters-http-KHAB5JSD.js → sdk-exporters-http-XVTZQRCE.js} +2 -2
- package/chunks/{sdk-impl-KD7FSTC3.js → sdk-impl-7W7AKCS4.js} +7 -3
- package/chunks/{serve-E3VUDRZN.js → serve-LJHAXDCH.js} +18 -14
- package/chunks/{server-OWMEMAKR.js → server-ADMLELR6.js} +1229 -1098
- package/chunks/{session-HZ57QK7K.js → session-YKZXFFTM.js} +55 -53
- package/chunks/{settings-V7BR3RKP.js → settings-EQBUAQ7Y.js} +15 -13
- package/chunks/{shell-23OMNMW6.js → shell-3QZOJGTT.js} +8 -8
- package/chunks/{skill-6HBDYZRS.js → skill-UWSSMXE7.js} +5 -5
- package/chunks/{skill-settings-HWJLTU7M.js → skill-settings-T6MLB7NU.js} +15 -13
- package/chunks/{spawnChannel-N6KKUW5B.js → spawnChannel-VS7ZFUFP.js} +11 -11
- package/chunks/{standalone-update-QGIKHATD.js → standalone-update-2W26SRRO.js} +11 -10
- package/chunks/{startInteractiveUI-GX2CRL42.js → startInteractiveUI-CVS7K3D6.js} +86 -75
- package/chunks/{team-create-CFFKU7KL.js → team-create-4WFTNNUL.js} +8 -8
- package/chunks/{team-plan-approval-6EFOKR6A.js → team-plan-approval-DBYI33S3.js} +8 -8
- package/chunks/{terminal-image-renderer-TLDNACQY.js → terminal-image-renderer-S5WPPQKH.js} +8 -8
- package/chunks/{theme-manager-5LJ3H7VO.js → theme-manager-LI2RIOVR.js} +8 -8
- package/chunks/{tool-search-UJV3A24H.js → tool-search-4773EUQ4.js} +4 -4
- package/chunks/{total-session-admission-D63QYXGO.js → total-session-admission-PAY5CH2Z.js} +16 -15
- package/chunks/{trustedFolders-KZCOB53W.js → trustedFolders-FRSLE674.js} +9 -9
- package/chunks/{types-ML3TRJQ5.js → types-WYCFCEHR.js} +5 -3
- package/chunks/{update-relaunch-IFILM3SA.js → update-relaunch-ZSFQTU6M.js} +5 -5
- package/chunks/{updateCheck-YZ2CRCFC.js → updateCheck-AXWSO7KA.js} +12 -11
- package/chunks/{useAutoAcceptIndicator-AXEVNA3Q.js → useAutoAcceptIndicator-VHLXIA7U.js} +18 -16
- package/chunks/{validateNonInterActiveAuth-3WTOJFWA.js → validateNonInterActiveAuth-PDJECMFU.js} +48 -46
- package/chunks/{version-GXK7OHZY.js → version-RBN764QS.js} +1 -1
- package/chunks/{web-fetch-ILB4GAVR.js → web-fetch-7BJK42AF.js} +4 -4
- package/chunks/{web-search-HKRPGPZZ.js → web-search-L2CILQXV.js} +4 -3
- package/chunks/{workflow-FXIPRQQA.js → workflow-5VH2R74I.js} +170 -137
- package/chunks/{workspace-providers-status-NYHC7HSR.js → workspace-providers-status-OZTQ6JFH.js} +19 -17
- package/chunks/{workspace-registration-store-AKEB7OMW.js → workspace-registration-store-IX5RJQS5.js} +1 -1
- package/chunks/{workspace-registry-CDAS5TVZ.js → workspace-registry-73N4BGG4.js} +16 -15
- package/chunks/{workspace-service-PAMUKMAV.js → workspace-service-I5RUPSNV.js} +26 -22
- package/chunks/{workspace-skills-status-YQSHCCMS.js → workspace-skills-status-DMK6VYDO.js} +17 -15
- package/chunks/{workspace-trust-reconciler-RPTXOIY2.js → workspace-trust-reconciler-QX4RL3TC.js} +24 -21
- package/chunks/{write-file-CGS57TS4.js → write-file-UGDD5UTS.js} +8 -8
- package/chunks/{zoom-image-E7D72GYV.js → zoom-image-ZAHEO3YP.js} +4 -4
- package/cli.js +12 -12
- package/package.json +3 -3
- package/web-shell/assets/{arc-DybZaz32.js → arc-CHY4saMJ.js} +1 -1
- package/web-shell/assets/{architectureDiagram-3BPJPVTR-jN3qBd19.js → architectureDiagram-3BPJPVTR-Bu6CwvHj.js} +1 -1
- package/web-shell/assets/{blockDiagram-GPEHLZMM-Ct5DZPrj.js → blockDiagram-GPEHLZMM-XGt6iGf_.js} +1 -1
- package/web-shell/assets/{c4Diagram-AAUBKEIU-CUAFMlUG.js → c4Diagram-AAUBKEIU-CBbYl19W.js} +1 -1
- package/web-shell/assets/channel-B40srHOa.js +1 -0
- package/web-shell/assets/{chunk-2J33WTMH-CuV8n90B.js → chunk-2J33WTMH-BEhmVrdx.js} +1 -1
- package/web-shell/assets/{chunk-4BX2VUAB-BUzl_kls.js → chunk-4BX2VUAB-fQLyE0Bg.js} +1 -1
- package/web-shell/assets/{chunk-55IACEB6-BnDBLX6A.js → chunk-55IACEB6-yGdtyx4a.js} +1 -1
- package/web-shell/assets/{chunk-727SXJPM-B83uTOjm.js → chunk-727SXJPM-DYbX2GLo.js} +1 -1
- package/web-shell/assets/{chunk-AQP2D5EJ-DM3HLgpT.js → chunk-AQP2D5EJ-DyKTEsYn.js} +1 -1
- package/web-shell/assets/{chunk-FMBD7UC4-CSQ5hgyb.js → chunk-FMBD7UC4-D8Uy_GzX.js} +1 -1
- package/web-shell/assets/{chunk-ND2GUHAM-BWOF4SxX.js → chunk-ND2GUHAM-C8wNR2K7.js} +1 -1
- package/web-shell/assets/{chunk-QZHKN3VN-BsOH9LMi.js → chunk-QZHKN3VN-BnybNxnt.js} +1 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-qumcXQW_.js +1 -0
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-qumcXQW_.js +1 -0
- package/web-shell/assets/{cose-bilkent-S5V4N54A-IENqH2iJ.js → cose-bilkent-S5V4N54A-jq4uiFRp.js} +1 -1
- package/web-shell/assets/{dagre-BM42HDAG--dyzDTGo.js → dagre-BM42HDAG-Bs7oye1U.js} +1 -1
- package/web-shell/assets/{diagram-2AECGRRQ-BE7Dcqof.js → diagram-2AECGRRQ-BHGGJNyM.js} +1 -1
- package/web-shell/assets/{diagram-5GNKFQAL-Cr8-5OTj.js → diagram-5GNKFQAL-BJezVLGT.js} +1 -1
- package/web-shell/assets/{diagram-KO2AKTUF-Bzey3uAY.js → diagram-KO2AKTUF-5JzQN_rL.js} +1 -1
- package/web-shell/assets/{diagram-LMA3HP47-sErl28Xb.js → diagram-LMA3HP47-BlPYOgY9.js} +1 -1
- package/web-shell/assets/{diagram-OG6HWLK6-Dq30ATIo.js → diagram-OG6HWLK6-CtMHEaFK.js} +1 -1
- package/web-shell/assets/{erDiagram-TEJ5UH35-BkCoEfVW.js → erDiagram-TEJ5UH35-CRNdq2AB.js} +1 -1
- package/web-shell/assets/{flowDiagram-I6XJVG4X-DHwO0rrI.js → flowDiagram-I6XJVG4X-De1WwLzu.js} +1 -1
- package/web-shell/assets/{ganttDiagram-6RSMTGT7-s7vAPxWq.js → ganttDiagram-6RSMTGT7-YbWfL5Zn.js} +1 -1
- package/web-shell/assets/{gitGraphDiagram-PVQCEYII-CQxhwPOU.js → gitGraphDiagram-PVQCEYII-DzCN8bmd.js} +1 -1
- package/web-shell/assets/index-BDOGGGaN.css +5 -0
- package/web-shell/assets/{index-CF4wApWp.js → index-CocPvF9Q.js} +1 -1
- package/web-shell/assets/index-DSH2KrMc.js +1771 -0
- package/web-shell/assets/{infoDiagram-5YYISTIA-BnFrD0bq.js → infoDiagram-5YYISTIA-DLHoopnE.js} +1 -1
- package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-Bf9zK5NK.js → ishikawaDiagram-YF4QCWOH-XnbU04SS.js} +1 -1
- package/web-shell/assets/{journeyDiagram-JHISSGLW-CyGAhsxi.js → journeyDiagram-JHISSGLW-CipPyEeJ.js} +1 -1
- package/web-shell/assets/{kanban-definition-UN3LZRKU-CbsK5akB.js → kanban-definition-UN3LZRKU-DrSeyE5d.js} +1 -1
- package/web-shell/assets/{linear-cQsF4P8D.js → linear-LrBKnAo_.js} +1 -1
- package/web-shell/assets/{mermaid.core-Z4HVqrKY.js → mermaid.core-C3U9UVmf.js} +5 -5
- package/web-shell/assets/{mindmap-definition-RKZ34NQL-CYnrBo_f.js → mindmap-definition-RKZ34NQL-DqRWgC9H.js} +1 -1
- package/web-shell/assets/{pieDiagram-4H26LBE5-CBzOfhrs.js → pieDiagram-4H26LBE5-BNXY5p6H.js} +1 -1
- package/web-shell/assets/{quadrantDiagram-W4KKPZXB-D4LK1Ebn.js → quadrantDiagram-W4KKPZXB-Ccj9QzE4.js} +1 -1
- package/web-shell/assets/{requirementDiagram-4Y6WPE33-Bzti2Lcj.js → requirementDiagram-4Y6WPE33-CjPM2_gx.js} +1 -1
- package/web-shell/assets/{sankeyDiagram-5OEKKPKP-yTBw5Z2s.js → sankeyDiagram-5OEKKPKP-C0RsvKbj.js} +1 -1
- package/web-shell/assets/{sequenceDiagram-3UESZ5HK-D07UVRiZ.js → sequenceDiagram-3UESZ5HK-ClN1P5z7.js} +1 -1
- package/web-shell/assets/{stateDiagram-AJRCARHV-UE_lHsTn.js → stateDiagram-AJRCARHV-By0eiB2Y.js} +1 -1
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-Ds0WlK3F.js +1 -0
- package/web-shell/assets/{timeline-definition-PNZ67QCA-DRvYdiTs.js → timeline-definition-PNZ67QCA-g_iaSQgv.js} +1 -1
- package/web-shell/assets/{vennDiagram-CIIHVFJN-CQLIXs0u.js → vennDiagram-CIIHVFJN-y9ZqJ-TD.js} +1 -1
- package/web-shell/assets/{wardley-L42UT6IY-JZz_Xqse.js → wardley-L42UT6IY-BVVfaxpF.js} +1 -1
- package/web-shell/assets/{wardleyDiagram-YWT4CUSO--i7BiJwB.js → wardleyDiagram-YWT4CUSO-D3ooZKZT.js} +1 -1
- package/web-shell/assets/{xychartDiagram-2RQKCTM6-Bkc-bW0S.js → xychartDiagram-2RQKCTM6-6GXrY6M1.js} +1 -1
- package/web-shell/index.html +2 -2
- package/chunks/chunk-RXFQM6FQ.js +0 -42
- package/chunks/chunk-UA5H3DS2.js +0 -203
- package/web-shell/assets/channel-BMwLrwLW.js +0 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-BGDv98jY.js +0 -1
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-BGDv98jY.js +0 -1
- package/web-shell/assets/index-Bckpjr-I.css +0 -5
- package/web-shell/assets/index-DwEr9HEW.js +0 -1768
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-DC6xgXjX.js +0 -1
- /package/chunks/{chunk-VXZBKKQR.js → chunk-NTTBXH7U.js} +0 -0
- /package/chunks/{chunk-GRC5HGPI.js → chunk-OIBUG24X.js} +0 -0
|
@@ -17,16 +17,17 @@ import {
|
|
|
17
17
|
} from "./chunk-OCPBI7J5.js";
|
|
18
18
|
import {
|
|
19
19
|
defaultSpawnChannelFactory
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-I5VM3SKY.js";
|
|
21
21
|
import {
|
|
22
22
|
BridgeChannelClosedError,
|
|
23
23
|
BridgeTimeoutError,
|
|
24
24
|
SERVE_CONTROL_EXT_METHODS,
|
|
25
25
|
SERVE_STATUS_EXT_METHODS,
|
|
26
26
|
STATUS_SCHEMA_VERSION,
|
|
27
|
+
SessionRestoreTimeoutError,
|
|
27
28
|
createIdleWorkspaceExtensionsStatus,
|
|
28
29
|
createIdleWorkspaceHooksStatus
|
|
29
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-DA4HRSBW.js";
|
|
30
31
|
import {
|
|
31
32
|
ACTIVE_WORK_CLOSE_IF_UNHELD_PARAM,
|
|
32
33
|
ACTIVE_WORK_CLOSE_TIMEOUT_MS,
|
|
@@ -59,6 +60,7 @@ import {
|
|
|
59
60
|
} from "./chunk-M2PNLYGY.js";
|
|
60
61
|
import {
|
|
61
62
|
BranchWhilePromptActiveError,
|
|
63
|
+
BridgeChannelQuarantinedError,
|
|
62
64
|
CancelSentinelCollisionError,
|
|
63
65
|
CdWhilePromptActiveError,
|
|
64
66
|
InvalidClientIdError,
|
|
@@ -77,7 +79,7 @@ import {
|
|
|
77
79
|
SessionShellDisabledError,
|
|
78
80
|
WorkspaceMismatchError,
|
|
79
81
|
isNotCurrentlyGeneratingCancelError
|
|
80
|
-
} from "./chunk-
|
|
82
|
+
} from "./chunk-LP2QGNSP.js";
|
|
81
83
|
import {
|
|
82
84
|
canonicalizeWorkspace,
|
|
83
85
|
translateAndCheckAbsoluteWorkspacePath
|
|
@@ -111,16 +113,16 @@ import {
|
|
|
111
113
|
metadataBudgetBytes,
|
|
112
114
|
normalizeSnapshotPayload,
|
|
113
115
|
stableSessionArtifactId
|
|
114
|
-
} from "./chunk-
|
|
116
|
+
} from "./chunk-XX7QFP34.js";
|
|
115
117
|
import {
|
|
116
118
|
DAEMON_TRACEPARENT_META_KEY,
|
|
117
119
|
DAEMON_TRACESTATE_META_KEY
|
|
118
|
-
} from "./chunk-
|
|
120
|
+
} from "./chunk-4TRQPFDP.js";
|
|
119
121
|
import {
|
|
120
122
|
INVOCATION_CONTEXT_META_KEY,
|
|
121
123
|
PRIVATE_ACP_CAPABILITY_ENV,
|
|
122
124
|
PRIVATE_PARENT_CAPABILITY_META_KEY
|
|
123
|
-
} from "./chunk-
|
|
125
|
+
} from "./chunk-YGT2AUJ7.js";
|
|
124
126
|
import {
|
|
125
127
|
init_esbuild_shims
|
|
126
128
|
} from "./chunk-5O2XNYP6.js";
|
|
@@ -148,6 +150,7 @@ var LATEST_WINS_UPDATES = /* @__PURE__ */ new Set([
|
|
|
148
150
|
"current_mode_update"
|
|
149
151
|
]);
|
|
150
152
|
var REPLAY_SEGMENT_COMPACT_THRESHOLD = 64;
|
|
153
|
+
var LIVE_JOURNAL_TEXT_CHUNKS_PER_EVENT = 256;
|
|
151
154
|
function replayRecordId(event) {
|
|
152
155
|
if (event.type !== "session_update") return void 0;
|
|
153
156
|
const data = event.data;
|
|
@@ -185,10 +188,14 @@ var TurnBoundaryCompactionEngine = class {
|
|
|
185
188
|
replaySegmentStart = 0;
|
|
186
189
|
replayBytes = 0;
|
|
187
190
|
liveJournal = [];
|
|
188
|
-
/** Serialized size of each `liveJournal` entry, index-parallel. */
|
|
191
|
+
/** Serialized source-event size of each `liveJournal` entry, index-parallel. */
|
|
189
192
|
journalEntryBytes = [];
|
|
193
|
+
/** Raw event count represented by each `liveJournal` entry. */
|
|
194
|
+
journalEntryEvents = [];
|
|
190
195
|
journalTotalBytes = 0;
|
|
196
|
+
journalTotalEvents = 0;
|
|
191
197
|
journalTruncatedEvents = 0;
|
|
198
|
+
liveJournalTextSegment;
|
|
192
199
|
lastEventId = 0;
|
|
193
200
|
closed = false;
|
|
194
201
|
truncatedEvents = 0;
|
|
@@ -233,15 +240,7 @@ var TurnBoundaryCompactionEngine = class {
|
|
|
233
240
|
if (seenRecordId !== void 0) {
|
|
234
241
|
this.activeRecordId = seenRecordId;
|
|
235
242
|
}
|
|
236
|
-
this.
|
|
237
|
-
const bytes = byteLength ?? serializedBridgeEventByteLength(event) ?? 0;
|
|
238
|
-
this.journalEntryBytes.push(bytes);
|
|
239
|
-
this.journalTotalBytes += bytes;
|
|
240
|
-
while (this.liveJournal.length > this.maxJournalEvents || this.journalTotalBytes > this.maxJournalBytes && this.liveJournal.length > 1) {
|
|
241
|
-
this.liveJournal.shift();
|
|
242
|
-
this.journalTotalBytes -= this.journalEntryBytes.shift() ?? 0;
|
|
243
|
-
this.journalTruncatedEvents += 1;
|
|
244
|
-
}
|
|
243
|
+
this.appendLiveJournal(event, byteLength);
|
|
245
244
|
if (TURN_BOUNDARY_TYPES.has(event.type)) {
|
|
246
245
|
this.compactCurrentTurn(event);
|
|
247
246
|
return;
|
|
@@ -259,7 +258,13 @@ var TurnBoundaryCompactionEngine = class {
|
|
|
259
258
|
this.makeHistoryTruncatedEvent(compactedTurns.length)
|
|
260
259
|
);
|
|
261
260
|
}
|
|
262
|
-
const liveJournal = this.liveJournal.
|
|
261
|
+
const liveJournal = this.liveJournal.map(
|
|
262
|
+
(entry) => isLiveJournalTextSegment(entry) ? mergeLiveJournalTextEvent(
|
|
263
|
+
entry.firstEvent,
|
|
264
|
+
entry.lastEvent,
|
|
265
|
+
entry.chunks
|
|
266
|
+
) : entry
|
|
267
|
+
);
|
|
263
268
|
if (this.journalTruncatedEvents > 0) {
|
|
264
269
|
liveJournal.unshift({
|
|
265
270
|
v: EVENT_SCHEMA_VERSION,
|
|
@@ -268,7 +273,7 @@ var TurnBoundaryCompactionEngine = class {
|
|
|
268
273
|
reason: "replay_window_exceeded",
|
|
269
274
|
scope: "live_journal",
|
|
270
275
|
truncatedEvents: this.journalTruncatedEvents,
|
|
271
|
-
retainedEvents: this.
|
|
276
|
+
retainedEvents: this.journalTotalEvents,
|
|
272
277
|
maxBytes: this.maxJournalBytes,
|
|
273
278
|
maxEvents: this.maxJournalEvents,
|
|
274
279
|
// Pagination anchor — see makeHistoryTruncatedEvent.
|
|
@@ -341,6 +346,54 @@ var TurnBoundaryCompactionEngine = class {
|
|
|
341
346
|
this.toolSlotIndex.clear();
|
|
342
347
|
this.clearTextSlotIndex();
|
|
343
348
|
}
|
|
349
|
+
appendLiveJournal(event, byteLength) {
|
|
350
|
+
const bytes = byteLength ?? serializedBridgeEventByteLength(event) ?? 0;
|
|
351
|
+
const textChunk = liveJournalTextChunk(event);
|
|
352
|
+
const current = this.liveJournalTextSegment;
|
|
353
|
+
const currentIndex = this.liveJournal.length - 1;
|
|
354
|
+
if (textChunk && current && this.liveJournal[currentIndex] === current && current.chunks.length < LIVE_JOURNAL_TEXT_CHUNKS_PER_EVENT && this.journalEntryBytes[currentIndex] + bytes <= this.maxJournalBytes && current.sessionUpdate === textChunk.sessionUpdate && current.parentToolCallId === textChunk.parentToolCallId && stringArraysEqual(current.sourceRecordIds, textChunk.sourceRecordIds) && current.promptId === event.promptId && current.originatorClientId === event.originatorClientId && current.sessionId === captureSessionId(event) && hasOnlyTimestampEnvelopeMeta(current.lastEvent._meta) && hasOnlyTimestampEnvelopeMeta(event._meta)) {
|
|
355
|
+
current.chunks.push(textChunk.text);
|
|
356
|
+
current.lastEvent = event;
|
|
357
|
+
this.journalEntryBytes[currentIndex] += bytes;
|
|
358
|
+
this.journalEntryEvents[currentIndex] += 1;
|
|
359
|
+
this.journalTotalBytes += bytes;
|
|
360
|
+
this.journalTotalEvents += 1;
|
|
361
|
+
} else {
|
|
362
|
+
let entry = event;
|
|
363
|
+
if (textChunk) {
|
|
364
|
+
const segment = {
|
|
365
|
+
sessionUpdate: textChunk.sessionUpdate,
|
|
366
|
+
chunks: [textChunk.text],
|
|
367
|
+
sourceRecordIds: textChunk.sourceRecordIds,
|
|
368
|
+
parentToolCallId: textChunk.parentToolCallId,
|
|
369
|
+
promptId: event.promptId,
|
|
370
|
+
originatorClientId: event.originatorClientId,
|
|
371
|
+
sessionId: captureSessionId(event),
|
|
372
|
+
firstEvent: event,
|
|
373
|
+
lastEvent: event
|
|
374
|
+
};
|
|
375
|
+
entry = segment;
|
|
376
|
+
this.liveJournalTextSegment = segment;
|
|
377
|
+
} else {
|
|
378
|
+
this.liveJournalTextSegment = void 0;
|
|
379
|
+
}
|
|
380
|
+
this.liveJournal.push(entry);
|
|
381
|
+
this.journalEntryBytes.push(bytes);
|
|
382
|
+
this.journalEntryEvents.push(1);
|
|
383
|
+
this.journalTotalBytes += bytes;
|
|
384
|
+
this.journalTotalEvents += 1;
|
|
385
|
+
}
|
|
386
|
+
while (this.liveJournal.length > this.maxJournalEvents || this.journalTotalBytes > this.maxJournalBytes && this.liveJournal.length > 1) {
|
|
387
|
+
const dropped = this.liveJournal.shift();
|
|
388
|
+
this.journalTotalBytes -= this.journalEntryBytes.shift() ?? 0;
|
|
389
|
+
const droppedEvents = this.journalEntryEvents.shift() ?? 0;
|
|
390
|
+
this.journalTotalEvents -= droppedEvents;
|
|
391
|
+
this.journalTruncatedEvents += droppedEvents;
|
|
392
|
+
if (dropped === this.liveJournalTextSegment) {
|
|
393
|
+
this.liveJournalTextSegment = void 0;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
344
397
|
classifySessionUpdate(event) {
|
|
345
398
|
const data = event.data;
|
|
346
399
|
const updateType = data?.update?.sessionUpdate;
|
|
@@ -350,7 +403,7 @@ var TurnBoundaryCompactionEngine = class {
|
|
|
350
403
|
}
|
|
351
404
|
switch (updateType) {
|
|
352
405
|
case "agent_message_chunk": {
|
|
353
|
-
if (
|
|
406
|
+
if (hasDiscreteMessageMeta(data?.update?._meta)) {
|
|
354
407
|
this.slots.push({ kind: "misc", event });
|
|
355
408
|
break;
|
|
356
409
|
}
|
|
@@ -358,6 +411,10 @@ var TurnBoundaryCompactionEngine = class {
|
|
|
358
411
|
break;
|
|
359
412
|
}
|
|
360
413
|
case "agent_thought_chunk": {
|
|
414
|
+
if (hasDiscreteMessageMeta(data?.update?._meta)) {
|
|
415
|
+
this.slots.push({ kind: "misc", event });
|
|
416
|
+
break;
|
|
417
|
+
}
|
|
361
418
|
this.mergeTextSlot("thought", event, data);
|
|
362
419
|
break;
|
|
363
420
|
}
|
|
@@ -506,8 +563,11 @@ var TurnBoundaryCompactionEngine = class {
|
|
|
506
563
|
resetJournal() {
|
|
507
564
|
this.liveJournal = [];
|
|
508
565
|
this.journalEntryBytes = [];
|
|
566
|
+
this.journalEntryEvents = [];
|
|
509
567
|
this.journalTotalBytes = 0;
|
|
568
|
+
this.journalTotalEvents = 0;
|
|
510
569
|
this.journalTruncatedEvents = 0;
|
|
570
|
+
this.liveJournalTextSegment = void 0;
|
|
511
571
|
}
|
|
512
572
|
addReplaySegment(events, turnCount) {
|
|
513
573
|
if (events.length === 0) return;
|
|
@@ -625,6 +685,61 @@ var TurnBoundaryCompactionEngine = class {
|
|
|
625
685
|
this.textSlotIndex.thought.clear();
|
|
626
686
|
}
|
|
627
687
|
};
|
|
688
|
+
function isLiveJournalTextSegment(entry) {
|
|
689
|
+
return "firstEvent" in entry;
|
|
690
|
+
}
|
|
691
|
+
__name(isLiveJournalTextSegment, "isLiveJournalTextSegment");
|
|
692
|
+
function liveJournalTextChunk(event) {
|
|
693
|
+
if (event.type !== "session_update") return void 0;
|
|
694
|
+
const data = event.data;
|
|
695
|
+
const sessionUpdate = data?.update?.sessionUpdate;
|
|
696
|
+
if (sessionUpdate !== "agent_message_chunk" && sessionUpdate !== "agent_thought_chunk") {
|
|
697
|
+
return void 0;
|
|
698
|
+
}
|
|
699
|
+
if (!hasOnlyModeledChunkKeys(data)) {
|
|
700
|
+
return void 0;
|
|
701
|
+
}
|
|
702
|
+
if (hasDiscreteMessageMeta(data?.update?._meta) || hasUnmodeledTextMeta(data?.update?._meta)) {
|
|
703
|
+
return void 0;
|
|
704
|
+
}
|
|
705
|
+
const content = data?.update?.content;
|
|
706
|
+
if (content?.type !== "text" || typeof content.text !== "string") {
|
|
707
|
+
return void 0;
|
|
708
|
+
}
|
|
709
|
+
return {
|
|
710
|
+
sessionUpdate,
|
|
711
|
+
text: content.text,
|
|
712
|
+
sourceRecordIds: extractSourceRecordIdsFromMeta(data?.update?._meta),
|
|
713
|
+
parentToolCallId: extractParentToolCallIdFromMeta(data?.update?._meta)
|
|
714
|
+
};
|
|
715
|
+
}
|
|
716
|
+
__name(liveJournalTextChunk, "liveJournalTextChunk");
|
|
717
|
+
function hasOnlyModeledChunkKeys(data) {
|
|
718
|
+
if (!data || !data.update) return false;
|
|
719
|
+
const content = data.update.content;
|
|
720
|
+
return Object.keys(data).every((key) => key === "sessionId" || key === "update") && Object.keys(data.update).every(
|
|
721
|
+
(key) => key === "sessionUpdate" || key === "content" || key === "_meta"
|
|
722
|
+
) && (content === void 0 || typeof content === "object" && content !== null && Object.keys(content).every((key) => key === "type" || key === "text"));
|
|
723
|
+
}
|
|
724
|
+
__name(hasOnlyModeledChunkKeys, "hasOnlyModeledChunkKeys");
|
|
725
|
+
function mergeLiveJournalTextEvent(existing, incoming, chunks) {
|
|
726
|
+
const existingData = existing.data;
|
|
727
|
+
const incomingData = incoming.data;
|
|
728
|
+
return {
|
|
729
|
+
...existing,
|
|
730
|
+
...incoming,
|
|
731
|
+
data: {
|
|
732
|
+
...existingData,
|
|
733
|
+
...incomingData,
|
|
734
|
+
update: {
|
|
735
|
+
...existingData.update,
|
|
736
|
+
...incomingData.update,
|
|
737
|
+
content: { type: "text", text: chunks.join("") }
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
};
|
|
741
|
+
}
|
|
742
|
+
__name(mergeLiveJournalTextEvent, "mergeLiveJournalTextEvent");
|
|
628
743
|
function makeMergedSessionUpdateEvent(sessionUpdate, text, eventId, meta, envelopeMeta, turn, sessionId) {
|
|
629
744
|
return {
|
|
630
745
|
id: eventId || void 0,
|
|
@@ -705,10 +820,57 @@ function stringArraysEqual(left, right) {
|
|
|
705
820
|
return left.every((value, index) => value === right[index]);
|
|
706
821
|
}
|
|
707
822
|
__name(stringArraysEqual, "stringArraysEqual");
|
|
708
|
-
function
|
|
709
|
-
return typeof meta === "object" && meta !== null && meta["qwenDiscreteMessage"] === true
|
|
823
|
+
function hasDiscreteMessageMeta(meta) {
|
|
824
|
+
return typeof meta === "object" && meta !== null && meta["qwenDiscreteMessage"] === true;
|
|
825
|
+
}
|
|
826
|
+
__name(hasDiscreteMessageMeta, "hasDiscreteMessageMeta");
|
|
827
|
+
function hasOnlyTimestampEnvelopeMeta(meta) {
|
|
828
|
+
if (meta === void 0) return true;
|
|
829
|
+
if (typeof meta !== "object" || meta === null) return false;
|
|
830
|
+
return Object.keys(meta).every(
|
|
831
|
+
(key) => key === "timestamp" || key === "serverTimestamp"
|
|
832
|
+
);
|
|
833
|
+
}
|
|
834
|
+
__name(hasOnlyTimestampEnvelopeMeta, "hasOnlyTimestampEnvelopeMeta");
|
|
835
|
+
function hasUnmodeledTextMeta(meta) {
|
|
836
|
+
if (meta === void 0) return false;
|
|
837
|
+
if (typeof meta !== "object" || meta === null) return true;
|
|
838
|
+
const record = meta;
|
|
839
|
+
for (const [key, value] of Object.entries(record)) {
|
|
840
|
+
if (key === "timestamp" || key === "serverTimestamp") {
|
|
841
|
+
continue;
|
|
842
|
+
}
|
|
843
|
+
if (key === "parentToolCallId") {
|
|
844
|
+
if (typeof value !== "string") return true;
|
|
845
|
+
continue;
|
|
846
|
+
}
|
|
847
|
+
if (key === "subagentType") {
|
|
848
|
+
if (typeof value !== "string") return true;
|
|
849
|
+
continue;
|
|
850
|
+
}
|
|
851
|
+
if (key === "qwenTranscript") {
|
|
852
|
+
if (typeof value !== "object" || value === null) return true;
|
|
853
|
+
const transcript = value;
|
|
854
|
+
for (const [field, fieldValue] of Object.entries(transcript)) {
|
|
855
|
+
if (field === "sourceRecordIds") {
|
|
856
|
+
if (!Array.isArray(fieldValue) || fieldValue.some((id) => typeof id !== "string")) {
|
|
857
|
+
return true;
|
|
858
|
+
}
|
|
859
|
+
continue;
|
|
860
|
+
}
|
|
861
|
+
if (field === "planToolCallId") {
|
|
862
|
+
if (typeof fieldValue !== "string") return true;
|
|
863
|
+
continue;
|
|
864
|
+
}
|
|
865
|
+
return true;
|
|
866
|
+
}
|
|
867
|
+
continue;
|
|
868
|
+
}
|
|
869
|
+
return true;
|
|
870
|
+
}
|
|
871
|
+
return false;
|
|
710
872
|
}
|
|
711
|
-
__name(
|
|
873
|
+
__name(hasUnmodeledTextMeta, "hasUnmodeledTextMeta");
|
|
712
874
|
function mergeToolCallEvent(existing, incoming) {
|
|
713
875
|
const existingData = existing.data;
|
|
714
876
|
const incomingData = incoming.data;
|
|
@@ -762,6 +924,46 @@ function mergeTranscriptUpdateMeta(existing, incoming) {
|
|
|
762
924
|
}
|
|
763
925
|
__name(mergeTranscriptUpdateMeta, "mergeTranscriptUpdateMeta");
|
|
764
926
|
|
|
927
|
+
// packages/acp-bridge/src/session-restore-timeout.ts
|
|
928
|
+
init_esbuild_shims();
|
|
929
|
+
var DEFAULT_SESSION_RESTORE_TIMEOUT_MS = 6e4;
|
|
930
|
+
var MAX_SESSION_RESTORE_TIMEOUT_MS = 2147483647;
|
|
931
|
+
var MIN_RESTORE_RETRY_AFTER_SECONDS = 5;
|
|
932
|
+
var MAX_RESTORE_RETRY_AFTER_SECONDS = 120;
|
|
933
|
+
function restoreRetryAfterSeconds(timeoutMs) {
|
|
934
|
+
return Math.min(
|
|
935
|
+
MAX_RESTORE_RETRY_AFTER_SECONDS,
|
|
936
|
+
Math.max(MIN_RESTORE_RETRY_AFTER_SECONDS, Math.ceil(timeoutMs / 1e3))
|
|
937
|
+
);
|
|
938
|
+
}
|
|
939
|
+
__name(restoreRetryAfterSeconds, "restoreRetryAfterSeconds");
|
|
940
|
+
function assertValidTimeoutMs(field, timeoutMs) {
|
|
941
|
+
if (!Number.isFinite(timeoutMs) || !Number.isInteger(timeoutMs) || timeoutMs <= 0 || timeoutMs > MAX_SESSION_RESTORE_TIMEOUT_MS) {
|
|
942
|
+
throw new TypeError(
|
|
943
|
+
`Invalid ${field}: ${timeoutMs}. Must be a positive integer no greater than ${MAX_SESSION_RESTORE_TIMEOUT_MS}.`
|
|
944
|
+
);
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
__name(assertValidTimeoutMs, "assertValidTimeoutMs");
|
|
948
|
+
function resolveSessionRestoreTimeoutMs(opts) {
|
|
949
|
+
if (opts.sessionRestoreTimeoutMs !== void 0) {
|
|
950
|
+
assertValidTimeoutMs(
|
|
951
|
+
"sessionRestoreTimeoutMs",
|
|
952
|
+
opts.sessionRestoreTimeoutMs
|
|
953
|
+
);
|
|
954
|
+
return opts.sessionRestoreTimeoutMs;
|
|
955
|
+
}
|
|
956
|
+
if (opts.initializeTimeoutMs !== void 0) {
|
|
957
|
+
assertValidTimeoutMs("initializeTimeoutMs", opts.initializeTimeoutMs);
|
|
958
|
+
return Math.max(
|
|
959
|
+
opts.initializeTimeoutMs,
|
|
960
|
+
DEFAULT_SESSION_RESTORE_TIMEOUT_MS
|
|
961
|
+
);
|
|
962
|
+
}
|
|
963
|
+
return DEFAULT_SESSION_RESTORE_TIMEOUT_MS;
|
|
964
|
+
}
|
|
965
|
+
__name(resolveSessionRestoreTimeoutMs, "resolveSessionRestoreTimeoutMs");
|
|
966
|
+
|
|
765
967
|
// packages/acp-bridge/src/session-source.ts
|
|
766
968
|
init_esbuild_shims();
|
|
767
969
|
var SESSION_SOURCE_META_KEY = "qwen.session.source";
|
|
@@ -1977,6 +2179,9 @@ var BridgeClient = class {
|
|
|
1977
2179
|
}
|
|
1978
2180
|
}
|
|
1979
2181
|
async sessionUpdate(params) {
|
|
2182
|
+
if (this.abandonedRestoreIds.has(params.sessionId)) {
|
|
2183
|
+
return;
|
|
2184
|
+
}
|
|
1980
2185
|
if (!this.ownsSession(params.sessionId) && !this.inFlightRestoreIds.has(params.sessionId)) {
|
|
1981
2186
|
writeStderrLine(
|
|
1982
2187
|
`[demux] session=${params.sessionId} type=session_update action=dropped reason=session_not_owned`
|
|
@@ -2147,22 +2352,19 @@ var BridgeClient = class {
|
|
|
2147
2352
|
* stale frame for that id anywhere in the system.
|
|
2148
2353
|
*/
|
|
2149
2354
|
tombstonedSessionIds = /* @__PURE__ */ new Map();
|
|
2355
|
+
/** Restore ownership for `sessionUpdate` and artifact demultiplexing. */
|
|
2356
|
+
inFlightRestoreIds = /* @__PURE__ */ new Set();
|
|
2150
2357
|
/**
|
|
2151
|
-
*
|
|
2152
|
-
*
|
|
2153
|
-
*
|
|
2154
|
-
* previously-closed id flow through to the future
|
|
2155
|
-
* `createSessionEntry -> drainEarlyEvents` call.
|
|
2156
|
-
*
|
|
2157
|
-
* Without this, the tombstone set before a future `load` can clear
|
|
2158
|
-
* it via `drainEarlyEvents` would silently drop legitimate
|
|
2159
|
-
* restore-time events (e.g. MCP discovery budget events firing
|
|
2160
|
-
* during the ACP call window).
|
|
2161
|
-
*
|
|
2162
|
-
* Bridge factory enters the set before awaiting the ACP restore
|
|
2163
|
-
* call and exits on settle (success or failure).
|
|
2358
|
+
* Registrations allowed to buffer early extended notifications through an
|
|
2359
|
+
* ordinary close tombstone. This includes restores and caller-supplied-id
|
|
2360
|
+
* spawns, and lasts only until their ACP registration attempt settles.
|
|
2164
2361
|
*/
|
|
2165
|
-
|
|
2362
|
+
inFlightSessionRegistrationIds = /* @__PURE__ */ new Set();
|
|
2363
|
+
/**
|
|
2364
|
+
* Restore ids whose caller timed out while the non-cancellable ACP request
|
|
2365
|
+
* continues.
|
|
2366
|
+
*/
|
|
2367
|
+
abandonedRestoreIds = /* @__PURE__ */ new Set();
|
|
2166
2368
|
/**
|
|
2167
2369
|
* Handle child->bridge ACP `extMethod` requests (calls that expect a
|
|
2168
2370
|
* response, unlike `extNotification`). Served methods:
|
|
@@ -2629,6 +2831,10 @@ var BridgeClient = class {
|
|
|
2629
2831
|
* forward-compat.
|
|
2630
2832
|
*/
|
|
2631
2833
|
async extNotification(method, params) {
|
|
2834
|
+
const notificationSessionId = params["sessionId"];
|
|
2835
|
+
if (typeof notificationSessionId === "string" && this.abandonedRestoreIds.has(notificationSessionId)) {
|
|
2836
|
+
return;
|
|
2837
|
+
}
|
|
2632
2838
|
if (method === ACTIVE_WORK_NOTIFICATION_METHOD) {
|
|
2633
2839
|
const snapshot = parseActiveWorkSnapshot(params);
|
|
2634
2840
|
if (snapshot) {
|
|
@@ -2907,6 +3113,9 @@ var BridgeClient = class {
|
|
|
2907
3113
|
}
|
|
2908
3114
|
}
|
|
2909
3115
|
publishExtNotification(sessionId, type, data, turnScoped = false) {
|
|
3116
|
+
if (this.abandonedRestoreIds.has(sessionId)) {
|
|
3117
|
+
return;
|
|
3118
|
+
}
|
|
2910
3119
|
const entry = this.resolveEntry(sessionId);
|
|
2911
3120
|
const frame = {
|
|
2912
3121
|
type,
|
|
@@ -3052,9 +3261,12 @@ var BridgeClient = class {
|
|
|
3052
3261
|
* dropped to bound per-session memory.
|
|
3053
3262
|
*/
|
|
3054
3263
|
bufferEarlyEvent(sessionId, frame) {
|
|
3264
|
+
if (this.abandonedRestoreIds.has(sessionId)) {
|
|
3265
|
+
return;
|
|
3266
|
+
}
|
|
3055
3267
|
const now = Date.now();
|
|
3056
3268
|
this.sweepExpiredTombstones(now);
|
|
3057
|
-
if (this.tombstonedSessionIds.has(sessionId) && !this.
|
|
3269
|
+
if (this.tombstonedSessionIds.has(sessionId) && !this.inFlightSessionRegistrationIds.has(sessionId)) {
|
|
3058
3270
|
writeStderrLine(
|
|
3059
3271
|
`qwen serve: dropping early extNotification for tombstoned session ${JSON.stringify(sessionId)} (post-close stale event)`
|
|
3060
3272
|
);
|
|
@@ -3116,8 +3328,31 @@ var BridgeClient = class {
|
|
|
3116
3328
|
* failed restore doesn't leave a dangling allow-list entry.
|
|
3117
3329
|
*/
|
|
3118
3330
|
markRestoreInFlight(sessionId) {
|
|
3331
|
+
this.markSessionRegistrationInFlight(sessionId);
|
|
3119
3332
|
this.inFlightRestoreIds.add(sessionId);
|
|
3120
3333
|
}
|
|
3334
|
+
/**
|
|
3335
|
+
* Transfer an id from closed/abandoned ownership to a new registration
|
|
3336
|
+
* attempt before its ACP call starts. The in-flight allow-list is what lets
|
|
3337
|
+
* legitimate early notifications bypass the ordinary close tombstone until
|
|
3338
|
+
* `createSessionEntry` can drain them.
|
|
3339
|
+
*/
|
|
3340
|
+
markSessionRegistrationInFlight(sessionId) {
|
|
3341
|
+
this.clearAbandonedRestoreFence(sessionId);
|
|
3342
|
+
this.inFlightSessionRegistrationIds.add(sessionId);
|
|
3343
|
+
}
|
|
3344
|
+
/**
|
|
3345
|
+
* Drop the abandoned-restore fence for `sessionId`.
|
|
3346
|
+
*
|
|
3347
|
+
* The fence has no TTL and suppresses session updates, guardrail events,
|
|
3348
|
+
* and child notifications, so it must not outlive the abandoned attempt it
|
|
3349
|
+
* was raised for. The bridge clears it whenever a legitimate owner takes
|
|
3350
|
+
* the id — a new restore, or `createSessionEntry` registering a session
|
|
3351
|
+
* from any other route.
|
|
3352
|
+
*/
|
|
3353
|
+
clearAbandonedRestoreFence(sessionId) {
|
|
3354
|
+
this.abandonedRestoreIds.delete(sessionId);
|
|
3355
|
+
}
|
|
3121
3356
|
/**
|
|
3122
3357
|
* Companion to `markRestoreInFlight`. Bridge factory calls this when
|
|
3123
3358
|
* the restore IIFE settles — after `createSessionEntry` runs
|
|
@@ -3126,6 +3361,16 @@ var BridgeClient = class {
|
|
|
3126
3361
|
*/
|
|
3127
3362
|
clearRestoreInFlight(sessionId) {
|
|
3128
3363
|
this.inFlightRestoreIds.delete(sessionId);
|
|
3364
|
+
this.clearSessionRegistrationInFlight(sessionId);
|
|
3365
|
+
}
|
|
3366
|
+
clearSessionRegistrationInFlight(sessionId) {
|
|
3367
|
+
this.inFlightSessionRegistrationIds.delete(sessionId);
|
|
3368
|
+
}
|
|
3369
|
+
markRestoreAbandoned(sessionId) {
|
|
3370
|
+
this.inFlightRestoreIds.delete(sessionId);
|
|
3371
|
+
this.inFlightSessionRegistrationIds.delete(sessionId);
|
|
3372
|
+
this.abandonedRestoreIds.add(sessionId);
|
|
3373
|
+
this.earlyEvents.delete(sessionId);
|
|
3129
3374
|
}
|
|
3130
3375
|
/**
|
|
3131
3376
|
* Drain any frames buffered for `sessionId` onto `entry.events`.
|
|
@@ -6172,7 +6417,31 @@ function createAcpSessionBridge(opts) {
|
|
|
6172
6417
|
} else {
|
|
6173
6418
|
maxSessions = opts.maxSessions;
|
|
6174
6419
|
}
|
|
6175
|
-
const
|
|
6420
|
+
const freshSessionBlocker = /* @__PURE__ */ __name(() => {
|
|
6421
|
+
for (const ci of aliveChannels) {
|
|
6422
|
+
if (ci.isDying) continue;
|
|
6423
|
+
if (ci.isQuarantined) {
|
|
6424
|
+
return { channel: ci, reason: "restore_cleanup_failed" };
|
|
6425
|
+
}
|
|
6426
|
+
if (ci.restoreSettlementOverdue) {
|
|
6427
|
+
return { channel: ci, reason: "restore_settlement_overdue" };
|
|
6428
|
+
}
|
|
6429
|
+
}
|
|
6430
|
+
return void 0;
|
|
6431
|
+
}, "freshSessionBlocker");
|
|
6432
|
+
const assertFreshSessionsAvailable = /* @__PURE__ */ __name(() => {
|
|
6433
|
+
const blocker = freshSessionBlocker();
|
|
6434
|
+
if (blocker) {
|
|
6435
|
+
throw new BridgeChannelQuarantinedError(
|
|
6436
|
+
blocker.reason,
|
|
6437
|
+
abandonedRestoreRetryAfterSeconds
|
|
6438
|
+
);
|
|
6439
|
+
}
|
|
6440
|
+
}, "assertFreshSessionsAvailable");
|
|
6441
|
+
const reserveFreshSession = /* @__PURE__ */ __name((context) => {
|
|
6442
|
+
assertFreshSessionsAvailable();
|
|
6443
|
+
return opts.freshSessionAdmission?.(context);
|
|
6444
|
+
}, "reserveFreshSession");
|
|
6176
6445
|
const releaseFreshSessionReservation = /* @__PURE__ */ __name((reservation) => {
|
|
6177
6446
|
if (!reservation) return;
|
|
6178
6447
|
try {
|
|
@@ -6217,6 +6486,11 @@ function createAcpSessionBridge(opts) {
|
|
|
6217
6486
|
`Invalid initializeTimeoutMs: ${initTimeoutMs}. Must be > 0.`
|
|
6218
6487
|
);
|
|
6219
6488
|
}
|
|
6489
|
+
const sessionRestoreTimeoutMs = resolveSessionRestoreTimeoutMs(opts);
|
|
6490
|
+
const restoreSettlementGraceMs = sessionRestoreTimeoutMs;
|
|
6491
|
+
const abandonedRestoreRetryAfterSeconds = restoreRetryAfterSeconds(
|
|
6492
|
+
sessionRestoreTimeoutMs
|
|
6493
|
+
);
|
|
6220
6494
|
const permissionTimeoutRaw = opts.permissionResponseTimeoutMs ?? DEFAULT_PERMISSION_TIMEOUT_MS;
|
|
6221
6495
|
const permissionTimeoutMs = permissionTimeoutRaw > 0 && Number.isFinite(permissionTimeoutRaw) ? (
|
|
6222
6496
|
// Clamp to 2^31-1: Node treats setTimeout delays larger than
|
|
@@ -6327,8 +6601,11 @@ function createAcpSessionBridge(opts) {
|
|
|
6327
6601
|
try {
|
|
6328
6602
|
if (!await confirmChildUnheld(entry)) return;
|
|
6329
6603
|
if (byId.get(entry.sessionId) !== entry) return;
|
|
6604
|
+
const condemnedOwner = channelInfoForEntry(entry);
|
|
6605
|
+
const agentCloseTimeoutMs = condemnedOwner?.isQuarantined === true || condemnedOwner?.restoreSettlementOverdue === true ? ACTIVE_WORK_CLOSE_TIMEOUT_MS : void 0;
|
|
6330
6606
|
await closeSessionImpl(entry.sessionId, void 0, {
|
|
6331
|
-
reason: opts2.closeReason
|
|
6607
|
+
reason: opts2.closeReason,
|
|
6608
|
+
...agentCloseTimeoutMs !== void 0 ? { agentCloseTimeoutMs } : {}
|
|
6332
6609
|
}).catch((err) => {
|
|
6333
6610
|
writeStderrLine(
|
|
6334
6611
|
`qwen serve: deferred close (${opts2.trigger}) failed for ${JSON.stringify(entry.sessionId)}: ${err instanceof Error ? err.stack ?? err.message : String(err)}`
|
|
@@ -6343,6 +6620,7 @@ function createAcpSessionBridge(opts) {
|
|
|
6343
6620
|
const info = channelInfoForEntry(entry);
|
|
6344
6621
|
if (!info?.activeWork) return true;
|
|
6345
6622
|
if (info.isDying) return false;
|
|
6623
|
+
if (info.isQuarantined || info.restoreSettlementOverdue) return true;
|
|
6346
6624
|
try {
|
|
6347
6625
|
const response = await withTimeout(
|
|
6348
6626
|
entry.connection.extMethod(SERVE_CONTROL_EXT_METHODS.sessionClose, {
|
|
@@ -6506,8 +6784,35 @@ function createAcpSessionBridge(opts) {
|
|
|
6506
6784
|
workspaceMcpResourcesCache.delete(serverName);
|
|
6507
6785
|
}
|
|
6508
6786
|
__name(invalidateWorkspaceMcpDetailCache, "invalidateWorkspaceMcpDetailCache");
|
|
6787
|
+
function channelShouldReapWhenIdle(ci) {
|
|
6788
|
+
return ci.emptyReapPending || ci.unsettledAbandonedRestores.size > 0 || ci.isQuarantined;
|
|
6789
|
+
}
|
|
6790
|
+
__name(channelShouldReapWhenIdle, "channelShouldReapWhenIdle");
|
|
6791
|
+
function armRestoreSettlementGrace(ci, sessionId, action) {
|
|
6792
|
+
if (ci.restoreSettlementTimers.has(sessionId)) return;
|
|
6793
|
+
const timer = setTimeout(() => {
|
|
6794
|
+
ci.restoreSettlementTimers.delete(sessionId);
|
|
6795
|
+
if (!ci.unsettledAbandonedRestores.has(sessionId)) return;
|
|
6796
|
+
if (ci.isDying || !aliveChannels.has(ci)) return;
|
|
6797
|
+
ci.restoreSettlementOverdue = true;
|
|
6798
|
+
writeStderrLine(
|
|
6799
|
+
`qwen serve: abandoned session/${action} for ${JSON.stringify(sessionId)} has not settled ${restoreSettlementGraceMs}ms after its deadline; refusing fresh sessions on channel ${ci.id} until it drains`
|
|
6800
|
+
);
|
|
6801
|
+
telemetry.event("session.restore.settlement_overdue", {
|
|
6802
|
+
"qwen-code.daemon.session_restore.action": action,
|
|
6803
|
+
"qwen-code.daemon.session_restore.timeout_ms": sessionRestoreTimeoutMs,
|
|
6804
|
+
"qwen-code.daemon.session_restore.settlement_grace_ms": restoreSettlementGraceMs,
|
|
6805
|
+
"qwen-code.daemon.acp_channel.id": ci.id,
|
|
6806
|
+
"session.id": sessionId
|
|
6807
|
+
});
|
|
6808
|
+
void reapPendingEmptyChannel(ci);
|
|
6809
|
+
}, restoreSettlementGraceMs);
|
|
6810
|
+
timer.unref();
|
|
6811
|
+
ci.restoreSettlementTimers.set(sessionId, timer);
|
|
6812
|
+
}
|
|
6813
|
+
__name(armRestoreSettlementGrace, "armRestoreSettlementGrace");
|
|
6509
6814
|
async function reapPendingEmptyChannel(ci) {
|
|
6510
|
-
if (!ci
|
|
6815
|
+
if (!channelShouldReapWhenIdle(ci) || !hasNoChannelWork(ci)) return;
|
|
6511
6816
|
ci.emptyReapPending = false;
|
|
6512
6817
|
ci.isDying = true;
|
|
6513
6818
|
await ci.channel.kill().catch(() => {
|
|
@@ -6677,6 +6982,7 @@ function createAcpSessionBridge(opts) {
|
|
|
6677
6982
|
}
|
|
6678
6983
|
}, "teeServeDebugLine");
|
|
6679
6984
|
const inFlightSpawns = /* @__PURE__ */ new Map();
|
|
6985
|
+
const inFlightRequestedSessionSpawns = /* @__PURE__ */ new Map();
|
|
6680
6986
|
const inFlightRestores = /* @__PURE__ */ new Map();
|
|
6681
6987
|
const pendingRestoreEvents = /* @__PURE__ */ new Map();
|
|
6682
6988
|
const createClientId = /* @__PURE__ */ __name(() => `client_${randomUUID2()}`, "createClientId");
|
|
@@ -6894,7 +7200,11 @@ function createAcpSessionBridge(opts) {
|
|
|
6894
7200
|
workspaceMcpAuthenticationServerNames: /* @__PURE__ */ new Set(),
|
|
6895
7201
|
workspaceMcpAuthenticationTimers: /* @__PURE__ */ new Map(),
|
|
6896
7202
|
emptyReapPending: false,
|
|
7203
|
+
unsettledAbandonedRestores: /* @__PURE__ */ new Set(),
|
|
7204
|
+
restoreSettlementOverdue: false,
|
|
7205
|
+
restoreSettlementTimers: /* @__PURE__ */ new Map(),
|
|
6897
7206
|
isDying: false,
|
|
7207
|
+
isQuarantined: false,
|
|
6898
7208
|
handshakeComplete: false
|
|
6899
7209
|
};
|
|
6900
7210
|
infoRef.current = info;
|
|
@@ -6915,6 +7225,10 @@ function createAcpSessionBridge(opts) {
|
|
|
6915
7225
|
}
|
|
6916
7226
|
info.workspaceMcpAuthenticationTimers.clear();
|
|
6917
7227
|
info.workspaceMcpAuthenticationServerNames.clear();
|
|
7228
|
+
for (const timer of info.restoreSettlementTimers.values()) {
|
|
7229
|
+
clearTimeout(timer);
|
|
7230
|
+
}
|
|
7231
|
+
info.restoreSettlementTimers.clear();
|
|
6918
7232
|
aliveChannels.delete(info);
|
|
6919
7233
|
if (channelInfo === info) channelInfo = void 0;
|
|
6920
7234
|
const sessions = Array.from(info.sessionIds);
|
|
@@ -7076,6 +7390,9 @@ function createAcpSessionBridge(opts) {
|
|
|
7076
7390
|
ensureChannel
|
|
7077
7391
|
);
|
|
7078
7392
|
ci.sessionSpawnsInFlight++;
|
|
7393
|
+
if (requestedSessionId !== void 0) {
|
|
7394
|
+
ci.client.markSessionRegistrationInFlight(requestedSessionId);
|
|
7395
|
+
}
|
|
7079
7396
|
let sessionRegistered = false;
|
|
7080
7397
|
let sessionRemovedDuringInitialization = false;
|
|
7081
7398
|
let initializedSessionId;
|
|
@@ -7260,6 +7577,12 @@ function createAcpSessionBridge(opts) {
|
|
|
7260
7577
|
...entry.branch ? { branch: entry.branch } : {}
|
|
7261
7578
|
};
|
|
7262
7579
|
} finally {
|
|
7580
|
+
if (requestedSessionId !== void 0) {
|
|
7581
|
+
ci.client.clearSessionRegistrationInFlight(requestedSessionId);
|
|
7582
|
+
if (initializedSessionId !== requestedSessionId && !byId.has(requestedSessionId)) {
|
|
7583
|
+
ci.client.markSessionClosed(requestedSessionId);
|
|
7584
|
+
}
|
|
7585
|
+
}
|
|
7263
7586
|
ci.sessionSpawnsInFlight = Math.max(0, ci.sessionSpawnsInFlight - 1);
|
|
7264
7587
|
if (!sessionRegistered) {
|
|
7265
7588
|
await reapPendingEmptyChannel(ci);
|
|
@@ -7932,6 +8255,7 @@ function createAcpSessionBridge(opts) {
|
|
|
7932
8255
|
};
|
|
7933
8256
|
ci.sessionIds.add(entry.sessionId);
|
|
7934
8257
|
byId.set(entry.sessionId, entry);
|
|
8258
|
+
ci.client.clearAbandonedRestoreFence(entry.sessionId);
|
|
7935
8259
|
touchActivity();
|
|
7936
8260
|
telemetry.metrics?.sessionLifecycle("spawn");
|
|
7937
8261
|
emitSessionLifecycle({
|
|
@@ -8272,19 +8596,27 @@ function createAcpSessionBridge(opts) {
|
|
|
8272
8596
|
...historyAnchorRecordId !== void 0 ? { historyAnchorRecordId } : {}
|
|
8273
8597
|
};
|
|
8274
8598
|
}
|
|
8599
|
+
if (inFlightRequestedSessionSpawns.has(req.sessionId)) {
|
|
8600
|
+
throw new RestoreInProgressError(req.sessionId, "spawn", action);
|
|
8601
|
+
}
|
|
8275
8602
|
const inFlight = inFlightRestores.get(req.sessionId);
|
|
8276
8603
|
if (inFlight) {
|
|
8277
|
-
if (action !== inFlight.action || historyReplay !== inFlight.historyReplay || hideInheritedHistory !== inFlight.hideInheritedHistory) {
|
|
8604
|
+
if (inFlight.lifecycle.phase === "abandoned" || action !== inFlight.action || historyReplay !== inFlight.historyReplay || hideInheritedHistory !== inFlight.hideInheritedHistory) {
|
|
8605
|
+
const abandoned = inFlight.lifecycle.phase === "abandoned";
|
|
8278
8606
|
throw new RestoreInProgressError(
|
|
8279
8607
|
req.sessionId,
|
|
8280
8608
|
inFlight.action,
|
|
8281
|
-
action
|
|
8609
|
+
action,
|
|
8610
|
+
abandoned ? {
|
|
8611
|
+
reason: "awaiting_abandoned_cleanup",
|
|
8612
|
+
retryAfterSeconds: abandonedRestoreRetryAfterSeconds
|
|
8613
|
+
} : void 0
|
|
8282
8614
|
);
|
|
8283
8615
|
}
|
|
8284
8616
|
inFlight.coalesceState.count++;
|
|
8285
8617
|
let restored;
|
|
8286
8618
|
try {
|
|
8287
|
-
restored = await inFlight.
|
|
8619
|
+
restored = await inFlight.publicPromise;
|
|
8288
8620
|
} catch (err) {
|
|
8289
8621
|
inFlight.coalesceState.count--;
|
|
8290
8622
|
throw err;
|
|
@@ -8310,6 +8642,7 @@ function createAcpSessionBridge(opts) {
|
|
|
8310
8642
|
hasActivePrompt: entry.promptActive
|
|
8311
8643
|
};
|
|
8312
8644
|
}
|
|
8645
|
+
assertFreshSessionsAvailable();
|
|
8313
8646
|
if (byId.size + inFlightSpawns.size + inFlightRestores.size >= maxSessions) {
|
|
8314
8647
|
throw new SessionLimitExceededError(maxSessions);
|
|
8315
8648
|
}
|
|
@@ -8328,12 +8661,145 @@ function createAcpSessionBridge(opts) {
|
|
|
8328
8661
|
admissionReleased = true;
|
|
8329
8662
|
releaseFreshSessionReservation(admission);
|
|
8330
8663
|
}, "releaseAdmissionOnce");
|
|
8664
|
+
let resolveSettlement;
|
|
8665
|
+
const settlementPromise = new Promise((resolve2) => {
|
|
8666
|
+
resolveSettlement = resolve2;
|
|
8667
|
+
});
|
|
8668
|
+
const restoreLifecycle = {
|
|
8669
|
+
phase: "active"
|
|
8670
|
+
};
|
|
8671
|
+
const settleAbandonedRestore = /* @__PURE__ */ __name(async (channel, lateResult) => {
|
|
8672
|
+
telemetry.event("session.restore.late_result", {
|
|
8673
|
+
"qwen-code.daemon.session_restore.action": action,
|
|
8674
|
+
"qwen-code.daemon.session_restore.result": lateResult,
|
|
8675
|
+
"qwen-code.daemon.session_restore.timeout_ms": sessionRestoreTimeoutMs,
|
|
8676
|
+
"qwen-code.daemon.acp_channel.id": channel.id,
|
|
8677
|
+
"session.id": req.sessionId
|
|
8678
|
+
});
|
|
8679
|
+
const usurper = byId.get(req.sessionId);
|
|
8680
|
+
if (usurper) {
|
|
8681
|
+
writeStderrLine(
|
|
8682
|
+
`qwen serve: skipping abandoned session/${action} cleanup for ${JSON.stringify(req.sessionId)}: the id is now owned by a live session`
|
|
8683
|
+
);
|
|
8684
|
+
telemetry.event("session.restore.cleanup", {
|
|
8685
|
+
"qwen-code.daemon.session_restore.action": action,
|
|
8686
|
+
"qwen-code.daemon.session_restore.cleanup_result": "id_reclaimed",
|
|
8687
|
+
"qwen-code.daemon.session_restore.timeout_ms": sessionRestoreTimeoutMs,
|
|
8688
|
+
"qwen-code.daemon.acp_channel.id": channel.id,
|
|
8689
|
+
"session.id": req.sessionId
|
|
8690
|
+
});
|
|
8691
|
+
channel.unsettledAbandonedRestores.delete(req.sessionId);
|
|
8692
|
+
const reclaimedTimer = channel.restoreSettlementTimers.get(
|
|
8693
|
+
req.sessionId
|
|
8694
|
+
);
|
|
8695
|
+
if (reclaimedTimer !== void 0) {
|
|
8696
|
+
clearTimeout(reclaimedTimer);
|
|
8697
|
+
channel.restoreSettlementTimers.delete(req.sessionId);
|
|
8698
|
+
}
|
|
8699
|
+
if (channel.unsettledAbandonedRestores.size === 0) {
|
|
8700
|
+
channel.restoreSettlementOverdue = false;
|
|
8701
|
+
}
|
|
8702
|
+
releaseAdmissionOnce();
|
|
8703
|
+
resolveSettlement();
|
|
8704
|
+
return;
|
|
8705
|
+
}
|
|
8706
|
+
try {
|
|
8707
|
+
if (channel.isDying || !aliveChannels.has(channel)) {
|
|
8708
|
+
await channel.channel.exited;
|
|
8709
|
+
telemetry.event("session.restore.cleanup", {
|
|
8710
|
+
"qwen-code.daemon.session_restore.action": action,
|
|
8711
|
+
"qwen-code.daemon.session_restore.cleanup_result": "transport_closed",
|
|
8712
|
+
"qwen-code.daemon.session_restore.timeout_ms": sessionRestoreTimeoutMs,
|
|
8713
|
+
"qwen-code.daemon.acp_channel.id": channel.id,
|
|
8714
|
+
"session.id": req.sessionId
|
|
8715
|
+
});
|
|
8716
|
+
return;
|
|
8717
|
+
}
|
|
8718
|
+
try {
|
|
8719
|
+
await Promise.race([
|
|
8720
|
+
withTimeout(
|
|
8721
|
+
channel.connection.extMethod(
|
|
8722
|
+
SERVE_CONTROL_EXT_METHODS.sessionClose,
|
|
8723
|
+
{
|
|
8724
|
+
sessionId: req.sessionId,
|
|
8725
|
+
drainTimeoutMs: Math.max(1, Math.floor(initTimeoutMs * 0.8))
|
|
8726
|
+
}
|
|
8727
|
+
),
|
|
8728
|
+
initTimeoutMs,
|
|
8729
|
+
"abandonedRestoreClose"
|
|
8730
|
+
),
|
|
8731
|
+
getChannelClosedReject(channel)
|
|
8732
|
+
]);
|
|
8733
|
+
telemetry.event("session.restore.cleanup", {
|
|
8734
|
+
"qwen-code.daemon.session_restore.action": action,
|
|
8735
|
+
"qwen-code.daemon.session_restore.cleanup_result": "closed",
|
|
8736
|
+
"qwen-code.daemon.session_restore.timeout_ms": sessionRestoreTimeoutMs,
|
|
8737
|
+
"qwen-code.daemon.acp_channel.id": channel.id,
|
|
8738
|
+
"session.id": req.sessionId
|
|
8739
|
+
});
|
|
8740
|
+
} catch (error) {
|
|
8741
|
+
if (isAcpSessionResourceNotFound(error, req.sessionId)) {
|
|
8742
|
+
telemetry.event("session.restore.cleanup", {
|
|
8743
|
+
"qwen-code.daemon.session_restore.action": action,
|
|
8744
|
+
"qwen-code.daemon.session_restore.cleanup_result": "not_found",
|
|
8745
|
+
"qwen-code.daemon.session_restore.timeout_ms": sessionRestoreTimeoutMs,
|
|
8746
|
+
"qwen-code.daemon.acp_channel.id": channel.id,
|
|
8747
|
+
"session.id": req.sessionId
|
|
8748
|
+
});
|
|
8749
|
+
return;
|
|
8750
|
+
}
|
|
8751
|
+
if (channel.isDying || !aliveChannels.has(channel)) {
|
|
8752
|
+
await channel.channel.exited;
|
|
8753
|
+
telemetry.event("session.restore.cleanup", {
|
|
8754
|
+
"qwen-code.daemon.session_restore.action": action,
|
|
8755
|
+
"qwen-code.daemon.session_restore.cleanup_result": "transport_closed",
|
|
8756
|
+
"qwen-code.daemon.session_restore.timeout_ms": sessionRestoreTimeoutMs,
|
|
8757
|
+
"qwen-code.daemon.acp_channel.id": channel.id,
|
|
8758
|
+
"session.id": req.sessionId
|
|
8759
|
+
});
|
|
8760
|
+
return;
|
|
8761
|
+
}
|
|
8762
|
+
channel.isQuarantined = true;
|
|
8763
|
+
writeStderrLine(
|
|
8764
|
+
`qwen serve: quarantining ACP channel after timed-out session/${action} cleanup failed for ${JSON.stringify(req.sessionId)}: ${extractErrorMessage(error)}`
|
|
8765
|
+
);
|
|
8766
|
+
telemetry.event("session.restore.cleanup", {
|
|
8767
|
+
"qwen-code.daemon.session_restore.action": action,
|
|
8768
|
+
"qwen-code.daemon.session_restore.cleanup_result": "quarantined",
|
|
8769
|
+
"qwen-code.daemon.session_restore.timeout_ms": sessionRestoreTimeoutMs,
|
|
8770
|
+
"qwen-code.daemon.acp_channel.id": channel.id,
|
|
8771
|
+
"session.id": req.sessionId
|
|
8772
|
+
});
|
|
8773
|
+
if (hasNoChannelWork(channel)) {
|
|
8774
|
+
void killChannelWithLog(
|
|
8775
|
+
channel,
|
|
8776
|
+
`abandoned session/${action} cleanup`
|
|
8777
|
+
);
|
|
8778
|
+
}
|
|
8779
|
+
await channel.channel.exited;
|
|
8780
|
+
}
|
|
8781
|
+
} finally {
|
|
8782
|
+
channel.client.markSessionClosed(req.sessionId);
|
|
8783
|
+
channel.unsettledAbandonedRestores.delete(req.sessionId);
|
|
8784
|
+
const graceTimer = channel.restoreSettlementTimers.get(req.sessionId);
|
|
8785
|
+
if (graceTimer !== void 0) {
|
|
8786
|
+
clearTimeout(graceTimer);
|
|
8787
|
+
channel.restoreSettlementTimers.delete(req.sessionId);
|
|
8788
|
+
}
|
|
8789
|
+
if (channel.unsettledAbandonedRestores.size === 0) {
|
|
8790
|
+
channel.restoreSettlementOverdue = false;
|
|
8791
|
+
}
|
|
8792
|
+
releaseAdmissionOnce();
|
|
8793
|
+
resolveSettlement();
|
|
8794
|
+
}
|
|
8795
|
+
}, "settleAbandonedRestore");
|
|
8331
8796
|
const promise = (async () => {
|
|
8332
8797
|
pendingRestoreEvents.set(req.sessionId, restoreEvents);
|
|
8333
|
-
|
|
8334
|
-
ci
|
|
8335
|
-
|
|
8336
|
-
|
|
8798
|
+
const restoreChannel = await ensureChannel();
|
|
8799
|
+
ci = restoreChannel;
|
|
8800
|
+
restoreChannel.pendingRestoreIds.add(req.sessionId);
|
|
8801
|
+
restoreChannel.client.markRestoreInFlight(req.sessionId);
|
|
8802
|
+
const transportClosed = restoreChannel.channel.exited.then(() => {
|
|
8337
8803
|
throw new BridgeChannelClosedError(`during session/${action}`);
|
|
8338
8804
|
});
|
|
8339
8805
|
transportClosed.catch(() => {
|
|
@@ -8344,10 +8810,18 @@ function createAcpSessionBridge(opts) {
|
|
|
8344
8810
|
let replayError;
|
|
8345
8811
|
let replayHasMore;
|
|
8346
8812
|
try {
|
|
8347
|
-
|
|
8348
|
-
|
|
8349
|
-
|
|
8350
|
-
|
|
8813
|
+
const rawRestore = telemetry.withSpan(
|
|
8814
|
+
"session.restore",
|
|
8815
|
+
{
|
|
8816
|
+
"qwen-code.daemon.bridge.operation": `session.${action}`,
|
|
8817
|
+
"qwen-code.daemon.session_restore.action": action,
|
|
8818
|
+
"qwen-code.daemon.acp_channel.id": restoreChannel.id,
|
|
8819
|
+
"qwen-code.daemon.session_restore.timeout_ms": sessionRestoreTimeoutMs,
|
|
8820
|
+
"session.id": req.sessionId
|
|
8821
|
+
},
|
|
8822
|
+
async () => {
|
|
8823
|
+
if (action === "load") {
|
|
8824
|
+
const request2 = telemetry.injectPromptContext({
|
|
8351
8825
|
sessionId: req.sessionId,
|
|
8352
8826
|
cwd: workspaceKey,
|
|
8353
8827
|
// Restore path drops per-request `mcpServers` (matches
|
|
@@ -8356,49 +8830,88 @@ function createAcpSessionBridge(opts) {
|
|
|
8356
8830
|
// intentionally has no `mcpServers` field for the
|
|
8357
8831
|
// same reason.
|
|
8358
8832
|
mcpServers: [],
|
|
8359
|
-
|
|
8360
|
-
|
|
8361
|
-
|
|
8362
|
-
|
|
8363
|
-
|
|
8364
|
-
|
|
8365
|
-
...historyReplay === "response" ? {
|
|
8366
|
-
[LOAD_REPLAY_MODE_META_KEY]: LOAD_REPLAY_BULK_MODE,
|
|
8367
|
-
...req.historyPageSize !== void 0 ? {
|
|
8368
|
-
[LOAD_REPLAY_PAGE_SIZE_META_KEY]: req.historyPageSize
|
|
8369
|
-
} : {}
|
|
8370
|
-
} : {},
|
|
8371
|
-
...hideInheritedHistory ? {
|
|
8372
|
-
[LOAD_REPLAY_HIDE_INHERITED_META_KEY]: true
|
|
8833
|
+
_meta: {
|
|
8834
|
+
...sessionSourceRequestMeta(req.sourceType, req.sourceId),
|
|
8835
|
+
...historyReplay === "response" ? {
|
|
8836
|
+
[LOAD_REPLAY_MODE_META_KEY]: LOAD_REPLAY_BULK_MODE,
|
|
8837
|
+
...req.historyPageSize !== void 0 ? {
|
|
8838
|
+
[LOAD_REPLAY_PAGE_SIZE_META_KEY]: req.historyPageSize
|
|
8373
8839
|
} : {}
|
|
8374
|
-
}
|
|
8375
|
-
|
|
8376
|
-
|
|
8377
|
-
|
|
8378
|
-
|
|
8379
|
-
|
|
8380
|
-
|
|
8381
|
-
|
|
8382
|
-
|
|
8383
|
-
|
|
8384
|
-
|
|
8385
|
-
|
|
8386
|
-
|
|
8387
|
-
|
|
8388
|
-
|
|
8389
|
-
|
|
8390
|
-
|
|
8391
|
-
|
|
8392
|
-
|
|
8393
|
-
|
|
8394
|
-
|
|
8395
|
-
|
|
8396
|
-
|
|
8397
|
-
|
|
8398
|
-
)
|
|
8399
|
-
|
|
8400
|
-
|
|
8401
|
-
|
|
8840
|
+
} : {},
|
|
8841
|
+
...hideInheritedHistory ? { [LOAD_REPLAY_HIDE_INHERITED_META_KEY]: true } : {}
|
|
8842
|
+
}
|
|
8843
|
+
});
|
|
8844
|
+
return await restoreChannel.connection.loadSession(request2);
|
|
8845
|
+
}
|
|
8846
|
+
const request = telemetry.injectPromptContext({
|
|
8847
|
+
sessionId: req.sessionId,
|
|
8848
|
+
cwd: workspaceKey,
|
|
8849
|
+
mcpServers: [],
|
|
8850
|
+
_meta: sessionSourceRequestMeta(req.sourceType, req.sourceId)
|
|
8851
|
+
});
|
|
8852
|
+
return await restoreChannel.connection.unstable_resumeSession(
|
|
8853
|
+
request
|
|
8854
|
+
);
|
|
8855
|
+
}
|
|
8856
|
+
);
|
|
8857
|
+
const observedRestore = Promise.race([rawRestore, transportClosed]);
|
|
8858
|
+
state = await new Promise((resolve2, reject) => {
|
|
8859
|
+
const timer = setTimeout(() => {
|
|
8860
|
+
if (restoreLifecycle.phase !== "active") return;
|
|
8861
|
+
restoreLifecycle.phase = "abandoned";
|
|
8862
|
+
restoreChannel.pendingRestoreIds.delete(req.sessionId);
|
|
8863
|
+
restoreChannel.client.markRestoreAbandoned(req.sessionId);
|
|
8864
|
+
pendingRestoreEvents.delete(req.sessionId);
|
|
8865
|
+
restoreEvents.close();
|
|
8866
|
+
restoreChannel.unsettledAbandonedRestores.add(req.sessionId);
|
|
8867
|
+
const channelWasEmpty = hasNoChannelWork(restoreChannel);
|
|
8868
|
+
telemetry.event("session.restore.public_result", {
|
|
8869
|
+
"qwen-code.daemon.session_restore.action": action,
|
|
8870
|
+
"qwen-code.daemon.session_restore.result": "timeout",
|
|
8871
|
+
"qwen-code.daemon.session_restore.timeout_ms": sessionRestoreTimeoutMs,
|
|
8872
|
+
"qwen-code.daemon.acp_channel.id": restoreChannel.id,
|
|
8873
|
+
"qwen-code.daemon.session_restore.channel_was_empty": channelWasEmpty,
|
|
8874
|
+
"session.id": req.sessionId
|
|
8875
|
+
});
|
|
8876
|
+
writeStderrLine(
|
|
8877
|
+
`qwen serve: session/${action} timed out after ${sessionRestoreTimeoutMs}ms for ${JSON.stringify(req.sessionId)} on channel ${restoreChannel.id}; decision=${channelWasEmpty ? "kill_empty" : "fence_shared"}`
|
|
8878
|
+
);
|
|
8879
|
+
if (channelWasEmpty) {
|
|
8880
|
+
void killChannelWithLog(
|
|
8881
|
+
restoreChannel,
|
|
8882
|
+
`timed-out session/${action} on empty channel`
|
|
8883
|
+
);
|
|
8884
|
+
} else {
|
|
8885
|
+
armRestoreSettlementGrace(restoreChannel, req.sessionId, action);
|
|
8886
|
+
}
|
|
8887
|
+
reject(
|
|
8888
|
+
new SessionRestoreTimeoutError(
|
|
8889
|
+
req.sessionId,
|
|
8890
|
+
action,
|
|
8891
|
+
sessionRestoreTimeoutMs
|
|
8892
|
+
)
|
|
8893
|
+
);
|
|
8894
|
+
}, sessionRestoreTimeoutMs);
|
|
8895
|
+
timer.unref();
|
|
8896
|
+
void observedRestore.then(
|
|
8897
|
+
(value) => {
|
|
8898
|
+
if (restoreLifecycle.phase === "active") {
|
|
8899
|
+
clearTimeout(timer);
|
|
8900
|
+
resolve2(value);
|
|
8901
|
+
return;
|
|
8902
|
+
}
|
|
8903
|
+
void settleAbandonedRestore(restoreChannel, "success");
|
|
8904
|
+
},
|
|
8905
|
+
(error) => {
|
|
8906
|
+
if (restoreLifecycle.phase === "active") {
|
|
8907
|
+
clearTimeout(timer);
|
|
8908
|
+
reject(error);
|
|
8909
|
+
return;
|
|
8910
|
+
}
|
|
8911
|
+
void settleAbandonedRestore(restoreChannel, "failure");
|
|
8912
|
+
}
|
|
8913
|
+
);
|
|
8914
|
+
});
|
|
8402
8915
|
if (action === "load" && historyReplay === "response") {
|
|
8403
8916
|
const extracted = extractLoadReplayResponse(state);
|
|
8404
8917
|
state = extracted.state;
|
|
@@ -8408,6 +8921,7 @@ function createAcpSessionBridge(opts) {
|
|
|
8408
8921
|
replayHasMore = extracted.hasMore === true ? true : void 0;
|
|
8409
8922
|
}
|
|
8410
8923
|
} catch (err) {
|
|
8924
|
+
if (err instanceof SessionRestoreTimeoutError) throw err;
|
|
8411
8925
|
restoreEvents.close();
|
|
8412
8926
|
if (isAcpSessionResourceNotFound(err, req.sessionId)) {
|
|
8413
8927
|
throw new SessionNotFoundError(req.sessionId);
|
|
@@ -8544,6 +9058,7 @@ function createAcpSessionBridge(opts) {
|
|
|
8544
9058
|
...replayFieldsFor(entry, action)
|
|
8545
9059
|
};
|
|
8546
9060
|
})().finally(async () => {
|
|
9061
|
+
if (restoreLifecycle.phase === "abandoned") return;
|
|
8547
9062
|
releaseAdmissionOnce();
|
|
8548
9063
|
ci?.pendingRestoreIds.delete(req.sessionId);
|
|
8549
9064
|
ci?.client.clearRestoreInFlight(req.sessionId);
|
|
@@ -8573,18 +9088,48 @@ function createAcpSessionBridge(opts) {
|
|
|
8573
9088
|
await reapPendingEmptyChannel(ci);
|
|
8574
9089
|
}
|
|
8575
9090
|
});
|
|
9091
|
+
void promise.then(
|
|
9092
|
+
() => {
|
|
9093
|
+
if (restoreLifecycle.phase === "active") {
|
|
9094
|
+
telemetry.event("session.restore.public_result", {
|
|
9095
|
+
"qwen-code.daemon.session_restore.action": action,
|
|
9096
|
+
"qwen-code.daemon.session_restore.result": "success",
|
|
9097
|
+
"qwen-code.daemon.session_restore.timeout_ms": sessionRestoreTimeoutMs,
|
|
9098
|
+
...ci ? { "qwen-code.daemon.acp_channel.id": ci.id } : {},
|
|
9099
|
+
"session.id": req.sessionId
|
|
9100
|
+
});
|
|
9101
|
+
resolveSettlement();
|
|
9102
|
+
}
|
|
9103
|
+
},
|
|
9104
|
+
() => {
|
|
9105
|
+
if (restoreLifecycle.phase === "active") {
|
|
9106
|
+
telemetry.event("session.restore.public_result", {
|
|
9107
|
+
"qwen-code.daemon.session_restore.action": action,
|
|
9108
|
+
"qwen-code.daemon.session_restore.result": "failure",
|
|
9109
|
+
"qwen-code.daemon.session_restore.timeout_ms": sessionRestoreTimeoutMs,
|
|
9110
|
+
...ci ? { "qwen-code.daemon.acp_channel.id": ci.id } : {},
|
|
9111
|
+
"session.id": req.sessionId
|
|
9112
|
+
});
|
|
9113
|
+
resolveSettlement();
|
|
9114
|
+
}
|
|
9115
|
+
}
|
|
9116
|
+
);
|
|
8576
9117
|
inFlightRestores.set(req.sessionId, {
|
|
8577
9118
|
action,
|
|
8578
9119
|
historyReplay,
|
|
8579
9120
|
hideInheritedHistory,
|
|
8580
|
-
promise,
|
|
9121
|
+
publicPromise: promise,
|
|
9122
|
+
settlementPromise,
|
|
9123
|
+
lifecycle: restoreLifecycle,
|
|
8581
9124
|
coalesceState
|
|
8582
9125
|
});
|
|
8583
|
-
|
|
8584
|
-
|
|
8585
|
-
|
|
8586
|
-
|
|
8587
|
-
|
|
9126
|
+
void settlementPromise.finally(() => {
|
|
9127
|
+
const current = inFlightRestores.get(req.sessionId);
|
|
9128
|
+
if (current?.settlementPromise === settlementPromise) {
|
|
9129
|
+
inFlightRestores.delete(req.sessionId);
|
|
9130
|
+
}
|
|
9131
|
+
});
|
|
9132
|
+
return await promise;
|
|
8588
9133
|
}
|
|
8589
9134
|
__name(restoreSession, "restoreSession");
|
|
8590
9135
|
async function closeSessionImpl(sessionId, context, closeOpts) {
|
|
@@ -8622,7 +9167,8 @@ function createAcpSessionBridge(opts) {
|
|
|
8622
9167
|
entry.pendingInteractions.clear();
|
|
8623
9168
|
await notifyAgentSessionClose(entry, ci, "closeSession", {
|
|
8624
9169
|
throwOnFailure: true,
|
|
8625
|
-
requireFlush: closeOpts?.requireAgentClose === true
|
|
9170
|
+
requireFlush: closeOpts?.requireAgentClose === true,
|
|
9171
|
+
...closeOpts?.agentCloseTimeoutMs !== void 0 ? { timeoutMs: closeOpts.agentCloseTimeoutMs } : {}
|
|
8626
9172
|
});
|
|
8627
9173
|
} catch (error) {
|
|
8628
9174
|
if (isDefinitiveAcpRequestError(error)) {
|
|
@@ -8827,7 +9373,7 @@ function createAcpSessionBridge(opts) {
|
|
|
8827
9373
|
if (req.sessionScope !== void 0 && req.sessionScope !== "single" && req.sessionScope !== "thread") {
|
|
8828
9374
|
throw new InvalidSessionScopeError(req.sessionScope);
|
|
8829
9375
|
}
|
|
8830
|
-
const effectiveScope = req.sessionScope ?? defaultSessionScope;
|
|
9376
|
+
const effectiveScope = req.sessionId !== void 0 ? "thread" : req.sessionScope ?? defaultSessionScope;
|
|
8831
9377
|
const source = parseSessionSource(req.sourceType, req.sourceId);
|
|
8832
9378
|
if ("error" in source) {
|
|
8833
9379
|
throw new InvalidSessionMetadataError("sourceType", source.error);
|
|
@@ -8914,13 +9460,51 @@ function createAcpSessionBridge(opts) {
|
|
|
8914
9460
|
};
|
|
8915
9461
|
}
|
|
8916
9462
|
}
|
|
9463
|
+
if (req.sessionId !== void 0) {
|
|
9464
|
+
const restoreOwner = inFlightRestores.get(req.sessionId);
|
|
9465
|
+
if (restoreOwner) {
|
|
9466
|
+
const abandoned = restoreOwner.lifecycle.phase === "abandoned";
|
|
9467
|
+
throw new RestoreInProgressError(
|
|
9468
|
+
req.sessionId,
|
|
9469
|
+
restoreOwner.action,
|
|
9470
|
+
"spawn",
|
|
9471
|
+
abandoned ? {
|
|
9472
|
+
reason: "awaiting_abandoned_cleanup",
|
|
9473
|
+
retryAfterSeconds: abandonedRestoreRetryAfterSeconds
|
|
9474
|
+
} : void 0
|
|
9475
|
+
);
|
|
9476
|
+
}
|
|
9477
|
+
if (inFlightRequestedSessionSpawns.has(req.sessionId)) {
|
|
9478
|
+
throw new RestoreInProgressError(req.sessionId, "spawn", "spawn");
|
|
9479
|
+
}
|
|
9480
|
+
}
|
|
9481
|
+
assertFreshSessionsAvailable();
|
|
8917
9482
|
if (byId.size + inFlightSpawns.size + inFlightRestores.size >= maxSessions) {
|
|
8918
9483
|
throw new SessionLimitExceededError(maxSessions);
|
|
8919
9484
|
}
|
|
8920
|
-
const
|
|
8921
|
-
|
|
8922
|
-
|
|
8923
|
-
|
|
9485
|
+
const requestedSessionRegistrationOwner = req.sessionId !== void 0 ? Symbol(req.sessionId) : void 0;
|
|
9486
|
+
if (req.sessionId !== void 0 && requestedSessionRegistrationOwner !== void 0) {
|
|
9487
|
+
inFlightRequestedSessionSpawns.set(
|
|
9488
|
+
req.sessionId,
|
|
9489
|
+
requestedSessionRegistrationOwner
|
|
9490
|
+
);
|
|
9491
|
+
}
|
|
9492
|
+
const releaseRequestedSessionRegistration = /* @__PURE__ */ __name(() => {
|
|
9493
|
+
if (req.sessionId !== void 0 && requestedSessionRegistrationOwner !== void 0 && inFlightRequestedSessionSpawns.get(req.sessionId) === requestedSessionRegistrationOwner) {
|
|
9494
|
+
inFlightRequestedSessionSpawns.delete(req.sessionId);
|
|
9495
|
+
}
|
|
9496
|
+
}, "releaseRequestedSessionRegistration");
|
|
9497
|
+
let admission;
|
|
9498
|
+
try {
|
|
9499
|
+
admission = reserveFreshSession({
|
|
9500
|
+
operation: "spawn",
|
|
9501
|
+
workspaceCwd: workspaceKey,
|
|
9502
|
+
...req.sessionId !== void 0 ? { sessionId: req.sessionId } : {}
|
|
9503
|
+
});
|
|
9504
|
+
} catch (error) {
|
|
9505
|
+
releaseRequestedSessionRegistration();
|
|
9506
|
+
throw error;
|
|
9507
|
+
}
|
|
8924
9508
|
let admissionReleased = false;
|
|
8925
9509
|
const releaseAdmissionOnce = /* @__PURE__ */ __name(() => {
|
|
8926
9510
|
if (admissionReleased) return;
|
|
@@ -8947,6 +9531,7 @@ function createAcpSessionBridge(opts) {
|
|
|
8947
9531
|
} finally {
|
|
8948
9532
|
releaseAdmissionOnce();
|
|
8949
9533
|
inFlightSpawns.delete(tracker);
|
|
9534
|
+
releaseRequestedSessionRegistration();
|
|
8950
9535
|
}
|
|
8951
9536
|
},
|
|
8952
9537
|
// Keep this method non-async: admission failures must throw before
|
|
@@ -9528,6 +10113,7 @@ function createAcpSessionBridge(opts) {
|
|
|
9528
10113
|
if (entry.promptActive && !isSideTask) {
|
|
9529
10114
|
throw new BranchWhilePromptActiveError(sessionId);
|
|
9530
10115
|
}
|
|
10116
|
+
assertFreshSessionsAvailable();
|
|
9531
10117
|
if (byId.size + inFlightSpawns.size + inFlightRestores.size >= maxSessions) {
|
|
9532
10118
|
throw new SessionLimitExceededError(maxSessions);
|
|
9533
10119
|
}
|
|
@@ -11486,7 +12072,7 @@ function createAcpSessionBridge(opts) {
|
|
|
11486
12072
|
)
|
|
11487
12073
|
);
|
|
11488
12074
|
const inFlightRestoreAwaits = Array.from(inFlightRestores.values()).map(
|
|
11489
|
-
(restore) => restore.
|
|
12075
|
+
(restore) => restore.settlementPromise.then(
|
|
11490
12076
|
() => void 0,
|
|
11491
12077
|
() => void 0
|
|
11492
12078
|
)
|