@qwen-code/qwen-code 0.21.13 → 0.21.14-preview.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundled/qc-helper/docs/configuration/settings.md +13 -7
- package/bundled/qc-helper/docs/features/code-review.md +5 -1
- package/bundled/qc-helper/docs/features/commands.md +120 -8
- package/bundled/qc-helper/docs/features/sub-agents.md +2 -2
- package/bundled/qc-helper/docs/qwen-serve-deploy-local.md +1 -1
- package/bundled/qc-helper/docs/qwen-serve.md +20 -3
- package/bundled/review/SKILL.md +50 -30
- package/chunks/{MaxSizedBox-UQALOVVT.js → MaxSizedBox-3PZITE2Y.js} +24 -23
- package/chunks/{StandaloneSessionPicker-KEGXNUG6.js → StandaloneSessionPicker-2C34PNGO.js} +41 -40
- package/chunks/{acp-startup-profiler-NMDXYGDN.js → acp-startup-profiler-HUYGO57H.js} +2 -2
- package/chunks/{acpAgent-XPES32S7.js → acpAgent-3J4NHAYT.js} +626 -141
- package/chunks/{agent-DPTOZFEM.js → agent-VFX4RPP5.js} +22 -21
- package/chunks/{agent-headless-GJCQMURW.js → agent-headless-6WCF4J6N.js} +22 -21
- package/chunks/{anthropicContentGenerator-G7BVXTKN.js → anthropicContentGenerator-M7XRJMSK.js} +3 -3
- package/chunks/{bridge-YNQBAA4Z.js → bridge-XR5ZSR7U.js} +26 -25
- package/chunks/{ca-4CQ6MYNQ.js → ca-SLZJD6QH.js} +8 -0
- package/chunks/{channel-management-service-GWY2GAIC.js → channel-management-service-X6LCQUAD.js} +1 -1
- package/chunks/{channel-settings-store-WNWYFHG7.js → channel-settings-store-Z7BUEUJE.js} +30 -29
- package/chunks/{channel-worker-group-7LXCMZ77.js → channel-worker-group-TJ35JDPE.js} +2 -2
- package/chunks/{channel-worker-manager-RYEME4ZZ.js → channel-worker-manager-G5LKWGOG.js} +2 -2
- package/chunks/{chunk-MLPXSYXR.js → chunk-25GHLMQQ.js} +25 -16
- package/chunks/chunk-2C6HJMG3.js +757 -0
- package/chunks/{chunk-TUGSVUJB.js → chunk-2JXDFSVE.js} +5 -5
- package/chunks/{chunk-AS5IN4GK.js → chunk-2OA3JMRD.js} +3 -3
- package/chunks/chunk-3PWCMXIR.js +9169 -0
- package/chunks/{chunk-U3VNBPUO.js → chunk-4KQ2TI2K.js} +2 -2
- package/chunks/{chunk-NEFOOD54.js → chunk-4V4DFJBS.js} +2 -2
- package/chunks/{chunk-OMLJNPBE.js → chunk-4ZMS3JCR.js} +1 -0
- package/chunks/{chunk-PP4FUZNV.js → chunk-55PIFSP2.js} +2 -2
- package/chunks/{chunk-3U3VAL47.js → chunk-57KOJ2KZ.js} +1 -1
- package/chunks/{chunk-A4QRWUDE.js → chunk-5IYS4WWR.js} +1 -1
- package/chunks/{chunk-TS6625XH.js → chunk-5MK45KZ3.js} +9 -5
- package/chunks/{chunk-CU6GJD55.js → chunk-6DFPR7CS.js} +1 -1
- package/chunks/{chunk-V57QC6WW.js → chunk-6LAPGPVA.js} +5 -3
- package/chunks/{chunk-OOQUVWIG.js → chunk-6PDOHRN6.js} +4 -4
- package/chunks/{chunk-UZPM4XHR.js → chunk-6VDPDHIP.js} +29 -8
- package/chunks/{chunk-O4D7SPJN.js → chunk-73G3Z7QS.js} +3 -3
- package/chunks/{chunk-QIH2HAEN.js → chunk-7OCSX7FC.js} +1 -1
- package/chunks/{chunk-OVZPVYZB.js → chunk-AKBOLMUF.js} +95 -17
- package/chunks/{chunk-DGK6P3BQ.js → chunk-AQBHJ2IG.js} +10 -10
- package/chunks/{chunk-JNDY2MDR.js → chunk-BOJNAPUE.js} +1 -1
- package/chunks/{chunk-NHDR76JX.js → chunk-BQWNIPTE.js} +1 -1
- package/chunks/{chunk-AA2BEKV3.js → chunk-CH5OFRV7.js} +1 -1
- package/chunks/{chunk-MS7GNABG.js → chunk-CXJHQVEK.js} +8 -0
- package/chunks/{chunk-K5IDV3PC.js → chunk-D34RDOLP.js} +12 -2
- package/chunks/{chunk-OXCMMLED.js → chunk-DGJ7O55J.js} +1 -1
- package/chunks/{chunk-BKPPWD33.js → chunk-DRKYT2TR.js} +1 -1
- package/chunks/{chunk-P7MPQI75.js → chunk-DVR7XKO5.js} +1 -1
- package/chunks/{chunk-MRMJCLIY.js → chunk-DZCV3ZYU.js} +2 -2
- package/chunks/{chunk-EZ5RP345.js → chunk-E5RS7LF4.js} +40 -9
- package/chunks/{chunk-4NFY2S7N.js → chunk-E7REAOTN.js} +15 -0
- package/chunks/chunk-EOCQCNV4.js +3887 -0
- package/chunks/{chunk-BVJS5BSP.js → chunk-FCTLOVYW.js} +1 -1
- package/chunks/{chunk-DGZEMW5R.js → chunk-FS5NGKWC.js} +1 -1
- package/chunks/{chunk-XHRY7BXD.js → chunk-G6FFFICU.js} +3 -3
- package/chunks/{chunk-NM5V5OVW.js → chunk-GV3OIADZ.js} +2 -2
- package/chunks/{chunk-QV5YN5YD.js → chunk-HGPMOXLZ.js} +5 -5
- package/chunks/{chunk-GMIEIY3Y.js → chunk-I3N2Z25H.js} +1 -1
- package/chunks/{chunk-RIAABG2K.js → chunk-I7NTHW4C.js} +1 -1
- package/chunks/{chunk-HUTNYWBG.js → chunk-IOTPI425.js} +18 -10
- package/chunks/{chunk-ZYYTZUI2.js → chunk-ISRHAMNL.js} +3 -3
- package/chunks/{chunk-BHILXOC3.js → chunk-J63PKMYA.js} +1 -1
- package/chunks/{chunk-KD5BOPLP.js → chunk-J6YS7Z25.js} +98 -4
- package/chunks/{chunk-GO7STP6N.js → chunk-K3CECR5C.js} +4 -4
- package/chunks/{chunk-RVOJ2FBP.js → chunk-KC4WMLZO.js} +1486 -10574
- package/chunks/{chunk-IGGGG5CX.js → chunk-KSGWAYNE.js} +4580 -1652
- package/chunks/{chunk-X26JYGTD.js → chunk-L6CCLB3G.js} +1 -1
- package/chunks/{chunk-M6NDLY2T.js → chunk-LD5VIJ7S.js} +1 -1
- package/chunks/{chunk-ZYBBISBY.js → chunk-LLR424CQ.js} +15 -12
- package/chunks/{chunk-JUEPY766.js → chunk-LRDB2OLB.js} +2 -2
- package/chunks/{chunk-PQ36L4F5.js → chunk-MCG53LWC.js} +1 -1
- package/chunks/{chunk-OD2WU5QY.js → chunk-NRPXRNN4.js} +1 -1
- package/chunks/{chunk-76J3IJ3M.js → chunk-NV6LW6FT.js} +3 -3
- package/chunks/{chunk-CKSJECTU.js → chunk-NVRMCWTP.js} +8 -4
- package/chunks/{chunk-Y3YCSWG5.js → chunk-OBJYN4MX.js} +1 -1
- package/chunks/{chunk-WFSTRPRO.js → chunk-OJOP26ET.js} +1 -1
- package/chunks/{chunk-A267JX7H.js → chunk-OLZSWUZR.js} +6 -6
- package/chunks/{chunk-TIGA2IVL.js → chunk-OO4FKHLO.js} +2 -2
- package/chunks/{chunk-OY5RNSV4.js → chunk-OSAFWBNR.js} +3 -3
- package/chunks/{chunk-BZ263IKX.js → chunk-OVY67CYC.js} +1 -1
- package/chunks/{chunk-YEYY7TEP.js → chunk-P425IVUK.js} +5 -5
- package/chunks/{chunk-AFSG32D5.js → chunk-PMS7O6SA.js} +1 -1
- package/chunks/{chunk-6ORZ2EDC.js → chunk-PPTM4O4R.js} +1 -1
- package/chunks/{chunk-JOOFMXGF.js → chunk-QECSDJET.js} +5 -5
- package/chunks/{chunk-CZBYX5MY.js → chunk-QEJZUXSK.js} +1 -1
- package/chunks/{chunk-4PKCUT7F.js → chunk-QIHHJKXT.js} +6 -6
- package/chunks/{chunk-QRCNA3SR.js → chunk-RAQBBGS6.js} +49 -69
- package/chunks/{chunk-M732YJPW.js → chunk-RXHBTKMG.js} +2 -2
- package/chunks/{chunk-XIT3GURH.js → chunk-S6CXQKDD.js} +3 -3
- package/chunks/{chunk-GGDBMYGZ.js → chunk-SA7GBPEA.js} +3 -3
- package/chunks/{chunk-7UXUJ5T3.js → chunk-SBRIBTYN.js} +1 -1
- package/chunks/{chunk-MC4TLKEI.js → chunk-SGLPDKRT.js} +2 -2
- package/chunks/{chunk-WSH6GRKG.js → chunk-SLILKYV2.js} +2 -2
- package/chunks/{chunk-DXIBNLBZ.js → chunk-SNQZZ765.js} +1 -1
- package/chunks/{chunk-5EYKMUUY.js → chunk-SR2LYSMT.js} +1 -1
- package/chunks/{chunk-AW4TRXOC.js → chunk-TNPWODIZ.js} +1 -1
- package/chunks/{chunk-QF2NHSPB.js → chunk-U6RZRKNM.js} +233 -184
- package/chunks/{chunk-QNQAPSN2.js → chunk-UC67T4SF.js} +3 -1
- package/chunks/{chunk-O565M6A4.js → chunk-UYDGFWIJ.js} +199 -14
- package/chunks/{chunk-LJQAUZMR.js → chunk-VGAAAMRD.js} +925 -92
- package/chunks/{chunk-UKMR3CKV.js → chunk-VHPMDDPT.js} +3 -3
- package/chunks/{chunk-S5DWMTHO.js → chunk-WP4WIUOJ.js} +2 -0
- package/chunks/{chunk-25EYDK42.js → chunk-WPVUOVYX.js} +1 -1
- package/chunks/{chunk-AXN7UPYQ.js → chunk-WSSH2BNO.js} +1 -1
- package/chunks/{chunk-6YKYPVDV.js → chunk-WVIABDXV.js} +3 -3
- package/chunks/chunk-WZAD4ZNJ.js +59 -0
- package/chunks/{chunk-N5YPT6PH.js → chunk-X3YA3YGG.js} +7 -4
- package/chunks/{chunk-4S5337WV.js → chunk-XC377TLN.js} +4312 -2704
- package/chunks/{chunk-NNHNLJ2X.js → chunk-XO24LIZC.js} +240 -42
- package/chunks/{chunk-EL5SXY3T.js → chunk-XT4RKHVE.js} +2 -2
- package/chunks/{chunk-FDGGZIYW.js → chunk-YECDICIO.js} +2 -2
- package/chunks/{chunk-E23IPNGS.js → chunk-YFPZ3NNC.js} +12 -3
- package/chunks/{chunk-46UV252V.js → chunk-YHC2EYYG.js} +35 -38
- package/chunks/{chunk-V26NVGAU.js → chunk-YIWH3MKK.js} +8 -3
- package/chunks/{chunk-IWPYVAO2.js → chunk-YXC7JYUI.js} +2 -2
- package/chunks/{chunk-A4MFR4C5.js → chunk-ZIGC3MUS.js} +2 -4
- package/chunks/{chunk-ZZO74WKW.js → chunk-ZXEAEZFN.js} +24 -18
- package/chunks/{computer-use-77C5FHMW.js → computer-use-ABECHPS5.js} +22 -21
- package/chunks/{config-utils-IVHRSXWI.js → config-utils-NJQA5YLJ.js} +2 -2
- package/chunks/{contextCommand-PJ77GBWL.js → contextCommand-4CD5HZQQ.js} +24 -23
- package/chunks/{core-runtime-7VMIKUTG.js → core-runtime-2MOVQ4VX.js} +22 -21
- package/chunks/{create-sub-session-2L5MQRN4.js → create-sub-session-L6NNHG5N.js} +26 -24
- package/chunks/{cron-create-H7UEPDSN.js → cron-create-NFRZEOQX.js} +2 -2
- package/chunks/{cron-delete-6SZK7YFM.js → cron-delete-GFVSVO7C.js} +2 -2
- package/chunks/{cron-list-H25JIHEZ.js → cron-list-NRW34CLU.js} +2 -2
- package/chunks/{daemon-2KTG7ZBN.js → daemon-XH76IXOC.js} +356 -21
- package/chunks/{daemon-git-worktree-guard-DXYIMWFT.js → daemon-git-worktree-guard-BLXFEG4Q.js} +24 -23
- package/chunks/{daemon-status-provider-ZDOYJCU6.js → daemon-status-provider-XGD3TPTO.js} +31 -30
- package/chunks/{daemon-trust-policy-E67OYUK2.js → daemon-trust-policy-THEGCWPO.js} +29 -28
- package/chunks/{daemon-trust-policy-monitor-RYYGCQ3J.js → daemon-trust-policy-monitor-L7L4ACWQ.js} +29 -28
- package/chunks/{de-UBEBKG6V.js → de-AH4LGCF5.js} +8 -0
- package/chunks/{deferred-core-runtime-3SGXFXEQ.js → deferred-core-runtime-YQLHDUGE.js} +22 -21
- package/chunks/{discovery-ORA5J7YP.js → discovery-X2NV535U.js} +1 -1
- package/chunks/{dist-WJ4BHIEW.js → dist-ESS34DHC.js} +72 -0
- package/chunks/{earlyInputCapture-KJMLFVQV.js → earlyInputCapture-PCTXNW7N.js} +22 -21
- package/chunks/{edit-I4LQFAEC.js → edit-QX2EGWYW.js} +25 -23
- package/chunks/{en-X6YV7GME.js → en-MD3GP5YL.js} +8 -0
- package/chunks/{enter-worktree-YNPOJSRH.js → enter-worktree-EM3ZZ2SB.js} +22 -21
- package/chunks/{enterPlanMode-XCPK62ER.js → enterPlanMode-ESCMVAKB.js} +22 -21
- package/chunks/{environment-S7CTIHMX.js → environment-TOJI56YV.js} +25 -24
- package/chunks/{errors-7HB2AIDS.js → errors-DZ5FWWEM.js} +24 -23
- package/chunks/{exit-worktree-AIIY7SR6.js → exit-worktree-KUIJ36XA.js} +22 -21
- package/chunks/{exitPlanMode-R4JY7V2O.js → exitPlanMode-NFVY54FV.js} +22 -21
- package/chunks/{fast-path-NDJV3ZFJ.js → fast-path-JLQXJSH6.js} +3 -3
- package/chunks/{fast-path-settings-LNOFM2YP.js → fast-path-settings-WHX3J3ZI.js} +2 -2
- package/chunks/{fr-VENTC2BS.js → fr-ZEML2JWS.js} +8 -0
- package/chunks/{gemini-RSUFP5OE.js → gemini-I7OT4FWL.js} +62 -61
- package/chunks/{geminiContentGenerator-SQ5XBPZ7.js → geminiContentGenerator-GRIS77NJ.js} +3 -3
- package/chunks/{glob-J4RUJAHX.js → glob-7TBUUV6R.js} +22 -21
- package/chunks/{goal-tools-VHTNVOKK.js → goal-tools-K5OHOJ6B.js} +1 -1
- package/chunks/{grep-VJWPLFOT.js → grep-743SYWCZ.js} +22 -21
- package/chunks/{handleAutoUpdate-POCX2MNB.js → handleAutoUpdate-GAOYUYOD.js} +26 -25
- package/chunks/{i18n-RM5YOICI.js → i18n-2ITURYX6.js} +23 -22
- package/chunks/{image-gen-EXECB5XM.js → image-gen-4OIWDZD6.js} +2 -2
- package/chunks/{initializer-Z2AFGBNR.js → initializer-OC7LWA6X.js} +29 -28
- package/chunks/{installationInfo-4I5FXNMH.js → installationInfo-CO47QX3Q.js} +23 -22
- package/chunks/{ja-QHT4EQTO.js → ja-UM5B2HMD.js} +8 -0
- package/chunks/{list-ZMBFIGZA.js → list-ATR2SFWT.js} +32 -31
- package/chunks/{loadedSettingsAdapter-T6TV4YJ7.js → loadedSettingsAdapter-NK4B7AGK.js} +29 -28
- package/chunks/{loggingContentGenerator-WF4ZOJEZ.js → loggingContentGenerator-3WXBU5TQ.js} +12 -10
- package/chunks/{loop-wakeup-WQS6JYAG.js → loop-wakeup-HWVUU5CF.js} +3 -3
- package/chunks/{managed-npm-update-E7IW6N7V.js → managed-npm-update-4SSBWI2D.js} +23 -22
- package/chunks/{mcp-6UNYX4HG.js → mcp-C62AE2QI.js} +29 -28
- package/chunks/{monitor-EE2UYMGE.js → monitor-FEYEGASA.js} +22 -21
- package/chunks/{nonInteractiveCli-WAY237O4.js → nonInteractiveCli-AJEV5ZWO.js} +59 -57
- package/chunks/{notebook-edit-NTDY4QDU.js → notebook-edit-SLLTEY4O.js} +26 -24
- package/chunks/{openaiContentGenerator-YNFVJMRJ.js → openaiContentGenerator-WLUGIAPX.js} +12 -11
- package/chunks/{pidfile-4XSFLYBZ.js → pidfile-TV2VWUMB.js} +22 -21
- package/chunks/{processUtils-WDA2MJFD.js → processUtils-3IN2ZR55.js} +2 -2
- package/chunks/{pt-VL3I5RNY.js → pt-5BMJ3XYH.js} +8 -0
- package/chunks/{qwenContentGenerator-434M7QKY.js → qwenContentGenerator-GSGRFPJE.js} +25 -24
- package/chunks/{qwenOAuth2-GMYZOO6A.js → qwenOAuth2-JLSTIS4Z.js} +3 -3
- package/chunks/{read-file-TAFBKMNI.js → read-file-6PZZRGZZ.js} +9 -7
- package/chunks/{record-artifact-SEYFJEJF.js → record-artifact-GLU3UWBV.js} +3 -1
- package/chunks/{resumeHistoryUtils-EVG3WYK2.js → resumeHistoryUtils-5GEWKOOO.js} +25 -24
- package/chunks/{ripGrep-WOEK2PXS.js → ripGrep-FX7GBGFN.js} +22 -21
- package/chunks/{ru-4RCKL4PY.js → ru-6GL66ORV.js} +8 -0
- package/chunks/{run-qwen-serve-3QSGRXAN.js → run-qwen-serve-7RHU3NSV.js} +49 -40
- package/chunks/{runtime-5MLLZ7DC.js → runtime-EPOXAMLP.js} +32 -31
- package/chunks/{scheduler-RPBJ63CH.js → scheduler-F4Y7ENVV.js} +24 -23
- package/chunks/{sdk-exporters-http-XUVP63H6.js → sdk-exporters-http-NC746HLT.js} +2 -2
- package/chunks/{sdk-impl-YXUEN2Z2.js → sdk-impl-YVL7BP6Y.js} +2 -2
- package/chunks/{send-message-VZENRWRH.js → send-message-TNBG5EVA.js} +1 -1
- package/chunks/{serve-HS3XLPXU.js → serve-LQV4TN5A.js} +29 -30
- package/chunks/{server-TC4A7AAZ.js → server-IZCKLIYQ.js} +1267 -165
- package/chunks/{session-UBOFXVMN.js → session-52ZGTDVB.js} +60 -58
- package/chunks/{settings-D5644OM5.js → settings-WCVB34HW.js} +28 -27
- package/chunks/{shell-3PZULQQV.js → shell-33BIUBLH.js} +22 -21
- package/chunks/{skill-PEVVXQ3L.js → skill-IYVQ2QNK.js} +11 -9
- package/chunks/{skill-settings-J65JKKES.js → skill-settings-YG4ZS4OZ.js} +28 -27
- package/chunks/{spawnChannel-IYGXRHSQ.js → spawnChannel-BLA4YT4W.js} +24 -23
- package/chunks/{standalone-update-IFM53PE7.js → standalone-update-ALRIPWSM.js} +24 -23
- package/chunks/{startInteractiveUI-3AVH7L6H.js → startInteractiveUI-PISBXWKA.js} +262 -191
- package/chunks/{task-create-FCBDX7UH.js → task-create-EILHJJB7.js} +4 -4
- package/chunks/{task-list-YIYIUFUA.js → task-list-WGJR6YL5.js} +18 -4
- package/chunks/{task-update-MYPFVOVM.js → task-update-XZAHVXJ5.js} +79 -8
- package/chunks/{team-create-ZAIA7KAV.js → team-create-CIQDCC6A.js} +23 -23
- package/chunks/{team-delete-6UMU4XLS.js → team-delete-UEP4QOOT.js} +3 -3
- package/chunks/{team-plan-approval-UNIUS7OD.js → team-plan-approval-664XCRB4.js} +22 -21
- package/chunks/{terminal-image-renderer-G343P2RV.js → terminal-image-renderer-TEBO6ONY.js} +22 -21
- package/chunks/{theme-manager-Z3RIT7DB.js → theme-manager-3CIFH2JV.js} +22 -21
- package/chunks/{todoWrite-U2R4NVF4.js → todoWrite-ATS62CAP.js} +1 -1
- package/chunks/{tool-search-5R2OE4C7.js → tool-search-IJX5JHJB.js} +9 -7
- package/chunks/{total-session-admission-4KBHMQQ2.js → total-session-admission-XBK2NVRV.js} +26 -25
- package/chunks/{trustedFolders-LK6T4XC7.js → trustedFolders-OOFNLRWK.js} +23 -22
- package/chunks/{update-relaunch-UBKROIC6.js → update-relaunch-EIG7EYAQ.js} +5 -5
- package/chunks/{updateCheck-W4Y2GFSD.js → updateCheck-KYDCBLSF.js} +25 -24
- package/chunks/{useAutoAcceptIndicator-C7BEICBF.js → useAutoAcceptIndicator-RFX3KNBN.js} +31 -30
- package/chunks/{validateNonInterActiveAuth-LTEI2TB6.js → validateNonInterActiveAuth-MZXSAITU.js} +56 -54
- package/chunks/{version-G5A5DGVS.js → version-PJC6ZNXV.js} +1 -1
- package/chunks/{web-fetch-RTEQTR5Z.js → web-fetch-XXICVGKQ.js} +11 -8
- package/chunks/{web-search-5OXHEZPV.js → web-search-LHPM6QWC.js} +2 -2
- package/chunks/{workflow-ISQJHPG2.js → workflow-4CUO2BV7.js} +139 -37
- package/chunks/{workspace-providers-status-2ZPZPUPZ.js → workspace-providers-status-G4MUGH3X.js} +32 -31
- package/chunks/{workspace-registration-store-CYNY6IP6.js → workspace-registration-store-QMDMFWBE.js} +1 -1
- package/chunks/{workspace-registry-34GTUUHB.js → workspace-registry-FKBB4MZK.js} +26 -25
- package/chunks/{workspace-service-XCDQLE2Y.js → workspace-service-TIDTTA65.js} +33 -32
- package/chunks/{workspace-skills-status-RS4O7AIJ.js → workspace-skills-status-LBC2TZKM.js} +30 -29
- package/chunks/{workspace-trust-reconciler-AYGXC7A3.js → workspace-trust-reconciler-4KJ567XP.js} +33 -32
- package/chunks/{write-file-EWXKVVXF.js → write-file-R6LAEER5.js} +22 -21
- package/chunks/{zh-TW-SQ4HTSCW.js → zh-TW-LVLBK4KF.js} +8 -0
- package/chunks/{zh-LMSTK4WD.js → zh-UBMWS2BJ.js} +8 -0
- package/chunks/{zoom-image-4BFYJ3HG.js → zoom-image-XLCK6DDK.js} +14 -11
- package/cli.js +13 -13
- package/locales/ca.js +13 -0
- package/locales/de.js +12 -0
- package/locales/en.js +11 -0
- package/locales/fr.js +13 -0
- package/locales/ja.js +13 -0
- package/locales/pt.js +12 -0
- package/locales/ru.js +12 -0
- package/locales/zh-TW.js +11 -0
- package/locales/zh.js +11 -0
- package/package.json +3 -3
- package/web-shell/assets/{arc-CgOpDKvm.js → arc-DItbX0DI.js} +1 -1
- package/web-shell/assets/{architectureDiagram-3BPJPVTR-0Ag_m34F.js → architectureDiagram-3BPJPVTR-CmnIlH8y.js} +1 -1
- package/web-shell/assets/{blockDiagram-GPEHLZMM-IwTwFau0.js → blockDiagram-GPEHLZMM-pObnB9kw.js} +1 -1
- package/web-shell/assets/{c4Diagram-AAUBKEIU-DLa5GUv8.js → c4Diagram-AAUBKEIU-BNBmMS0Y.js} +1 -1
- package/web-shell/assets/channel-hZnMfWA9.js +1 -0
- package/web-shell/assets/{chunk-2J33WTMH-DcYP-WFG.js → chunk-2J33WTMH-Dz4JBOO6.js} +1 -1
- package/web-shell/assets/{chunk-4BX2VUAB-C8MVPMiQ.js → chunk-4BX2VUAB-Cz2GnvAR.js} +1 -1
- package/web-shell/assets/{chunk-55IACEB6-BUi4Yfv3.js → chunk-55IACEB6-CC6kOQYx.js} +1 -1
- package/web-shell/assets/{chunk-727SXJPM-Cy3Su2YY.js → chunk-727SXJPM-Z4lY4gbh.js} +1 -1
- package/web-shell/assets/{chunk-AQP2D5EJ-Dp8Teqv6.js → chunk-AQP2D5EJ-Yz0hZr3D.js} +1 -1
- package/web-shell/assets/{chunk-FMBD7UC4-BDTDM-4j.js → chunk-FMBD7UC4-nKmTWTv9.js} +1 -1
- package/web-shell/assets/{chunk-ND2GUHAM-7HfDt0r2.js → chunk-ND2GUHAM-CjZz0f6Y.js} +1 -1
- package/web-shell/assets/{chunk-QZHKN3VN-BIBU0uCF.js → chunk-QZHKN3VN-Bab3FpuS.js} +1 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-BRnxm8DX.js +1 -0
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-BRnxm8DX.js +1 -0
- package/web-shell/assets/{cose-bilkent-S5V4N54A-DRLdcg9p.js → cose-bilkent-S5V4N54A-BuSAGFox.js} +1 -1
- package/web-shell/assets/{dagre-BM42HDAG-DCCgDwqW.js → dagre-BM42HDAG-CRZXTg3g.js} +1 -1
- package/web-shell/assets/{diagram-2AECGRRQ-CsBTBmk3.js → diagram-2AECGRRQ-BFx1Ayrz.js} +1 -1
- package/web-shell/assets/{diagram-5GNKFQAL-C9qjH8Lt.js → diagram-5GNKFQAL-B2hMZ3gS.js} +1 -1
- package/web-shell/assets/{diagram-KO2AKTUF-Brjs_lj2.js → diagram-KO2AKTUF-DKxAQLmc.js} +1 -1
- package/web-shell/assets/{diagram-LMA3HP47-DtiWCl_F.js → diagram-LMA3HP47-Bo1xGqVY.js} +1 -1
- package/web-shell/assets/{diagram-OG6HWLK6-DmfKLkBT.js → diagram-OG6HWLK6-B9NG78d-.js} +1 -1
- package/web-shell/assets/{erDiagram-TEJ5UH35-Bve_4deH.js → erDiagram-TEJ5UH35-DltQKiqQ.js} +1 -1
- package/web-shell/assets/{flowDiagram-I6XJVG4X-C2_kXCcV.js → flowDiagram-I6XJVG4X-5xXGmS4I.js} +1 -1
- package/web-shell/assets/{ganttDiagram-6RSMTGT7-BSBIjiTF.js → ganttDiagram-6RSMTGT7-bhGL5n0l.js} +1 -1
- package/web-shell/assets/{gitGraphDiagram-PVQCEYII-CyebwI55.js → gitGraphDiagram-PVQCEYII-ZYnz9hgh.js} +1 -1
- package/web-shell/assets/{index-d0yfnV1M.js → index-CBBeUArD.js} +1 -1
- package/web-shell/assets/index-CbgU-jUo.css +5 -0
- package/web-shell/assets/index-_nhzXqab.js +1750 -0
- package/web-shell/assets/{infoDiagram-5YYISTIA-CSDGnWxU.js → infoDiagram-5YYISTIA-Cg-jamQf.js} +1 -1
- package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-BK4jU13p.js → ishikawaDiagram-YF4QCWOH-CcmvKlyq.js} +1 -1
- package/web-shell/assets/{journeyDiagram-JHISSGLW-D_W6j-oF.js → journeyDiagram-JHISSGLW-BRsOQZp1.js} +1 -1
- package/web-shell/assets/{kanban-definition-UN3LZRKU-C7xf-SdC.js → kanban-definition-UN3LZRKU-xW-dmEHK.js} +1 -1
- package/web-shell/assets/{linear-DQmzxpxd.js → linear-ClBfEZH2.js} +1 -1
- package/web-shell/assets/{mermaid.core-9P7AGOLG.js → mermaid.core-D65NDkzc.js} +5 -5
- package/web-shell/assets/{mindmap-definition-RKZ34NQL-DgcgMyPk.js → mindmap-definition-RKZ34NQL-CyvFslYa.js} +1 -1
- package/web-shell/assets/{pieDiagram-4H26LBE5-3wWGb9eG.js → pieDiagram-4H26LBE5-BwSefMyG.js} +1 -1
- package/web-shell/assets/{quadrantDiagram-W4KKPZXB-BeCXnQw9.js → quadrantDiagram-W4KKPZXB-GqBJspFS.js} +1 -1
- package/web-shell/assets/{requirementDiagram-4Y6WPE33-Bi1UOHDz.js → requirementDiagram-4Y6WPE33-B137PlTJ.js} +1 -1
- package/web-shell/assets/{sankeyDiagram-5OEKKPKP-lrLUjjbb.js → sankeyDiagram-5OEKKPKP-maHkkt8i.js} +1 -1
- package/web-shell/assets/{sequenceDiagram-3UESZ5HK-BFuqKz6Q.js → sequenceDiagram-3UESZ5HK-DJ1mRaG3.js} +1 -1
- package/web-shell/assets/{stateDiagram-AJRCARHV-8DemQLhu.js → stateDiagram-AJRCARHV-aRmP7Q4i.js} +1 -1
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-Db39gvZ_.js +1 -0
- package/web-shell/assets/{timeline-definition-PNZ67QCA-uzEuVQXg.js → timeline-definition-PNZ67QCA-CIQ3BRPA.js} +1 -1
- package/web-shell/assets/{vennDiagram-CIIHVFJN-BQTeZ_-o.js → vennDiagram-CIIHVFJN-DR9VPd5h.js} +1 -1
- package/web-shell/assets/{wardley-L42UT6IY-B6yM5Im7.js → wardley-L42UT6IY-ZcfIbT4D.js} +1 -1
- package/web-shell/assets/{wardleyDiagram-YWT4CUSO-ChM8bmgn.js → wardleyDiagram-YWT4CUSO-D0jgPi4T.js} +1 -1
- package/web-shell/assets/{xychartDiagram-2RQKCTM6-oNG6HyB1.js → xychartDiagram-2RQKCTM6-BGWU4s5o.js} +1 -1
- package/web-shell/index.html +2 -2
- package/chunks/chunk-MPHPFVKK.js +0 -48
- package/chunks/chunk-RLKC46YT.js +0 -3582
- package/chunks/chunk-UPDOZBWO.js +0 -358
- package/web-shell/assets/channel-BrGVBa2L.js +0 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-B5TUzJzI.js +0 -1
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-B5TUzJzI.js +0 -1
- package/web-shell/assets/index-CIDsgxTe.js +0 -1792
- package/web-shell/assets/index-DiQnWi_E.css +0 -5
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-DhM5ixYd.js +0 -1
- /package/chunks/{chunk-NTTBXH7U.js → chunk-UGK4K2N2.js} +0 -0
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
} from "./chunk-OCPBI7J5.js";
|
|
20
20
|
import {
|
|
21
21
|
defaultSpawnChannelFactory
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-BQWNIPTE.js";
|
|
23
23
|
import {
|
|
24
24
|
BridgeChannelClosedError,
|
|
25
25
|
BridgeTimeoutError,
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
SessionRestoreTimeoutError,
|
|
30
30
|
createIdleWorkspaceExtensionsStatus,
|
|
31
31
|
createIdleWorkspaceHooksStatus
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-UC67T4SF.js";
|
|
33
33
|
import {
|
|
34
34
|
ACTIVE_WORK_CLOSE_IF_UNHELD_PARAM,
|
|
35
35
|
ACTIVE_WORK_CLOSE_TIMEOUT_MS,
|
|
@@ -45,6 +45,7 @@ import {
|
|
|
45
45
|
CHANNEL_STARTUP_PROFILE_META_KEY,
|
|
46
46
|
CHANNEL_STARTUP_PROFILE_VERSION,
|
|
47
47
|
DAEMON_CHANNEL_DELIVERY_META_KEY,
|
|
48
|
+
DAEMON_MEDIA_REFERENCES_META_KEY,
|
|
48
49
|
DAEMON_MODEL_PROMPT_META_KEY,
|
|
49
50
|
DAEMON_PROMPT_DISPLAY_TEXT_META_KEY,
|
|
50
51
|
LOAD_REPLAY_BULK_MODE,
|
|
@@ -64,7 +65,7 @@ import {
|
|
|
64
65
|
clampActiveWorkIntervalMs,
|
|
65
66
|
isValidTrustedModelPrompt,
|
|
66
67
|
sessionCloseDrainBudgetMs
|
|
67
|
-
} from "./chunk-
|
|
68
|
+
} from "./chunk-WP4WIUOJ.js";
|
|
68
69
|
import {
|
|
69
70
|
BranchWhilePromptActiveError,
|
|
70
71
|
BridgeChannelQuarantinedError,
|
|
@@ -113,6 +114,8 @@ import {
|
|
|
113
114
|
SESSION_ARTIFACT_PERSISTENCE_VERSION,
|
|
114
115
|
SESSION_TRANSCRIPT_MAX_LIMIT,
|
|
115
116
|
ShellExecutionService,
|
|
117
|
+
TURN_RESULT_CODE_TEXT_TRUNCATED,
|
|
118
|
+
TURN_RESULT_TEXT_MAX_CHARS,
|
|
116
119
|
TrustGateError,
|
|
117
120
|
WORKSPACE_CONTENT_MTIME_MS_METADATA_KEY,
|
|
118
121
|
WORKSPACE_CONTENT_SHA256_METADATA_KEY,
|
|
@@ -120,17 +123,18 @@ import {
|
|
|
120
123
|
isReservedWorkspaceMetadataKey,
|
|
121
124
|
metadataBudgetBytes,
|
|
122
125
|
normalizeSnapshotPayload,
|
|
126
|
+
normalizeTurnResultError,
|
|
123
127
|
stableSessionArtifactId
|
|
124
|
-
} from "./chunk-
|
|
128
|
+
} from "./chunk-XC377TLN.js";
|
|
125
129
|
import {
|
|
126
130
|
DAEMON_TRACEPARENT_META_KEY,
|
|
127
131
|
DAEMON_TRACESTATE_META_KEY
|
|
128
|
-
} from "./chunk-
|
|
132
|
+
} from "./chunk-OO4FKHLO.js";
|
|
129
133
|
import {
|
|
130
134
|
INVOCATION_CONTEXT_META_KEY,
|
|
131
135
|
PRIVATE_ACP_CAPABILITY_ENV,
|
|
132
136
|
PRIVATE_PARENT_CAPABILITY_META_KEY
|
|
133
|
-
} from "./chunk-
|
|
137
|
+
} from "./chunk-KC4WMLZO.js";
|
|
134
138
|
import {
|
|
135
139
|
init_esbuild_shims
|
|
136
140
|
} from "./chunk-5O2XNYP6.js";
|
|
@@ -140,8 +144,8 @@ import {
|
|
|
140
144
|
|
|
141
145
|
// packages/acp-bridge/src/bridge.ts
|
|
142
146
|
init_esbuild_shims();
|
|
143
|
-
import { randomBytes, randomUUID as
|
|
144
|
-
import * as
|
|
147
|
+
import { randomBytes, randomUUID as randomUUID3 } from "node:crypto";
|
|
148
|
+
import * as path4 from "node:path";
|
|
145
149
|
import { inspect } from "node:util";
|
|
146
150
|
|
|
147
151
|
// packages/acp-bridge/src/compactionEngine.ts
|
|
@@ -1280,6 +1284,267 @@ function getChannelStartupProfileAttributes(response, receivedAtEpochMs, initial
|
|
|
1280
1284
|
}
|
|
1281
1285
|
__name(getChannelStartupProfileAttributes, "getChannelStartupProfileAttributes");
|
|
1282
1286
|
|
|
1287
|
+
// packages/acp-bridge/src/sessionMedia.ts
|
|
1288
|
+
init_esbuild_shims();
|
|
1289
|
+
import { randomUUID } from "node:crypto";
|
|
1290
|
+
import { promises as fs } from "node:fs";
|
|
1291
|
+
import { tmpdir } from "node:os";
|
|
1292
|
+
import * as path from "node:path";
|
|
1293
|
+
var SESSION_MEDIA_MAX_ITEM_BYTES = 8 * 1024 * 1024;
|
|
1294
|
+
var SESSION_MEDIA_MAX_TOTAL_BYTES = 100 * 1024 * 1024;
|
|
1295
|
+
var SESSION_MEDIA_MAX_ITEMS = 256;
|
|
1296
|
+
var SESSION_MEDIA_UNAVAILABLE_TEXT = "[Attached media is no longer available]";
|
|
1297
|
+
var SessionMediaReferenceError = class extends Error {
|
|
1298
|
+
constructor(message, code) {
|
|
1299
|
+
super(message);
|
|
1300
|
+
this.code = code;
|
|
1301
|
+
this.name = "SessionMediaReferenceError";
|
|
1302
|
+
}
|
|
1303
|
+
static {
|
|
1304
|
+
__name(this, "SessionMediaReferenceError");
|
|
1305
|
+
}
|
|
1306
|
+
};
|
|
1307
|
+
function isSessionMediaReference(value) {
|
|
1308
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
1309
|
+
const record = value;
|
|
1310
|
+
return record["type"] === "image" && typeof record["mediaId"] === "string" && record["mediaId"].length > 0 && typeof record["mimeType"] === "string" && record["mimeType"].startsWith(`${record["type"]}/`) && typeof record["size"] === "number" && Number.isSafeInteger(record["size"]) && record["size"] > 0;
|
|
1311
|
+
}
|
|
1312
|
+
__name(isSessionMediaReference, "isSessionMediaReference");
|
|
1313
|
+
function withMediaDegradationMarker(blocks) {
|
|
1314
|
+
for (let i = blocks.length - 1; i >= 0; i--) {
|
|
1315
|
+
const block = blocks[i];
|
|
1316
|
+
if (block.type === "text") {
|
|
1317
|
+
if (block.text.endsWith(SESSION_MEDIA_UNAVAILABLE_TEXT)) {
|
|
1318
|
+
return [...blocks];
|
|
1319
|
+
}
|
|
1320
|
+
const next = [...blocks];
|
|
1321
|
+
next[i] = {
|
|
1322
|
+
type: "text",
|
|
1323
|
+
text: `${block.text}
|
|
1324
|
+
${SESSION_MEDIA_UNAVAILABLE_TEXT}`
|
|
1325
|
+
};
|
|
1326
|
+
return next;
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1329
|
+
return [
|
|
1330
|
+
...blocks,
|
|
1331
|
+
{ type: "text", text: SESSION_MEDIA_UNAVAILABLE_TEXT }
|
|
1332
|
+
];
|
|
1333
|
+
}
|
|
1334
|
+
__name(withMediaDegradationMarker, "withMediaDegradationMarker");
|
|
1335
|
+
var SessionMediaStore = class {
|
|
1336
|
+
static {
|
|
1337
|
+
__name(this, "SessionMediaStore");
|
|
1338
|
+
}
|
|
1339
|
+
records = /* @__PURE__ */ new Map();
|
|
1340
|
+
directoryPromise;
|
|
1341
|
+
totalBytes = 0;
|
|
1342
|
+
pendingItems = 0;
|
|
1343
|
+
closed = false;
|
|
1344
|
+
async put(data, mimeType) {
|
|
1345
|
+
if (this.closed) throw new Error("Session media store is closed");
|
|
1346
|
+
const type = "image";
|
|
1347
|
+
if (!mimeType.startsWith("image/")) {
|
|
1348
|
+
throw new TypeError("Session media must be image/*");
|
|
1349
|
+
}
|
|
1350
|
+
if (data.byteLength === 0 || data.byteLength > SESSION_MEDIA_MAX_ITEM_BYTES) {
|
|
1351
|
+
throw new RangeError(
|
|
1352
|
+
`Session media must be between 1 and ${SESSION_MEDIA_MAX_ITEM_BYTES} bytes`
|
|
1353
|
+
);
|
|
1354
|
+
}
|
|
1355
|
+
if (this.totalBytes + data.byteLength > SESSION_MEDIA_MAX_TOTAL_BYTES) {
|
|
1356
|
+
throw new RangeError(
|
|
1357
|
+
`Session media exceeds the ${SESSION_MEDIA_MAX_TOTAL_BYTES}-byte session limit`
|
|
1358
|
+
);
|
|
1359
|
+
}
|
|
1360
|
+
if (this.records.size + this.pendingItems >= SESSION_MEDIA_MAX_ITEMS) {
|
|
1361
|
+
throw new RangeError(
|
|
1362
|
+
`Session media exceeds the ${SESSION_MEDIA_MAX_ITEMS}-item session limit`
|
|
1363
|
+
);
|
|
1364
|
+
}
|
|
1365
|
+
const mediaId = randomUUID();
|
|
1366
|
+
let filePath;
|
|
1367
|
+
this.totalBytes += data.byteLength;
|
|
1368
|
+
this.pendingItems += 1;
|
|
1369
|
+
try {
|
|
1370
|
+
const directory = await this.directory();
|
|
1371
|
+
filePath = path.join(directory, mediaId);
|
|
1372
|
+
await fs.writeFile(filePath, data, { flag: "wx" });
|
|
1373
|
+
if (this.closed) {
|
|
1374
|
+
throw new Error("Session media store is closed");
|
|
1375
|
+
}
|
|
1376
|
+
const record = {
|
|
1377
|
+
type,
|
|
1378
|
+
mediaId,
|
|
1379
|
+
mimeType,
|
|
1380
|
+
size: data.byteLength,
|
|
1381
|
+
filePath
|
|
1382
|
+
};
|
|
1383
|
+
this.records.set(mediaId, record);
|
|
1384
|
+
return { type, mediaId, mimeType, size: data.byteLength };
|
|
1385
|
+
} catch (error) {
|
|
1386
|
+
if (filePath) await fs.rm(filePath, { force: true }).catch(() => {
|
|
1387
|
+
});
|
|
1388
|
+
if (!this.closed) this.totalBytes -= data.byteLength;
|
|
1389
|
+
throw error;
|
|
1390
|
+
} finally {
|
|
1391
|
+
if (!this.closed) this.pendingItems -= 1;
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
// Validate one block against the store. Blocks without a `mediaId` (inline
|
|
1395
|
+
// media, text) pass through untouched, matching `assertReferences`.
|
|
1396
|
+
assertReference(block) {
|
|
1397
|
+
if (!block || typeof block !== "object" || Array.isArray(block) || !("mediaId" in block)) {
|
|
1398
|
+
return;
|
|
1399
|
+
}
|
|
1400
|
+
if (!isSessionMediaReference(block)) {
|
|
1401
|
+
throw new SessionMediaReferenceError(
|
|
1402
|
+
"Invalid session media reference",
|
|
1403
|
+
"invalid_session_media_reference"
|
|
1404
|
+
);
|
|
1405
|
+
}
|
|
1406
|
+
this.assertStored(block);
|
|
1407
|
+
}
|
|
1408
|
+
assertReferences(content) {
|
|
1409
|
+
const seenMediaIds = /* @__PURE__ */ new Set();
|
|
1410
|
+
for (const block of content) {
|
|
1411
|
+
if (!block || typeof block !== "object" || Array.isArray(block) || !("mediaId" in block)) {
|
|
1412
|
+
continue;
|
|
1413
|
+
}
|
|
1414
|
+
if (!isSessionMediaReference(block)) {
|
|
1415
|
+
throw new SessionMediaReferenceError(
|
|
1416
|
+
"Invalid session media reference",
|
|
1417
|
+
"invalid_session_media_reference"
|
|
1418
|
+
);
|
|
1419
|
+
}
|
|
1420
|
+
if (seenMediaIds.has(block.mediaId)) {
|
|
1421
|
+
throw new SessionMediaReferenceError(
|
|
1422
|
+
`Session media referenced more than once: ${block.mediaId}`,
|
|
1423
|
+
"invalid_session_media_reference"
|
|
1424
|
+
);
|
|
1425
|
+
}
|
|
1426
|
+
seenMediaIds.add(block.mediaId);
|
|
1427
|
+
this.assertStored(block);
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
async resolveContent(content, memo) {
|
|
1431
|
+
const pendingByMediaId = memo ?? /* @__PURE__ */ new Map();
|
|
1432
|
+
return await Promise.all(
|
|
1433
|
+
content.map(async (block) => {
|
|
1434
|
+
if (!isSessionMediaReference(block)) return block;
|
|
1435
|
+
let pending = pendingByMediaId.get(block.mediaId);
|
|
1436
|
+
if (!pending) {
|
|
1437
|
+
const created = this.resolve(block);
|
|
1438
|
+
pendingByMediaId.set(block.mediaId, created);
|
|
1439
|
+
void created.catch(() => {
|
|
1440
|
+
if (pendingByMediaId.get(block.mediaId) === created) {
|
|
1441
|
+
pendingByMediaId.delete(block.mediaId);
|
|
1442
|
+
}
|
|
1443
|
+
});
|
|
1444
|
+
pending = created;
|
|
1445
|
+
}
|
|
1446
|
+
return await pending;
|
|
1447
|
+
})
|
|
1448
|
+
);
|
|
1449
|
+
}
|
|
1450
|
+
// Per-block variant of `resolveContent` for degrade paths: one unresolvable
|
|
1451
|
+
// reference drops only itself, keeping the sibling blocks a wholesale
|
|
1452
|
+
// fallback would discard. Non-media errors still propagate.
|
|
1453
|
+
async resolveContentDegrading(content, memo) {
|
|
1454
|
+
const retainedBlocks = [];
|
|
1455
|
+
const resolvedBlocks = [];
|
|
1456
|
+
let degraded = 0;
|
|
1457
|
+
for (const block of content) {
|
|
1458
|
+
if (!isSessionMediaReference(block)) {
|
|
1459
|
+
retainedBlocks.push(block);
|
|
1460
|
+
resolvedBlocks.push(block);
|
|
1461
|
+
continue;
|
|
1462
|
+
}
|
|
1463
|
+
try {
|
|
1464
|
+
const [resolved] = await this.resolveContent([block], memo);
|
|
1465
|
+
if (resolved) resolvedBlocks.push(resolved);
|
|
1466
|
+
retainedBlocks.push(block);
|
|
1467
|
+
} catch (error) {
|
|
1468
|
+
if (!(error instanceof SessionMediaReferenceError)) throw error;
|
|
1469
|
+
degraded += 1;
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1472
|
+
return { retainedBlocks, resolvedBlocks, degraded };
|
|
1473
|
+
}
|
|
1474
|
+
async read(mediaId) {
|
|
1475
|
+
const record = this.records.get(mediaId);
|
|
1476
|
+
if (!record) return void 0;
|
|
1477
|
+
try {
|
|
1478
|
+
return {
|
|
1479
|
+
data: await fs.readFile(record.filePath),
|
|
1480
|
+
mimeType: record.mimeType
|
|
1481
|
+
};
|
|
1482
|
+
} catch (error) {
|
|
1483
|
+
if (error.code === "ENOENT") {
|
|
1484
|
+
if (this.records.delete(mediaId)) this.totalBytes -= record.size;
|
|
1485
|
+
return void 0;
|
|
1486
|
+
}
|
|
1487
|
+
throw error;
|
|
1488
|
+
}
|
|
1489
|
+
}
|
|
1490
|
+
async remove(mediaId) {
|
|
1491
|
+
const record = this.records.get(mediaId);
|
|
1492
|
+
if (!record) return false;
|
|
1493
|
+
this.records.delete(mediaId);
|
|
1494
|
+
this.totalBytes -= record.size;
|
|
1495
|
+
await fs.rm(record.filePath, { force: true });
|
|
1496
|
+
return true;
|
|
1497
|
+
}
|
|
1498
|
+
get sizeBytes() {
|
|
1499
|
+
return this.totalBytes;
|
|
1500
|
+
}
|
|
1501
|
+
async close() {
|
|
1502
|
+
if (this.closed) return;
|
|
1503
|
+
this.closed = true;
|
|
1504
|
+
this.records.clear();
|
|
1505
|
+
this.totalBytes = 0;
|
|
1506
|
+
this.pendingItems = 0;
|
|
1507
|
+
if (!this.directoryPromise) return;
|
|
1508
|
+
const directory = await this.directoryPromise.catch(() => void 0);
|
|
1509
|
+
if (!directory) return;
|
|
1510
|
+
await fs.rm(directory, { recursive: true, force: true });
|
|
1511
|
+
}
|
|
1512
|
+
assertStored(reference) {
|
|
1513
|
+
const stored = this.records.get(reference.mediaId);
|
|
1514
|
+
if (!stored || stored.type !== reference.type || stored.mimeType !== reference.mimeType || stored.size !== reference.size) {
|
|
1515
|
+
throw new SessionMediaReferenceError(
|
|
1516
|
+
`Unknown or unavailable session media: ${reference.mediaId}`,
|
|
1517
|
+
"session_media_gone"
|
|
1518
|
+
);
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1521
|
+
async resolve(reference) {
|
|
1522
|
+
const media = await this.read(reference.mediaId);
|
|
1523
|
+
if (!media || media.mimeType !== reference.mimeType) {
|
|
1524
|
+
throw new SessionMediaReferenceError(
|
|
1525
|
+
`Unknown or unavailable session media: ${reference.mediaId}`,
|
|
1526
|
+
"session_media_gone"
|
|
1527
|
+
);
|
|
1528
|
+
}
|
|
1529
|
+
return {
|
|
1530
|
+
type: reference.type,
|
|
1531
|
+
data: media.data.toString("base64"),
|
|
1532
|
+
mimeType: media.mimeType
|
|
1533
|
+
};
|
|
1534
|
+
}
|
|
1535
|
+
async directory() {
|
|
1536
|
+
if (!this.directoryPromise) {
|
|
1537
|
+
const pending = fs.mkdtemp(path.join(tmpdir(), "qwen-session-media-"));
|
|
1538
|
+
this.directoryPromise = pending;
|
|
1539
|
+
void pending.catch(() => {
|
|
1540
|
+
if (this.directoryPromise === pending)
|
|
1541
|
+
this.directoryPromise = void 0;
|
|
1542
|
+
});
|
|
1543
|
+
}
|
|
1544
|
+
return await this.directoryPromise;
|
|
1545
|
+
}
|
|
1546
|
+
};
|
|
1547
|
+
|
|
1283
1548
|
// packages/acp-bridge/src/internal/stderrLine.ts
|
|
1284
1549
|
init_esbuild_shims();
|
|
1285
1550
|
function writeStderrLine(message) {
|
|
@@ -1290,9 +1555,9 @@ __name(writeStderrLine, "writeStderrLine");
|
|
|
1290
1555
|
|
|
1291
1556
|
// packages/acp-bridge/src/bridgeClient.ts
|
|
1292
1557
|
init_esbuild_shims();
|
|
1293
|
-
import { randomUUID } from "node:crypto";
|
|
1294
|
-
import { promises as
|
|
1295
|
-
import * as
|
|
1558
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
1559
|
+
import { promises as fs2 } from "node:fs";
|
|
1560
|
+
import * as path2 from "node:path";
|
|
1296
1561
|
|
|
1297
1562
|
// packages/acp-bridge/src/daemonEventTypes.ts
|
|
1298
1563
|
init_esbuild_shims();
|
|
@@ -2278,7 +2543,7 @@ function sliceLineRange(content, startLine, endLine) {
|
|
|
2278
2543
|
}
|
|
2279
2544
|
__name(sliceLineRange, "sliceLineRange");
|
|
2280
2545
|
var BridgeClient = class {
|
|
2281
|
-
constructor(resolveEntry, resolvePendingRestoreEvents, mediator, permissionTimeoutMs, maxPendingPerSession, fileSystem, onModelPromoted, onModePromoted, clientMcpSender, ownsSession = () => true, onTokenUsage, onCreateSubSession, onGenerationEvent, onWorkspaceGenerationEvent, onChannelDelivery, hasSessionSpawnInFlight = () => false, getLiveScreenContextCaptureHandler = () => void 0, getLiveTaskToolRequestHandler = () => void 0, getLiveSpeakToUserHandler = () => void 0, externalToolGuard, onActiveWork) {
|
|
2546
|
+
constructor(resolveEntry, resolvePendingRestoreEvents, mediator, permissionTimeoutMs, maxPendingPerSession, fileSystem, onModelPromoted, onModePromoted, clientMcpSender, ownsSession = () => true, onTokenUsage, onCreateSubSession, onGenerationEvent, onWorkspaceGenerationEvent, onChannelDelivery, hasSessionSpawnInFlight = () => false, getLiveScreenContextCaptureHandler = () => void 0, getLiveTaskToolRequestHandler = () => void 0, getLiveSpeakToUserHandler = () => void 0, externalToolGuard, onActiveWork, onSessionCatalogChanged) {
|
|
2282
2547
|
this.resolveEntry = resolveEntry;
|
|
2283
2548
|
this.resolvePendingRestoreEvents = resolvePendingRestoreEvents;
|
|
2284
2549
|
this.mediator = mediator;
|
|
@@ -2300,6 +2565,7 @@ var BridgeClient = class {
|
|
|
2300
2565
|
this.getLiveSpeakToUserHandler = getLiveSpeakToUserHandler;
|
|
2301
2566
|
this.externalToolGuard = externalToolGuard;
|
|
2302
2567
|
this.onActiveWork = onActiveWork;
|
|
2568
|
+
this.onSessionCatalogChanged = onSessionCatalogChanged;
|
|
2303
2569
|
}
|
|
2304
2570
|
static {
|
|
2305
2571
|
__name(this, "BridgeClient");
|
|
@@ -2318,7 +2584,7 @@ var BridgeClient = class {
|
|
|
2318
2584
|
options.map((o) => String(o.optionId ?? ""))
|
|
2319
2585
|
);
|
|
2320
2586
|
allowedOptionIds.delete("");
|
|
2321
|
-
const requestId =
|
|
2587
|
+
const requestId = randomUUID2();
|
|
2322
2588
|
if (allowedOptionIds.has(CANCEL_VOTE_SENTINEL)) {
|
|
2323
2589
|
throw new CancelSentinelCollisionError(requestId, CANCEL_VOTE_SENTINEL);
|
|
2324
2590
|
}
|
|
@@ -2564,8 +2830,8 @@ var BridgeClient = class {
|
|
|
2564
2830
|
* between tool batches to pull any messages the browser queued mid-turn. We splice the per-session
|
|
2565
2831
|
* queue, return them to the child as the response, and — when non-empty —
|
|
2566
2832
|
* publish a `mid_turn_message_injected` SSE frame so the browser can move
|
|
2567
|
-
* those messages out of its pending queue
|
|
2568
|
-
*
|
|
2833
|
+
* those messages out of its pending queue and render the immediate echo.
|
|
2834
|
+
* Unknown methods reject with ACP `methodNotFound` (-32601), matching
|
|
2569
2835
|
* the SDK's
|
|
2570
2836
|
* default for an unimplemented client surface; the child's drain caller
|
|
2571
2837
|
* treats that as "drain unsupported" and stops asking.
|
|
@@ -2599,9 +2865,12 @@ var BridgeClient = class {
|
|
|
2599
2865
|
throw RequestError.methodNotFound(method);
|
|
2600
2866
|
}
|
|
2601
2867
|
const sessionId = typeof params["sessionId"] === "string" ? params["sessionId"] : void 0;
|
|
2602
|
-
if (!sessionId) return { messages: [], hasQueuedPrompt: false };
|
|
2868
|
+
if (!sessionId) return { messages: [], items: [], hasQueuedPrompt: false };
|
|
2869
|
+
if (!this.ownsSession(sessionId)) {
|
|
2870
|
+
return { messages: [], items: [], hasQueuedPrompt: false };
|
|
2871
|
+
}
|
|
2603
2872
|
const entry = this.resolveEntry(sessionId);
|
|
2604
|
-
if (!entry) return { messages: [], hasQueuedPrompt: false };
|
|
2873
|
+
if (!entry) return { messages: [], items: [], hasQueuedPrompt: false };
|
|
2605
2874
|
const drained = entry.midTurnMessageQueue.splice(0);
|
|
2606
2875
|
if (drained.length > 0) {
|
|
2607
2876
|
for (const item of drained) {
|
|
@@ -2614,6 +2883,64 @@ var BridgeClient = class {
|
|
|
2614
2883
|
);
|
|
2615
2884
|
}
|
|
2616
2885
|
}
|
|
2886
|
+
const mediaMemo = /* @__PURE__ */ new Map();
|
|
2887
|
+
const serializedMediaIds = /* @__PURE__ */ new Set();
|
|
2888
|
+
const items = [];
|
|
2889
|
+
try {
|
|
2890
|
+
for (const item of drained) {
|
|
2891
|
+
let degraded = 0;
|
|
2892
|
+
const planned = (item.content ?? []).filter((block) => {
|
|
2893
|
+
if (!isSessionMediaReference(block)) return true;
|
|
2894
|
+
if (serializedMediaIds.has(block.mediaId)) {
|
|
2895
|
+
degraded += 1;
|
|
2896
|
+
return false;
|
|
2897
|
+
}
|
|
2898
|
+
serializedMediaIds.add(block.mediaId);
|
|
2899
|
+
return true;
|
|
2900
|
+
});
|
|
2901
|
+
let resolvedBlocks;
|
|
2902
|
+
let mediaReferences;
|
|
2903
|
+
try {
|
|
2904
|
+
resolvedBlocks = await entry.media.resolveContent(planned, mediaMemo);
|
|
2905
|
+
mediaReferences = planned.filter(isSessionMediaReference);
|
|
2906
|
+
} catch (error) {
|
|
2907
|
+
if (!(error instanceof SessionMediaReferenceError)) throw error;
|
|
2908
|
+
writeStderrLine(
|
|
2909
|
+
`[mid-turn] session=${JSON.stringify(entry.sessionId)} degraded media for message ${JSON.stringify(item.messageId)}: ${JSON.stringify(error instanceof Error ? error.message : String(error))}`
|
|
2910
|
+
);
|
|
2911
|
+
const perBlock = await entry.media.resolveContentDegrading(
|
|
2912
|
+
planned,
|
|
2913
|
+
mediaMemo
|
|
2914
|
+
);
|
|
2915
|
+
resolvedBlocks = perBlock.resolvedBlocks;
|
|
2916
|
+
mediaReferences = perBlock.retainedBlocks.filter(
|
|
2917
|
+
isSessionMediaReference
|
|
2918
|
+
);
|
|
2919
|
+
degraded += perBlock.degraded;
|
|
2920
|
+
}
|
|
2921
|
+
let content = [
|
|
2922
|
+
...item.text ? [{ type: "text", text: item.text }] : [],
|
|
2923
|
+
...resolvedBlocks
|
|
2924
|
+
];
|
|
2925
|
+
if (degraded > 0) content = withMediaDegradationMarker(content);
|
|
2926
|
+
items.push({
|
|
2927
|
+
messageId: item.messageId,
|
|
2928
|
+
displayText: item.text,
|
|
2929
|
+
content,
|
|
2930
|
+
...mediaReferences.length > 0 ? { mediaReferences } : {}
|
|
2931
|
+
});
|
|
2932
|
+
}
|
|
2933
|
+
} catch (error) {
|
|
2934
|
+
const requeued = new Set(drained.map((queued) => queued.messageId));
|
|
2935
|
+
const ring = entry.settledMidTurnMessageIds;
|
|
2936
|
+
const kept = ring.filter((id) => !requeued.has(id));
|
|
2937
|
+
ring.splice(0, ring.length, ...kept);
|
|
2938
|
+
entry.midTurnMessageQueue.unshift(...drained);
|
|
2939
|
+
writeStderrLine(
|
|
2940
|
+
`[mid-turn] session=${JSON.stringify(entry.sessionId)} drain failed, requeued ${drained.length} message(s): ${JSON.stringify(error instanceof Error ? error.message : String(error))}`
|
|
2941
|
+
);
|
|
2942
|
+
throw error;
|
|
2943
|
+
}
|
|
2617
2944
|
const echoed = drained.filter((item) => !item.queueOnly);
|
|
2618
2945
|
const messages = drained.map((item) => item.text);
|
|
2619
2946
|
const hasQueuedPrompt = entry.pendingPromptList.some(
|
|
@@ -2626,14 +2953,21 @@ var BridgeClient = class {
|
|
|
2626
2953
|
data: {
|
|
2627
2954
|
sessionId: entry.sessionId,
|
|
2628
2955
|
messages: echoed.map((item) => item.text),
|
|
2629
|
-
messageIds: echoed.map((item) => item.messageId)
|
|
2956
|
+
messageIds: echoed.map((item) => item.messageId),
|
|
2957
|
+
// Carry the structured `items` twin (content blocks per message) so
|
|
2958
|
+
// the browser-side echo renderer can show attached images alongside
|
|
2959
|
+
// the message text. Older consumers that don't read this field keep
|
|
2960
|
+
// working unchanged.
|
|
2961
|
+
items: echoed.map((item) => ({
|
|
2962
|
+
...item.content && item.content.length > 0 ? { content: item.content } : {}
|
|
2963
|
+
}))
|
|
2630
2964
|
}
|
|
2631
2965
|
});
|
|
2632
2966
|
writeStderrLine(
|
|
2633
2967
|
published ? `[mid-turn] session=${entry.sessionId} drained=${messages.length} echoed=${echoed.length} injected into running turn` : `[mid-turn] session=${entry.sessionId} drained=${messages.length} echoed=${echoed.length} echo frame dropped (bus closed); reconciliation required`
|
|
2634
2968
|
);
|
|
2635
2969
|
}
|
|
2636
|
-
return { messages, hasQueuedPrompt };
|
|
2970
|
+
return { messages, items, hasQueuedPrompt };
|
|
2637
2971
|
}
|
|
2638
2972
|
async handleExternalToolGuardPrepare(params) {
|
|
2639
2973
|
if (!this.externalToolGuard) {
|
|
@@ -3160,6 +3494,7 @@ var BridgeClient = class {
|
|
|
3160
3494
|
return;
|
|
3161
3495
|
const entry = this.resolveEntry(sessionId2);
|
|
3162
3496
|
if (!entry) return;
|
|
3497
|
+
this.onSessionCatalogChanged?.();
|
|
3163
3498
|
try {
|
|
3164
3499
|
entry.events.publish({
|
|
3165
3500
|
type: "session_metadata_updated",
|
|
@@ -3602,20 +3937,20 @@ var BridgeClient = class {
|
|
|
3602
3937
|
}
|
|
3603
3938
|
let realTarget = params.path;
|
|
3604
3939
|
try {
|
|
3605
|
-
realTarget = await
|
|
3940
|
+
realTarget = await fs2.realpath(params.path);
|
|
3606
3941
|
} catch (err) {
|
|
3607
3942
|
const code = err && typeof err === "object" && "code" in err ? err.code : void 0;
|
|
3608
3943
|
if (code !== "ENOENT") throw err;
|
|
3609
3944
|
try {
|
|
3610
|
-
const linkTarget = await
|
|
3611
|
-
realTarget =
|
|
3945
|
+
const linkTarget = await fs2.readlink(params.path);
|
|
3946
|
+
realTarget = path2.resolve(path2.dirname(params.path), linkTarget);
|
|
3612
3947
|
} catch {
|
|
3613
3948
|
}
|
|
3614
3949
|
}
|
|
3615
|
-
const tmp = `${realTarget}.${process.pid}.${Date.now()}.${
|
|
3950
|
+
const tmp = `${realTarget}.${process.pid}.${Date.now()}.${randomUUID2()}.tmp`;
|
|
3616
3951
|
let preserveMode;
|
|
3617
3952
|
try {
|
|
3618
|
-
const targetStat = await
|
|
3953
|
+
const targetStat = await fs2.stat(realTarget);
|
|
3619
3954
|
preserveMode = {
|
|
3620
3955
|
mode: targetStat.mode & 4095,
|
|
3621
3956
|
uid: targetStat.uid,
|
|
@@ -3626,20 +3961,20 @@ var BridgeClient = class {
|
|
|
3626
3961
|
if (code !== "ENOENT") throw err;
|
|
3627
3962
|
}
|
|
3628
3963
|
try {
|
|
3629
|
-
await
|
|
3964
|
+
await fs2.writeFile(tmp, params.content, {
|
|
3630
3965
|
encoding: "utf8",
|
|
3631
3966
|
flag: "wx",
|
|
3632
3967
|
mode: preserveMode?.mode ?? 384
|
|
3633
3968
|
});
|
|
3634
3969
|
if (preserveMode) {
|
|
3635
|
-
await
|
|
3970
|
+
await fs2.chmod(tmp, preserveMode.mode).catch(() => {
|
|
3636
3971
|
});
|
|
3637
|
-
await
|
|
3972
|
+
await fs2.chown(tmp, preserveMode.uid, preserveMode.gid).catch(() => {
|
|
3638
3973
|
});
|
|
3639
3974
|
}
|
|
3640
|
-
await
|
|
3975
|
+
await fs2.rename(tmp, realTarget);
|
|
3641
3976
|
} catch (err) {
|
|
3642
|
-
await
|
|
3977
|
+
await fs2.unlink(tmp).catch(() => {
|
|
3643
3978
|
});
|
|
3644
3979
|
throw err;
|
|
3645
3980
|
}
|
|
@@ -3669,7 +4004,7 @@ var BridgeClient = class {
|
|
|
3669
4004
|
);
|
|
3670
4005
|
}
|
|
3671
4006
|
const READ_FILE_SIZE_CAP = 100 * 1024 * 1024;
|
|
3672
|
-
const stats = await
|
|
4007
|
+
const stats = await fs2.stat(params.path);
|
|
3673
4008
|
if (!stats.isFile()) {
|
|
3674
4009
|
throw new Error(
|
|
3675
4010
|
`readTextFile: ${params.path} is not a regular file (reported as ${describeStatKind(stats)}). Pipe / device / proc-like inputs can produce unbounded data and aren't supported by the bridge fs proxy.`
|
|
@@ -3680,7 +4015,7 @@ var BridgeClient = class {
|
|
|
3680
4015
|
`readTextFile: ${params.path} is ${stats.size} bytes, exceeds the ${READ_FILE_SIZE_CAP}-byte daemon cap. Tail/grep externally and feed the relevant slice instead.`
|
|
3681
4016
|
);
|
|
3682
4017
|
}
|
|
3683
|
-
const content = await
|
|
4018
|
+
const content = await fs2.readFile(params.path, "utf8");
|
|
3684
4019
|
if (typeof params.line === "number" || typeof params.limit === "number") {
|
|
3685
4020
|
const startLine = params.line ?? 1;
|
|
3686
4021
|
const start = startLine > 0 ? startLine - 1 : 0;
|
|
@@ -3882,8 +4217,8 @@ var GenerationStreamQueue = class {
|
|
|
3882
4217
|
// packages/acp-bridge/src/sessionArtifacts.ts
|
|
3883
4218
|
init_esbuild_shims();
|
|
3884
4219
|
import { createHash } from "node:crypto";
|
|
3885
|
-
import { constants as fsConstants, promises as
|
|
3886
|
-
import
|
|
4220
|
+
import { constants as fsConstants, promises as fs3 } from "node:fs";
|
|
4221
|
+
import path3 from "node:path";
|
|
3887
4222
|
var SOURCE_RESERVATIONS = {
|
|
3888
4223
|
tool: 100,
|
|
3889
4224
|
client: 50,
|
|
@@ -4954,7 +5289,7 @@ var SessionArtifactStore = class {
|
|
|
4954
5289
|
}
|
|
4955
5290
|
getRealWorkspaceCwd() {
|
|
4956
5291
|
if (!this.realWorkspaceCwdPromise) {
|
|
4957
|
-
const promise =
|
|
5292
|
+
const promise = fs3.realpath(this.workspaceCwd).catch((error) => {
|
|
4958
5293
|
if (this.realWorkspaceCwdPromise === promise) {
|
|
4959
5294
|
this.realWorkspaceCwdPromise = void 0;
|
|
4960
5295
|
}
|
|
@@ -5074,8 +5409,15 @@ function mergeBatchArtifact(existing, next) {
|
|
|
5074
5409
|
delete merged.workspacePath;
|
|
5075
5410
|
return merged;
|
|
5076
5411
|
}
|
|
5412
|
+
const refreshDisplay = existing.storage === "workspace" && next.storage === "workspace" && shouldRefreshWorkspaceDisplay(next, existing);
|
|
5077
5413
|
return {
|
|
5078
5414
|
...existing,
|
|
5415
|
+
title: refreshDisplay ? next.title : existing.title,
|
|
5416
|
+
description: refreshDisplay ? next.description ?? existing.description : existing.description,
|
|
5417
|
+
toolName: refreshDisplay ? next.toolName : existing.toolName,
|
|
5418
|
+
source: refreshDisplay ? next.source : existing.source,
|
|
5419
|
+
hookEventName: refreshDisplay ? next.hookEventName : existing.hookEventName,
|
|
5420
|
+
toolCallId: refreshDisplay ? next.toolCallId : existing.toolCallId,
|
|
5079
5421
|
status: next.status,
|
|
5080
5422
|
sizeBytes: mergeSizeBytes(existing, next),
|
|
5081
5423
|
metadata: mergeMetadata(existing, next),
|
|
@@ -5122,6 +5464,13 @@ function mergeArtifact(existing, incoming) {
|
|
|
5122
5464
|
next.description = incoming.description;
|
|
5123
5465
|
delete next.workspacePath;
|
|
5124
5466
|
delete next.hideWorkspacePath;
|
|
5467
|
+
} else if (existing.storage === "workspace" && incoming.storage === "workspace" && shouldRefreshWorkspaceDisplay(incoming, existing)) {
|
|
5468
|
+
next.title = incoming.title;
|
|
5469
|
+
next.description = incoming.description ?? existing.description;
|
|
5470
|
+
next.toolCallId = incoming.toolCallId;
|
|
5471
|
+
next.toolName = incoming.toolName;
|
|
5472
|
+
next.source = incoming.source;
|
|
5473
|
+
next.hookEventName = incoming.hookEventName;
|
|
5125
5474
|
}
|
|
5126
5475
|
const changed = !publicArtifactsEqual(
|
|
5127
5476
|
toPublicArtifact(existing),
|
|
@@ -5137,6 +5486,16 @@ function shouldRecordEphemeralUnpin(existing, incoming) {
|
|
|
5137
5486
|
return incoming.retentionExplicit && incoming.retention === "ephemeral" && (existing.retention !== "ephemeral" || existing.persistedAt !== void 0 || existing.durableTombstoneRequired === true);
|
|
5138
5487
|
}
|
|
5139
5488
|
__name(shouldRecordEphemeralUnpin, "shouldRecordEphemeralUnpin");
|
|
5489
|
+
function shouldRefreshWorkspaceDisplay(incoming, existing) {
|
|
5490
|
+
if (incoming.toolName === "record_artifact" && incoming.source !== "hook") {
|
|
5491
|
+
return true;
|
|
5492
|
+
}
|
|
5493
|
+
if (!incoming.toolName) {
|
|
5494
|
+
return true;
|
|
5495
|
+
}
|
|
5496
|
+
return incoming.toolName === existing.toolName && incoming.source === existing.source && incoming.hookEventName === existing.hookEventName;
|
|
5497
|
+
}
|
|
5498
|
+
__name(shouldRefreshWorkspaceDisplay, "shouldRefreshWorkspaceDisplay");
|
|
5140
5499
|
function publicArtifactsEqual(a, b) {
|
|
5141
5500
|
return a.id === b.id && a.kind === b.kind && a.storage === b.storage && a.source === b.source && a.status === b.status && a.title === b.title && a.description === b.description && a.workspacePath === b.workspacePath && a.managedId === b.managedId && a.url === b.url && a.mimeType === b.mimeType && a.sizeBytes === b.sizeBytes && metadataEqual(a.metadata, b.metadata) && a.retention === b.retention && a.restoreState === b.restoreState && a.persistenceWarning === b.persistenceWarning && a.persistedAt === b.persistedAt && a.clientRetained === b.clientRetained && a.createdAt === b.createdAt && a.updatedAt === b.updatedAt && a.toolCallId === b.toolCallId && a.toolName === b.toolName && a.hookEventName === b.hookEventName && a.clientId === b.clientId;
|
|
5142
5501
|
}
|
|
@@ -5589,7 +5948,7 @@ function buildIdentityKey(input) {
|
|
|
5589
5948
|
}
|
|
5590
5949
|
__name(buildIdentityKey, "buildIdentityKey");
|
|
5591
5950
|
function managedIdForWorkspacePath(workspaceCwd, workspacePath) {
|
|
5592
|
-
return createHash("sha1").update(
|
|
5951
|
+
return createHash("sha1").update(path3.resolve(workspaceCwd, workspacePath)).digest("hex").slice(0, 16);
|
|
5593
5952
|
}
|
|
5594
5953
|
__name(managedIdForWorkspacePath, "managedIdForWorkspacePath");
|
|
5595
5954
|
function normalizeString(value, field, maxLength, required) {
|
|
@@ -5636,7 +5995,7 @@ __name(normalizeString, "normalizeString");
|
|
|
5636
5995
|
function normalizeManagedId(value) {
|
|
5637
5996
|
const managedId = normalizeString(value, "managedId", 200, false);
|
|
5638
5997
|
if (!managedId) return void 0;
|
|
5639
|
-
if (managedId.includes("/") || managedId.includes("\\") || managedId.includes("..") ||
|
|
5998
|
+
if (managedId.includes("/") || managedId.includes("\\") || managedId.includes("..") || path3.isAbsolute(managedId) || path3.win32.isAbsolute(managedId)) {
|
|
5640
5999
|
throw new SessionArtifactValidationError(
|
|
5641
6000
|
"managedId must be an opaque managed resource id",
|
|
5642
6001
|
"managedId"
|
|
@@ -5670,21 +6029,21 @@ function hasUnsafeDisplayPayload(value) {
|
|
|
5670
6029
|
__name(hasUnsafeDisplayPayload, "hasUnsafeDisplayPayload");
|
|
5671
6030
|
function normalizeWorkspacePath(raw, workspaceCwd) {
|
|
5672
6031
|
const trimmed = normalizeString(raw, "workspacePath", 500, true);
|
|
5673
|
-
if (
|
|
6032
|
+
if (path3.isAbsolute(trimmed)) {
|
|
5674
6033
|
throw new SessionArtifactValidationError(
|
|
5675
6034
|
"workspacePath must be relative to the workspace",
|
|
5676
6035
|
"workspacePath"
|
|
5677
6036
|
);
|
|
5678
6037
|
}
|
|
5679
|
-
const absolute =
|
|
5680
|
-
const relative =
|
|
6038
|
+
const absolute = path3.resolve(workspaceCwd, trimmed);
|
|
6039
|
+
const relative = path3.relative(workspaceCwd, absolute);
|
|
5681
6040
|
if (!relative || isOutsidePath(relative)) {
|
|
5682
6041
|
throw new SessionArtifactValidationError(
|
|
5683
6042
|
"workspacePath must stay inside the workspace",
|
|
5684
6043
|
"workspacePath"
|
|
5685
6044
|
);
|
|
5686
6045
|
}
|
|
5687
|
-
return relative.split(
|
|
6046
|
+
return relative.split(path3.sep).join("/");
|
|
5688
6047
|
}
|
|
5689
6048
|
__name(normalizeWorkspacePath, "normalizeWorkspacePath");
|
|
5690
6049
|
function normalizeArtifactUrl(raw, allowFile) {
|
|
@@ -5885,7 +6244,7 @@ __name(normalizeSizeBytes, "normalizeSizeBytes");
|
|
|
5885
6244
|
function inferKind(input) {
|
|
5886
6245
|
if (input.storage === "published") return "html";
|
|
5887
6246
|
if (input.url) return "link";
|
|
5888
|
-
const ext = input.workspacePath ?
|
|
6247
|
+
const ext = input.workspacePath ? path3.extname(input.workspacePath).toLowerCase() : "";
|
|
5889
6248
|
if (ext === ".html" || ext === ".htm") return "html";
|
|
5890
6249
|
if ([".png", ".jpg", ".jpeg", ".gif", ".webp", ".svg"].includes(ext)) {
|
|
5891
6250
|
return "image";
|
|
@@ -5899,15 +6258,15 @@ function inferKind(input) {
|
|
|
5899
6258
|
__name(inferKind, "inferKind");
|
|
5900
6259
|
async function getWorkspaceStatus(workspacePath, realWorkspaceCwd, expected, options = { hashContent: true }) {
|
|
5901
6260
|
const realWorkspace = await realWorkspaceCwd;
|
|
5902
|
-
const absolutePath =
|
|
6261
|
+
const absolutePath = path3.resolve(realWorkspace, workspacePath);
|
|
5903
6262
|
try {
|
|
5904
|
-
const realPath = await
|
|
5905
|
-
const relative =
|
|
6263
|
+
const realPath = await fs3.realpath(absolutePath);
|
|
6264
|
+
const relative = path3.relative(realWorkspace, realPath);
|
|
5906
6265
|
if (!relative || isOutsidePath(relative)) {
|
|
5907
6266
|
return { status: "missing", escaped: true };
|
|
5908
6267
|
}
|
|
5909
|
-
const preOpenStat = await
|
|
5910
|
-
const handle = await
|
|
6268
|
+
const preOpenStat = await fs3.lstat(realPath);
|
|
6269
|
+
const handle = await fs3.open(
|
|
5911
6270
|
realPath,
|
|
5912
6271
|
fsConstants.O_RDONLY | fsConstants.O_NOFOLLOW
|
|
5913
6272
|
);
|
|
@@ -6021,14 +6380,14 @@ function isWorkspaceContentChanged(artifact, status) {
|
|
|
6021
6380
|
__name(isWorkspaceContentChanged, "isWorkspaceContentChanged");
|
|
6022
6381
|
async function danglingSymlinkEscapesWorkspace(absolutePath, realWorkspace) {
|
|
6023
6382
|
try {
|
|
6024
|
-
const stat = await
|
|
6383
|
+
const stat = await fs3.lstat(absolutePath);
|
|
6025
6384
|
if (!stat.isSymbolicLink()) {
|
|
6026
6385
|
return false;
|
|
6027
6386
|
}
|
|
6028
|
-
const target = await
|
|
6029
|
-
const parent = await
|
|
6030
|
-
const targetPath =
|
|
6031
|
-
return isOutsidePath(
|
|
6387
|
+
const target = await fs3.readlink(absolutePath);
|
|
6388
|
+
const parent = await fs3.realpath(path3.dirname(absolutePath));
|
|
6389
|
+
const targetPath = path3.resolve(parent, target);
|
|
6390
|
+
return isOutsidePath(path3.relative(realWorkspace, targetPath));
|
|
6032
6391
|
} catch (error) {
|
|
6033
6392
|
if (isNotFoundError(error)) {
|
|
6034
6393
|
return false;
|
|
@@ -6059,7 +6418,7 @@ function isNoFollowSymlinkError(error) {
|
|
|
6059
6418
|
}
|
|
6060
6419
|
__name(isNoFollowSymlinkError, "isNoFollowSymlinkError");
|
|
6061
6420
|
function isOutsidePath(relative) {
|
|
6062
|
-
return relative === ".." || relative.startsWith(`..${
|
|
6421
|
+
return relative === ".." || relative.startsWith(`..${path3.sep}`) || path3.isAbsolute(relative);
|
|
6063
6422
|
}
|
|
6064
6423
|
__name(isOutsidePath, "isOutsidePath");
|
|
6065
6424
|
|
|
@@ -6866,6 +7225,57 @@ function broadcastTurnError(entry, sessionId, err, promptId, originatorClientId,
|
|
|
6866
7225
|
}
|
|
6867
7226
|
}
|
|
6868
7227
|
__name(broadcastTurnError, "broadcastTurnError");
|
|
7228
|
+
var TERMINAL_TURN_STATUS_OVERLAY_LIMIT = 64;
|
|
7229
|
+
function truncateTurnText(text) {
|
|
7230
|
+
const truncated = text.length > TURN_RESULT_TEXT_MAX_CHARS;
|
|
7231
|
+
return {
|
|
7232
|
+
text: truncated ? text.slice(0, TURN_RESULT_TEXT_MAX_CHARS) : text,
|
|
7233
|
+
truncated
|
|
7234
|
+
};
|
|
7235
|
+
}
|
|
7236
|
+
__name(truncateTurnText, "truncateTurnText");
|
|
7237
|
+
function rememberTerminalTurnStatus(entry, pending, terminal) {
|
|
7238
|
+
const promptText = truncateTurnText(pending.text);
|
|
7239
|
+
const shared = {
|
|
7240
|
+
sessionId: entry.sessionId,
|
|
7241
|
+
promptId: pending.promptId,
|
|
7242
|
+
promptText: promptText.text,
|
|
7243
|
+
...promptText.truncated ? { promptTextTruncated: true } : {},
|
|
7244
|
+
queuedAt: pending.queuedAt,
|
|
7245
|
+
...pending.startedAt !== void 0 ? { startedAt: pending.startedAt } : {},
|
|
7246
|
+
endedAt: Date.now(),
|
|
7247
|
+
...pending.originatorClientId !== void 0 ? { originatorClientId: pending.originatorClientId } : {}
|
|
7248
|
+
};
|
|
7249
|
+
const status = terminal.kind === "complete" ? {
|
|
7250
|
+
...shared,
|
|
7251
|
+
state: terminal.result.stopReason === "cancelled" ? "cancelled" : "completed",
|
|
7252
|
+
...terminal.result.stopReason !== void 0 ? { stopReason: terminal.result.stopReason } : {}
|
|
7253
|
+
} : terminal.kind === "cancelled" ? { ...shared, state: "cancelled", stopReason: "cancelled" } : {
|
|
7254
|
+
...shared,
|
|
7255
|
+
state: "error",
|
|
7256
|
+
error: normalizeTurnResultError(terminal.err)
|
|
7257
|
+
};
|
|
7258
|
+
entry.terminalTurnStatuses.set(pending.promptId, status);
|
|
7259
|
+
entry.enrichedTerminalPromptIds.delete(pending.promptId);
|
|
7260
|
+
while (entry.terminalTurnStatuses.size > TERMINAL_TURN_STATUS_OVERLAY_LIMIT) {
|
|
7261
|
+
const oldest2 = entry.terminalTurnStatuses.keys().next().value;
|
|
7262
|
+
if (oldest2 === void 0) break;
|
|
7263
|
+
entry.terminalTurnStatuses.delete(oldest2);
|
|
7264
|
+
entry.enrichedTerminalPromptIds.delete(oldest2);
|
|
7265
|
+
}
|
|
7266
|
+
}
|
|
7267
|
+
__name(rememberTerminalTurnStatus, "rememberTerminalTurnStatus");
|
|
7268
|
+
function rememberEnrichedTerminalTurnStatus(entry, promptId, status) {
|
|
7269
|
+
entry.terminalTurnStatuses.set(promptId, status);
|
|
7270
|
+
entry.enrichedTerminalPromptIds.add(promptId);
|
|
7271
|
+
while (entry.terminalTurnStatuses.size > TERMINAL_TURN_STATUS_OVERLAY_LIMIT) {
|
|
7272
|
+
const oldest2 = entry.terminalTurnStatuses.keys().next().value;
|
|
7273
|
+
if (oldest2 === void 0) break;
|
|
7274
|
+
entry.terminalTurnStatuses.delete(oldest2);
|
|
7275
|
+
entry.enrichedTerminalPromptIds.delete(oldest2);
|
|
7276
|
+
}
|
|
7277
|
+
}
|
|
7278
|
+
__name(rememberEnrichedTerminalTurnStatus, "rememberEnrichedTerminalTurnStatus");
|
|
6869
7279
|
function publishPromptTerminal(entry, pendingEntry, terminal) {
|
|
6870
7280
|
if (pendingEntry.terminalPublished) {
|
|
6871
7281
|
writeServeDebugLine(
|
|
@@ -6874,6 +7284,7 @@ function publishPromptTerminal(entry, pendingEntry, terminal) {
|
|
|
6874
7284
|
return;
|
|
6875
7285
|
}
|
|
6876
7286
|
pendingEntry.terminalPublished = true;
|
|
7287
|
+
rememberTerminalTurnStatus(entry, pendingEntry, terminal);
|
|
6877
7288
|
const originatorClientId = pendingEntry.originatorClientId;
|
|
6878
7289
|
const mutateTurnState = pendingEntry.state === "running";
|
|
6879
7290
|
if (!mutateTurnState && entry.turnErrorEvent) {
|
|
@@ -6941,16 +7352,109 @@ function extractPromptText(prompt) {
|
|
|
6941
7352
|
if (!Array.isArray(prompt)) return "";
|
|
6942
7353
|
let hasImage = false;
|
|
6943
7354
|
for (const block of prompt) {
|
|
6944
|
-
|
|
7355
|
+
const record = block;
|
|
7356
|
+
if (record["type"] === "image") {
|
|
6945
7357
|
hasImage = true;
|
|
6946
7358
|
}
|
|
6947
|
-
if (
|
|
6948
|
-
return
|
|
7359
|
+
if (record["type"] === "text" && typeof record["text"] === "string" && record["text"].length > 0) {
|
|
7360
|
+
return record["text"];
|
|
6949
7361
|
}
|
|
6950
7362
|
}
|
|
6951
7363
|
return hasImage ? "[image]" : "";
|
|
6952
7364
|
}
|
|
6953
7365
|
__name(extractPromptText, "extractPromptText");
|
|
7366
|
+
function liveTurnStatus(sessionId, pending) {
|
|
7367
|
+
const promptText = truncateTurnText(pending.text);
|
|
7368
|
+
return {
|
|
7369
|
+
sessionId,
|
|
7370
|
+
state: pending.state === "running" ? "running" : "queued",
|
|
7371
|
+
promptId: pending.promptId,
|
|
7372
|
+
promptText: promptText.text,
|
|
7373
|
+
...promptText.truncated ? { promptTextTruncated: true } : {},
|
|
7374
|
+
queuedAt: pending.queuedAt,
|
|
7375
|
+
...pending.startedAt !== void 0 ? { startedAt: pending.startedAt } : {},
|
|
7376
|
+
...pending.originatorClientId !== void 0 ? { originatorClientId: pending.originatorClientId } : {}
|
|
7377
|
+
};
|
|
7378
|
+
}
|
|
7379
|
+
__name(liveTurnStatus, "liveTurnStatus");
|
|
7380
|
+
function findLiveTurnStatus(entry, promptId) {
|
|
7381
|
+
const live = entry.pendingPromptList.filter(
|
|
7382
|
+
(pending) => !pending.terminalPublished && (!pending.removed || pending.state === "running")
|
|
7383
|
+
);
|
|
7384
|
+
if (promptId !== void 0) {
|
|
7385
|
+
const match = live.find((pending) => pending.promptId === promptId);
|
|
7386
|
+
return match ? liveTurnStatus(entry.sessionId, match) : void 0;
|
|
7387
|
+
}
|
|
7388
|
+
const running = live.find((pending) => pending.state === "running");
|
|
7389
|
+
if (running) return liveTurnStatus(entry.sessionId, running);
|
|
7390
|
+
const queued = live.find((pending) => pending.state === "queued");
|
|
7391
|
+
return queued ? liveTurnStatus(entry.sessionId, queued) : void 0;
|
|
7392
|
+
}
|
|
7393
|
+
__name(findLiveTurnStatus, "findLiveTurnStatus");
|
|
7394
|
+
function settledTurnStatus(sessionId, record) {
|
|
7395
|
+
return {
|
|
7396
|
+
sessionId,
|
|
7397
|
+
state: record.state,
|
|
7398
|
+
promptId: record.promptId,
|
|
7399
|
+
...record.stopReason !== void 0 ? { stopReason: record.stopReason } : {},
|
|
7400
|
+
...record.error !== void 0 ? { error: record.error } : {},
|
|
7401
|
+
...record.startedAt !== void 0 ? { startedAt: record.startedAt } : {},
|
|
7402
|
+
endedAt: record.endedAt,
|
|
7403
|
+
...record.promptText !== void 0 ? { promptText: record.promptText } : {},
|
|
7404
|
+
...record.promptTextTruncated !== void 0 ? { promptTextTruncated: record.promptTextTruncated } : {},
|
|
7405
|
+
...record.resultText !== void 0 ? { resultText: record.resultText } : {},
|
|
7406
|
+
...record.resultTruncated !== void 0 ? { resultTruncated: record.resultTruncated } : {},
|
|
7407
|
+
...record.resultTruncated === true ? { resultCode: record.resultCode ?? TURN_RESULT_CODE_TEXT_TRUNCATED } : {},
|
|
7408
|
+
...record.originatorClientId !== void 0 ? { originatorClientId: record.originatorClientId } : {}
|
|
7409
|
+
};
|
|
7410
|
+
}
|
|
7411
|
+
__name(settledTurnStatus, "settledTurnStatus");
|
|
7412
|
+
function enrichTerminalTurnStatus(terminal, persisted) {
|
|
7413
|
+
return {
|
|
7414
|
+
...terminal,
|
|
7415
|
+
// The bridge's display projection is trusted; the child-recorded text
|
|
7416
|
+
// only backfills when the terminal has none, so hidden channel context
|
|
7417
|
+
// the child derived from raw blocks never replaces it.
|
|
7418
|
+
...terminal.promptText === void 0 && persisted.promptText !== void 0 ? { promptText: persisted.promptText } : {},
|
|
7419
|
+
...terminal.promptTextTruncated === void 0 && persisted.promptTextTruncated !== void 0 ? { promptTextTruncated: persisted.promptTextTruncated } : {},
|
|
7420
|
+
...persisted.resultText !== void 0 ? { resultText: persisted.resultText } : {},
|
|
7421
|
+
...persisted.resultTruncated !== void 0 ? { resultTruncated: persisted.resultTruncated } : {},
|
|
7422
|
+
...persisted.resultCode !== void 0 ? { resultCode: persisted.resultCode } : {},
|
|
7423
|
+
...terminal.originatorClientId === void 0 && persisted.originatorClientId !== void 0 ? { originatorClientId: persisted.originatorClientId } : {}
|
|
7424
|
+
};
|
|
7425
|
+
}
|
|
7426
|
+
__name(enrichTerminalTurnStatus, "enrichTerminalTurnStatus");
|
|
7427
|
+
function mergeTerminalWithPersisted(terminal, persisted) {
|
|
7428
|
+
if (terminal.state === "error" && persisted.state !== "error") {
|
|
7429
|
+
return {
|
|
7430
|
+
...persisted,
|
|
7431
|
+
...terminal.promptText !== void 0 ? { promptText: terminal.promptText } : {},
|
|
7432
|
+
...terminal.promptTextTruncated !== void 0 ? { promptTextTruncated: terminal.promptTextTruncated } : {}
|
|
7433
|
+
};
|
|
7434
|
+
}
|
|
7435
|
+
return enrichTerminalTurnStatus(terminal, persisted);
|
|
7436
|
+
}
|
|
7437
|
+
__name(mergeTerminalWithPersisted, "mergeTerminalWithPersisted");
|
|
7438
|
+
function latestTerminalTurnStatus(entry) {
|
|
7439
|
+
let latest;
|
|
7440
|
+
for (const status of entry.terminalTurnStatuses.values()) {
|
|
7441
|
+
if ((status.endedAt ?? 0) >= (latest?.endedAt ?? 0)) latest = status;
|
|
7442
|
+
}
|
|
7443
|
+
return latest;
|
|
7444
|
+
}
|
|
7445
|
+
__name(latestTerminalTurnStatus, "latestTerminalTurnStatus");
|
|
7446
|
+
function extractMediaBlocks(prompt) {
|
|
7447
|
+
if (!Array.isArray(prompt)) return void 0;
|
|
7448
|
+
const media = [];
|
|
7449
|
+
for (const block of prompt) {
|
|
7450
|
+
if (!block || typeof block !== "object") continue;
|
|
7451
|
+
if (block.type === "image" || block.type === "audio") {
|
|
7452
|
+
media.push(block);
|
|
7453
|
+
}
|
|
7454
|
+
}
|
|
7455
|
+
return media.length > 0 ? media : void 0;
|
|
7456
|
+
}
|
|
7457
|
+
__name(extractMediaBlocks, "extractMediaBlocks");
|
|
6954
7458
|
var DEFAULT_INIT_TIMEOUT_MS = 1e4;
|
|
6955
7459
|
var PERSIST_TIMEOUT_MS = 5e3;
|
|
6956
7460
|
var MAX_PARENT_PERSIST_ATTEMPTS = 3;
|
|
@@ -6968,6 +7472,15 @@ var MAX_EMPTY_TRANSCRIPT_PAGES = 20;
|
|
|
6968
7472
|
var SHELL_COMMAND_TIMEOUT_MS = 12e4;
|
|
6969
7473
|
var MAX_SHELL_OUTPUT_FOR_HISTORY = 1e4;
|
|
6970
7474
|
var MAX_MID_TURN_QUEUE_DEPTH = 20;
|
|
7475
|
+
var inlineMediaBlockBytes = /* @__PURE__ */ __name((blocks) => {
|
|
7476
|
+
let total = 0;
|
|
7477
|
+
for (const block of blocks) {
|
|
7478
|
+
if (block.type === "image" && "data" in block) {
|
|
7479
|
+
total += block.data.length;
|
|
7480
|
+
}
|
|
7481
|
+
}
|
|
7482
|
+
return total;
|
|
7483
|
+
}, "inlineMediaBlockBytes");
|
|
6971
7484
|
var DEFAULT_MAX_SESSIONS = 32;
|
|
6972
7485
|
var DEFAULT_MAX_PENDING_PROMPTS_PER_SESSION = 5;
|
|
6973
7486
|
var CHAT_RECORD_UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
@@ -6976,6 +7489,8 @@ var DEFAULT_PERMISSION_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
|
6976
7489
|
var DEFAULT_MAX_PENDING_PER_SESSION = 64;
|
|
6977
7490
|
var DEFAULT_SESSION_REAP_INTERVAL_MS = 6e4;
|
|
6978
7491
|
var DEFAULT_SESSION_IDLE_TIMEOUT_MS = 30 * 6e4;
|
|
7492
|
+
var MAX_RETAINED_SESSION_MEDIA_BYTES = 512 * 1024 * 1024;
|
|
7493
|
+
var RETAINED_SESSION_MEDIA_TTL_MS = 3 * 60 * 6e4;
|
|
6979
7494
|
function createAcpSessionBridge(opts) {
|
|
6980
7495
|
let liveScreenContextCaptureHandler;
|
|
6981
7496
|
let liveTaskToolRequestHandler;
|
|
@@ -7034,7 +7549,17 @@ function createAcpSessionBridge(opts) {
|
|
|
7034
7549
|
);
|
|
7035
7550
|
}
|
|
7036
7551
|
}, "releaseFreshSessionReservation");
|
|
7552
|
+
const sessionCatalogGeneration = randomUUID3();
|
|
7553
|
+
let sessionCatalogRevision = 0;
|
|
7554
|
+
const getSessionCatalogVersion = /* @__PURE__ */ __name(() => ({
|
|
7555
|
+
generation: sessionCatalogGeneration,
|
|
7556
|
+
revision: sessionCatalogRevision
|
|
7557
|
+
}), "getSessionCatalogVersion");
|
|
7558
|
+
const markSessionCatalogChanged = /* @__PURE__ */ __name(() => {
|
|
7559
|
+
sessionCatalogRevision += 1;
|
|
7560
|
+
}, "markSessionCatalogChanged");
|
|
7037
7561
|
const emitSessionLifecycle = /* @__PURE__ */ __name((event) => {
|
|
7562
|
+
markSessionCatalogChanged();
|
|
7038
7563
|
try {
|
|
7039
7564
|
opts.sessionLifecycle?.(event);
|
|
7040
7565
|
} catch (err) {
|
|
@@ -7104,7 +7629,7 @@ function createAcpSessionBridge(opts) {
|
|
|
7104
7629
|
} else {
|
|
7105
7630
|
maxPendingPromptsPerSession = maxPendingPromptsRaw;
|
|
7106
7631
|
}
|
|
7107
|
-
if (!
|
|
7632
|
+
if (!path4.isAbsolute(opts.boundWorkspace)) {
|
|
7108
7633
|
throw new TypeError(
|
|
7109
7634
|
`Invalid boundWorkspace: "${opts.boundWorkspace}". Must be an absolute path.`
|
|
7110
7635
|
);
|
|
@@ -7127,6 +7652,7 @@ function createAcpSessionBridge(opts) {
|
|
|
7127
7652
|
DEFAULT_SESSION_IDLE_TIMEOUT_MS
|
|
7128
7653
|
);
|
|
7129
7654
|
let sessionReaper;
|
|
7655
|
+
let mediaSweeper;
|
|
7130
7656
|
let lastActivityTimestamp = null;
|
|
7131
7657
|
let activePromptCounter = 0;
|
|
7132
7658
|
function touchActivity() {
|
|
@@ -7443,9 +7969,32 @@ function createAcpSessionBridge(opts) {
|
|
|
7443
7969
|
}
|
|
7444
7970
|
}
|
|
7445
7971
|
__name(withWorkspaceControl, "withWorkspaceControl");
|
|
7972
|
+
function sweepRetainedMedia() {
|
|
7973
|
+
const now = Date.now();
|
|
7974
|
+
for (const [id] of retainedMedia) {
|
|
7975
|
+
if (byId.has(id) || inFlightRestores.has(id)) continue;
|
|
7976
|
+
const detachedAt = retainedMediaDetachedAt.get(id);
|
|
7977
|
+
if (detachedAt === void 0 || now - detachedAt < RETAINED_SESSION_MEDIA_TTL_MS) {
|
|
7978
|
+
continue;
|
|
7979
|
+
}
|
|
7980
|
+
void releaseSessionMedia(id).catch((error) => {
|
|
7981
|
+
writeStderrLine(
|
|
7982
|
+
`qwen serve: failed to release retained media for ${JSON.stringify(id)}: ${error instanceof Error ? error.message : String(error)}`
|
|
7983
|
+
);
|
|
7984
|
+
});
|
|
7985
|
+
}
|
|
7986
|
+
}
|
|
7987
|
+
__name(sweepRetainedMedia, "sweepRetainedMedia");
|
|
7446
7988
|
function startSessionReaper() {
|
|
7447
|
-
if (sessionReapIntervalMs <= 0
|
|
7448
|
-
writeStderrLine(
|
|
7989
|
+
if (sessionReapIntervalMs <= 0) {
|
|
7990
|
+
writeStderrLine(
|
|
7991
|
+
`qwen serve: session reaper disabled; retained media sweep runs every ${DEFAULT_SESSION_REAP_INTERVAL_MS}ms`
|
|
7992
|
+
);
|
|
7993
|
+
mediaSweeper = setInterval(() => {
|
|
7994
|
+
if (shuttingDown) return;
|
|
7995
|
+
sweepRetainedMedia();
|
|
7996
|
+
}, DEFAULT_SESSION_REAP_INTERVAL_MS);
|
|
7997
|
+
mediaSweeper.unref();
|
|
7449
7998
|
return;
|
|
7450
7999
|
}
|
|
7451
8000
|
writeStderrLine(
|
|
@@ -7455,6 +8004,7 @@ function createAcpSessionBridge(opts) {
|
|
|
7455
8004
|
if (shuttingDown) return;
|
|
7456
8005
|
const now = Date.now();
|
|
7457
8006
|
for (const [id, entry] of byId) {
|
|
8007
|
+
if (sessionIdleTimeoutMs <= 0) break;
|
|
7458
8008
|
if (!entryIsAutoCloseCandidate(entry)) continue;
|
|
7459
8009
|
const lastActive = entry.sessionLastSeenAt ?? Date.parse(entry.createdAt);
|
|
7460
8010
|
const idle = now - lastActive;
|
|
@@ -7467,6 +8017,7 @@ function createAcpSessionBridge(opts) {
|
|
|
7467
8017
|
closeReason: "idle_timeout"
|
|
7468
8018
|
});
|
|
7469
8019
|
}
|
|
8020
|
+
sweepRetainedMedia();
|
|
7470
8021
|
}, sessionReapIntervalMs);
|
|
7471
8022
|
sessionReaper.unref();
|
|
7472
8023
|
}
|
|
@@ -7476,11 +8027,29 @@ function createAcpSessionBridge(opts) {
|
|
|
7476
8027
|
clearInterval(sessionReaper);
|
|
7477
8028
|
sessionReaper = void 0;
|
|
7478
8029
|
}
|
|
8030
|
+
if (mediaSweeper !== void 0) {
|
|
8031
|
+
clearInterval(mediaSweeper);
|
|
8032
|
+
mediaSweeper = void 0;
|
|
8033
|
+
}
|
|
7479
8034
|
}
|
|
7480
8035
|
__name(stopSessionReaper, "stopSessionReaper");
|
|
7481
8036
|
const aliveChannels = /* @__PURE__ */ new Set();
|
|
7482
8037
|
let inFlightChannelSpawn;
|
|
7483
8038
|
const byId = /* @__PURE__ */ new Map();
|
|
8039
|
+
const retainedMedia = /* @__PURE__ */ new Map();
|
|
8040
|
+
const retainedMediaDetachedAt = /* @__PURE__ */ new Map();
|
|
8041
|
+
let mediaPutQueue = Promise.resolve();
|
|
8042
|
+
const retainSessionMedia = /* @__PURE__ */ __name((sessionId, store = retainedMedia.get(sessionId) ?? new SessionMediaStore()) => {
|
|
8043
|
+
retainedMedia.set(sessionId, store);
|
|
8044
|
+
return store;
|
|
8045
|
+
}, "retainSessionMedia");
|
|
8046
|
+
const releaseSessionMedia = /* @__PURE__ */ __name(async (sessionId) => {
|
|
8047
|
+
const store = retainedMedia.get(sessionId);
|
|
8048
|
+
if (!store) return;
|
|
8049
|
+
retainedMedia.delete(sessionId);
|
|
8050
|
+
retainedMediaDetachedAt.delete(sessionId);
|
|
8051
|
+
await store.close();
|
|
8052
|
+
}, "releaseSessionMedia");
|
|
7484
8053
|
const forwardRunningPromptCancel = /* @__PURE__ */ __name(async (entry, pending, notification) => {
|
|
7485
8054
|
if (pending.cancelForwardInitial) {
|
|
7486
8055
|
return pending.cancelForwardInitial;
|
|
@@ -7620,7 +8189,7 @@ function createAcpSessionBridge(opts) {
|
|
|
7620
8189
|
return limits;
|
|
7621
8190
|
}, "journalSessionLimits");
|
|
7622
8191
|
const unregisterJournalGrowthSessionLimits = journalGrowthPolicy !== void 0 && opts.registerJournalGrowthSessionLimits !== void 0 ? opts.registerJournalGrowthSessionLimits(journalSessionLimits) : void 0;
|
|
7623
|
-
const createClientId = /* @__PURE__ */ __name(() => `client_${
|
|
8192
|
+
const createClientId = /* @__PURE__ */ __name(() => `client_${randomUUID3()}`, "createClientId");
|
|
7624
8193
|
const registerClient = /* @__PURE__ */ __name((entry, requestedClientId) => {
|
|
7625
8194
|
if (requestedClientId && entry.clientIds.has(requestedClientId)) {
|
|
7626
8195
|
entry.clientIds.set(
|
|
@@ -7679,7 +8248,7 @@ function createAcpSessionBridge(opts) {
|
|
|
7679
8248
|
if (inFlightChannelSpawn) return await inFlightChannelSpawn;
|
|
7680
8249
|
const promise = (async () => {
|
|
7681
8250
|
const privateParentCapability = randomBytes(32).toString("base64url");
|
|
7682
|
-
const acpChannelId =
|
|
8251
|
+
const acpChannelId = randomUUID3();
|
|
7683
8252
|
const channel = await telemetry.withSpan(
|
|
7684
8253
|
"channel.spawn",
|
|
7685
8254
|
{
|
|
@@ -7800,7 +8369,10 @@ function createAcpSessionBridge(opts) {
|
|
|
7800
8369
|
const currentInfo = infoRef.current;
|
|
7801
8370
|
if (!currentInfo) return;
|
|
7802
8371
|
applyActiveWorkSnapshot(currentInfo, snapshot);
|
|
7803
|
-
}
|
|
8372
|
+
},
|
|
8373
|
+
// Child-side automatic title updates change persisted catalog
|
|
8374
|
+
// metadata the bridge never sees; forward the catalog-clock mark.
|
|
8375
|
+
markSessionCatalogChanged
|
|
7804
8376
|
);
|
|
7805
8377
|
const rawConnection = new ClientSideConnection(
|
|
7806
8378
|
() => channel.transportGuard ? createLogSafeAcpClient(client, channel.transportGuard) : client,
|
|
@@ -7938,6 +8510,9 @@ function createAcpSessionBridge(opts) {
|
|
|
7938
8510
|
touchActivity();
|
|
7939
8511
|
}
|
|
7940
8512
|
byId.delete(sid);
|
|
8513
|
+
if (retainedMedia.has(sid)) {
|
|
8514
|
+
retainedMediaDetachedAt.set(sid, Date.now());
|
|
8515
|
+
}
|
|
7941
8516
|
telemetry.metrics?.sessionLifecycle("die");
|
|
7942
8517
|
emitSessionLifecycle({
|
|
7943
8518
|
type: "removed",
|
|
@@ -8975,6 +9550,7 @@ function createAcpSessionBridge(opts) {
|
|
|
8975
9550
|
workspaceCwd,
|
|
8976
9551
|
persistence: createSessionArtifactPersistence(ci.connection, sessionId)
|
|
8977
9552
|
}),
|
|
9553
|
+
media: retainSessionMedia(sessionId),
|
|
8978
9554
|
recordingDegraded: false,
|
|
8979
9555
|
closing: false,
|
|
8980
9556
|
cwdChangeQueue: Promise.resolve(),
|
|
@@ -8982,6 +9558,9 @@ function createAcpSessionBridge(opts) {
|
|
|
8982
9558
|
pendingPromptCount: 0,
|
|
8983
9559
|
pendingAgentNotificationCount: 0,
|
|
8984
9560
|
pendingPromptList: [],
|
|
9561
|
+
terminalTurnStatuses: /* @__PURE__ */ new Map(),
|
|
9562
|
+
enrichedTerminalPromptIds: /* @__PURE__ */ new Set(),
|
|
9563
|
+
rewindGeneration: 0,
|
|
8985
9564
|
midTurnMessageQueue: [],
|
|
8986
9565
|
settledMidTurnMessageIds: [],
|
|
8987
9566
|
promotedMidTurnMessageIds: [],
|
|
@@ -9931,6 +10510,9 @@ function createAcpSessionBridge(opts) {
|
|
|
9931
10510
|
const restoreEntry = byId.get(req.sessionId);
|
|
9932
10511
|
if (restoreEntry?.events === restoreEvents) {
|
|
9933
10512
|
byId.delete(req.sessionId);
|
|
10513
|
+
if (retainedMedia.has(req.sessionId)) {
|
|
10514
|
+
retainedMediaDetachedAt.set(req.sessionId, Date.now());
|
|
10515
|
+
}
|
|
9934
10516
|
ci?.sessionIds.delete(req.sessionId);
|
|
9935
10517
|
emitSessionLifecycle({
|
|
9936
10518
|
type: "removed",
|
|
@@ -10094,6 +10676,15 @@ function createAcpSessionBridge(opts) {
|
|
|
10094
10676
|
} catch {
|
|
10095
10677
|
}
|
|
10096
10678
|
entry.events.close();
|
|
10679
|
+
if (reason === "last_client_detached" || reason === "idle_timeout") {
|
|
10680
|
+
retainedMediaDetachedAt.set(sessionId, Date.now());
|
|
10681
|
+
} else {
|
|
10682
|
+
await releaseSessionMedia(sessionId).catch((error) => {
|
|
10683
|
+
writeStderrLine(
|
|
10684
|
+
`qwen serve: failed to release media for closed session ${JSON.stringify(sessionId)}: ${error instanceof Error ? error.message : String(error)}`
|
|
10685
|
+
);
|
|
10686
|
+
});
|
|
10687
|
+
}
|
|
10097
10688
|
if (!agentSessionClosed) {
|
|
10098
10689
|
try {
|
|
10099
10690
|
await telemetry.withSpan(
|
|
@@ -10122,25 +10713,76 @@ function createAcpSessionBridge(opts) {
|
|
|
10122
10713
|
ring.splice(0, ring.length - MID_TURN_RECONCILIATION_RING_SIZE);
|
|
10123
10714
|
}
|
|
10124
10715
|
}, "rememberMidTurnId");
|
|
10125
|
-
const
|
|
10126
|
-
|
|
10716
|
+
const removeQueuedMedia = /* @__PURE__ */ __name((entry, content) => {
|
|
10717
|
+
for (const block of content ?? []) {
|
|
10718
|
+
if (!isSessionMediaReference(block)) continue;
|
|
10719
|
+
void entry.media.remove(block.mediaId).catch((error) => {
|
|
10720
|
+
writeStderrLine(
|
|
10721
|
+
`[session-media] session=${JSON.stringify(entry.sessionId)} failed to remove queued media ${JSON.stringify(block.mediaId)}: ${JSON.stringify(error instanceof Error ? error.message : String(error))}`
|
|
10722
|
+
);
|
|
10723
|
+
});
|
|
10724
|
+
}
|
|
10725
|
+
}, "removeQueuedMedia");
|
|
10726
|
+
const promoteMidTurnMessage = /* @__PURE__ */ __name((entry, messageId, text, originatorClientId, content) => {
|
|
10727
|
+
const resolvableBlocks = [];
|
|
10728
|
+
let degraded = 0;
|
|
10729
|
+
for (const block of content ?? []) {
|
|
10730
|
+
try {
|
|
10731
|
+
entry.media.assertReference(block);
|
|
10732
|
+
resolvableBlocks.push(block);
|
|
10733
|
+
} catch (error) {
|
|
10734
|
+
if (!(error instanceof SessionMediaReferenceError)) throw error;
|
|
10735
|
+
degraded += 1;
|
|
10736
|
+
}
|
|
10737
|
+
}
|
|
10738
|
+
let prompt = [
|
|
10739
|
+
...text ? [{ type: "text", text }] : [],
|
|
10740
|
+
...resolvableBlocks
|
|
10741
|
+
];
|
|
10742
|
+
if (degraded > 0) {
|
|
10743
|
+
prompt = withMediaDegradationMarker(prompt);
|
|
10744
|
+
}
|
|
10745
|
+
const context = {
|
|
10746
|
+
promptId: messageId,
|
|
10747
|
+
promotedMidTurn: { originatorClientId },
|
|
10748
|
+
onPromptAdmitted: /* @__PURE__ */ __name(() => {
|
|
10749
|
+
rememberMidTurnId(entry.promotedMidTurnMessageIds, messageId);
|
|
10750
|
+
}, "onPromptAdmitted")
|
|
10751
|
+
};
|
|
10752
|
+
const sendFallback = /* @__PURE__ */ __name(() => bridgeApi.sendPrompt(
|
|
10127
10753
|
entry.sessionId,
|
|
10128
10754
|
{
|
|
10129
10755
|
sessionId: entry.sessionId,
|
|
10130
|
-
prompt:
|
|
10756
|
+
prompt: withMediaDegradationMarker(
|
|
10757
|
+
text ? [{ type: "text", text }] : []
|
|
10758
|
+
)
|
|
10131
10759
|
},
|
|
10132
10760
|
void 0,
|
|
10133
|
-
|
|
10134
|
-
|
|
10135
|
-
|
|
10136
|
-
|
|
10137
|
-
|
|
10138
|
-
|
|
10139
|
-
|
|
10140
|
-
|
|
10141
|
-
|
|
10142
|
-
|
|
10143
|
-
|
|
10761
|
+
context
|
|
10762
|
+
), "sendFallback");
|
|
10763
|
+
let result;
|
|
10764
|
+
try {
|
|
10765
|
+
result = bridgeApi.sendPrompt(
|
|
10766
|
+
entry.sessionId,
|
|
10767
|
+
{
|
|
10768
|
+
sessionId: entry.sessionId,
|
|
10769
|
+
prompt
|
|
10770
|
+
},
|
|
10771
|
+
void 0,
|
|
10772
|
+
context
|
|
10773
|
+
);
|
|
10774
|
+
} catch (error) {
|
|
10775
|
+
try {
|
|
10776
|
+
if (!(error instanceof SessionMediaReferenceError)) throw error;
|
|
10777
|
+
result = sendFallback();
|
|
10778
|
+
} catch (fallbackError) {
|
|
10779
|
+
writeStderrLine(
|
|
10780
|
+
`[mid-turn] session=${JSON.stringify(entry.sessionId)} failed to run promoted message ${JSON.stringify(messageId)}: ${JSON.stringify(fallbackError instanceof Error ? fallbackError.message : String(fallbackError))}`
|
|
10781
|
+
);
|
|
10782
|
+
return;
|
|
10783
|
+
}
|
|
10784
|
+
}
|
|
10785
|
+
void result.catch((error) => {
|
|
10144
10786
|
writeStderrLine(
|
|
10145
10787
|
`[mid-turn] session=${JSON.stringify(entry.sessionId)} failed to run promoted message ${JSON.stringify(messageId)}: ${JSON.stringify(error instanceof Error ? error.message : String(error))}`
|
|
10146
10788
|
);
|
|
@@ -10460,7 +11102,7 @@ function createAcpSessionBridge(opts) {
|
|
|
10460
11102
|
req.branch,
|
|
10461
11103
|
req.sessionId
|
|
10462
11104
|
);
|
|
10463
|
-
const tracker = effectiveScope === "single" ? workspaceKey : `${workspaceKey}#${
|
|
11105
|
+
const tracker = effectiveScope === "single" ? workspaceKey : `${workspaceKey}#${randomUUID3()}`;
|
|
10464
11106
|
inFlightSpawns.set(tracker, promise);
|
|
10465
11107
|
try {
|
|
10466
11108
|
return await promise;
|
|
@@ -10490,9 +11132,15 @@ function createAcpSessionBridge(opts) {
|
|
|
10490
11132
|
)
|
|
10491
11133
|
);
|
|
10492
11134
|
}
|
|
11135
|
+
if (!Array.isArray(req.prompt)) {
|
|
11136
|
+
return Promise.reject(
|
|
11137
|
+
RequestError.invalidParams(void 0, "Prompt must be an array")
|
|
11138
|
+
);
|
|
11139
|
+
}
|
|
10493
11140
|
const promotedMidTurn = context?.promotedMidTurn;
|
|
10494
11141
|
const isPromotedMidTurn = promotedMidTurn !== void 0;
|
|
10495
11142
|
const originatorClientId = promotedMidTurn ? promotedMidTurn.originatorClientId : resolveTrustedClientId(entry, context?.clientId);
|
|
11143
|
+
entry.media.assertReferences(req.prompt);
|
|
10496
11144
|
const modelPrompt = context?.modelPrompt;
|
|
10497
11145
|
if (modelPrompt !== void 0 && !isValidTrustedModelPrompt(modelPrompt)) {
|
|
10498
11146
|
throw new TypeError(
|
|
@@ -10516,7 +11164,7 @@ function createAcpSessionBridge(opts) {
|
|
|
10516
11164
|
promptSlotReleased = true;
|
|
10517
11165
|
entry.pendingPromptCount = Math.max(0, entry.pendingPromptCount - 1);
|
|
10518
11166
|
}, "releasePromptSlot");
|
|
10519
|
-
const promptId = context?.promptId ??
|
|
11167
|
+
const promptId = context?.promptId ?? randomUUID3();
|
|
10520
11168
|
const invocationContext = Object.freeze({
|
|
10521
11169
|
version: 1,
|
|
10522
11170
|
sessionId,
|
|
@@ -10549,6 +11197,7 @@ function createAcpSessionBridge(opts) {
|
|
|
10549
11197
|
...originatorClientId !== void 0 ? { originatorClientId } : {},
|
|
10550
11198
|
...isPromotedMidTurn ? { promotedMidTurn: true } : {},
|
|
10551
11199
|
text: pendingText,
|
|
11200
|
+
content: extractMediaBlocks(req.prompt),
|
|
10552
11201
|
abortController: pendingAbort,
|
|
10553
11202
|
state: isQueued ? "queued" : "running"
|
|
10554
11203
|
};
|
|
@@ -10641,6 +11290,7 @@ function createAcpSessionBridge(opts) {
|
|
|
10641
11290
|
}
|
|
10642
11291
|
throw new DOMException("Prompt aborted", "AbortError");
|
|
10643
11292
|
}
|
|
11293
|
+
pendingEntry.startedAt = Date.now();
|
|
10644
11294
|
if (pendingEntry.state === "queued" || isPromotedMidTurn) {
|
|
10645
11295
|
if (pendingEntry.state === "queued") {
|
|
10646
11296
|
delete entry.todoStopGuardAwaitingQueuedPromptOwnerPromptId;
|
|
@@ -10668,10 +11318,25 @@ function createAcpSessionBridge(opts) {
|
|
|
10668
11318
|
...context?.clientId ? { "qwen-code.client_id": context.clientId } : {}
|
|
10669
11319
|
},
|
|
10670
11320
|
async () => {
|
|
11321
|
+
let dispatchBlocks = req.prompt;
|
|
11322
|
+
let resolvedPrompt;
|
|
11323
|
+
try {
|
|
11324
|
+
resolvedPrompt = await entry.media.resolveContent(dispatchBlocks);
|
|
11325
|
+
} catch (error) {
|
|
11326
|
+
if (!isPromotedMidTurn || !(error instanceof SessionMediaReferenceError)) {
|
|
11327
|
+
throw error;
|
|
11328
|
+
}
|
|
11329
|
+
const perBlock = await entry.media.resolveContentDegrading(dispatchBlocks);
|
|
11330
|
+
dispatchBlocks = perBlock.retainedBlocks;
|
|
11331
|
+
resolvedPrompt = withMediaDegradationMarker(
|
|
11332
|
+
perBlock.resolvedBlocks
|
|
11333
|
+
);
|
|
11334
|
+
}
|
|
10671
11335
|
const normalized = telemetry.injectPromptContext(
|
|
10672
11336
|
{
|
|
10673
11337
|
...req,
|
|
10674
|
-
sessionId
|
|
11338
|
+
sessionId,
|
|
11339
|
+
prompt: resolvedPrompt
|
|
10675
11340
|
}
|
|
10676
11341
|
);
|
|
10677
11342
|
assertLivePromptEntry(sessionId, entry);
|
|
@@ -10694,6 +11359,7 @@ function createAcpSessionBridge(opts) {
|
|
|
10694
11359
|
delete meta[DAEMON_CHANNEL_DELIVERY_META_KEY];
|
|
10695
11360
|
delete meta[DAEMON_PROMPT_DISPLAY_TEXT_META_KEY];
|
|
10696
11361
|
delete meta[DAEMON_MODEL_PROMPT_META_KEY];
|
|
11362
|
+
delete meta[DAEMON_MEDIA_REFERENCES_META_KEY];
|
|
10697
11363
|
delete meta[CHANNEL_PROMPT_META_KEY];
|
|
10698
11364
|
if (isRetry) {
|
|
10699
11365
|
meta[DAEMON_RETRY_META_KEY] = true;
|
|
@@ -10710,6 +11376,12 @@ function createAcpSessionBridge(opts) {
|
|
|
10710
11376
|
if (modelPrompt !== void 0) {
|
|
10711
11377
|
meta[DAEMON_MODEL_PROMPT_META_KEY] = modelPrompt;
|
|
10712
11378
|
}
|
|
11379
|
+
const mediaReferences = dispatchBlocks.filter(
|
|
11380
|
+
isSessionMediaReference
|
|
11381
|
+
);
|
|
11382
|
+
if (mediaReferences.length > 0) {
|
|
11383
|
+
meta[DAEMON_MEDIA_REFERENCES_META_KEY] = mediaReferences;
|
|
11384
|
+
}
|
|
10713
11385
|
if (context?.channelPrompt === true) {
|
|
10714
11386
|
meta[CHANNEL_PROMPT_META_KEY] = true;
|
|
10715
11387
|
}
|
|
@@ -10738,7 +11410,10 @@ function createAcpSessionBridge(opts) {
|
|
|
10738
11410
|
if (!isRetry && !isContinue) {
|
|
10739
11411
|
echoPromptToSessionBus(
|
|
10740
11412
|
entry,
|
|
10741
|
-
|
|
11413
|
+
{
|
|
11414
|
+
...promptRequest,
|
|
11415
|
+
prompt: dispatchBlocks
|
|
11416
|
+
},
|
|
10742
11417
|
pendingEntry.promptId,
|
|
10743
11418
|
originatorClientId,
|
|
10744
11419
|
channelDisplayText
|
|
@@ -10894,7 +11569,8 @@ function createAcpSessionBridge(opts) {
|
|
|
10894
11569
|
entry,
|
|
10895
11570
|
message.messageId,
|
|
10896
11571
|
message.text,
|
|
10897
|
-
message.originatorClientId
|
|
11572
|
+
message.originatorClientId,
|
|
11573
|
+
message.content
|
|
10898
11574
|
);
|
|
10899
11575
|
}
|
|
10900
11576
|
void maybeCloseIdleSession(entry, "prompt_settled");
|
|
@@ -11141,6 +11817,7 @@ function createAcpSessionBridge(opts) {
|
|
|
11141
11817
|
`branchSession: agent returned invalid response: ${JSON.stringify(result)}`
|
|
11142
11818
|
);
|
|
11143
11819
|
}
|
|
11820
|
+
markSessionCatalogChanged();
|
|
11144
11821
|
const rawBranchName = result.displayName ?? result.title;
|
|
11145
11822
|
const branchDisplayName = typeof rawBranchName === "string" ? rawBranchName : result.newSessionId.slice(0, 8);
|
|
11146
11823
|
if (!restoreBranch) {
|
|
@@ -11334,6 +12011,7 @@ function createAcpSessionBridge(opts) {
|
|
|
11334
12011
|
const entry = byId.get(sessionId);
|
|
11335
12012
|
if (entry) {
|
|
11336
12013
|
entry.worktree = worktree;
|
|
12014
|
+
markSessionCatalogChanged();
|
|
11337
12015
|
}
|
|
11338
12016
|
},
|
|
11339
12017
|
async closeSession(sessionId, context, closeOpts) {
|
|
@@ -11359,6 +12037,7 @@ function createAcpSessionBridge(opts) {
|
|
|
11359
12037
|
const nextDisplayName = metadata.displayName || void 0;
|
|
11360
12038
|
if (entry.displayName !== nextDisplayName) {
|
|
11361
12039
|
entry.displayName = nextDisplayName;
|
|
12040
|
+
markSessionCatalogChanged();
|
|
11362
12041
|
writeStderrLine(
|
|
11363
12042
|
`qwen serve: updated session metadata ${JSON.stringify(sessionId)} displayName=${entry.displayName === void 0 ? "cleared" : "set"}` + (context?.clientId ? ` by client ${JSON.stringify(context.clientId)}` : "")
|
|
11364
12043
|
);
|
|
@@ -11421,7 +12100,7 @@ function createAcpSessionBridge(opts) {
|
|
|
11421
12100
|
return warnings.length > 0 ? { ...result, warnings } : result;
|
|
11422
12101
|
},
|
|
11423
12102
|
listWorkspaceSessions(workspaceCwd) {
|
|
11424
|
-
if (!
|
|
12103
|
+
if (!path4.isAbsolute(workspaceCwd)) return [];
|
|
11425
12104
|
const key = workspaceCwd === boundWorkspace ? boundWorkspace : canonicalizeWorkspace(workspaceCwd);
|
|
11426
12105
|
if (key !== boundWorkspace) return [];
|
|
11427
12106
|
const out = [];
|
|
@@ -11432,6 +12111,8 @@ function createAcpSessionBridge(opts) {
|
|
|
11432
12111
|
}
|
|
11433
12112
|
return out;
|
|
11434
12113
|
},
|
|
12114
|
+
getSessionCatalogVersion,
|
|
12115
|
+
markSessionCatalogChanged,
|
|
11435
12116
|
getSessionSummary(sessionId) {
|
|
11436
12117
|
const entry = byId.get(sessionId);
|
|
11437
12118
|
if (!entry) throw new SessionNotFoundError(sessionId);
|
|
@@ -12124,7 +12805,7 @@ function createAcpSessionBridge(opts) {
|
|
|
12124
12805
|
const info = channelInfoForEntry(entry);
|
|
12125
12806
|
if (!info || info.isDying) throw new SessionNotFoundError(sessionId);
|
|
12126
12807
|
resolveTrustedClientId(entry, context?.clientId);
|
|
12127
|
-
const requestId =
|
|
12808
|
+
const requestId = randomUUID3();
|
|
12128
12809
|
const queue = new GenerationStreamQueue(
|
|
12129
12810
|
GENERATION_STREAM_QUEUE_CAPACITY
|
|
12130
12811
|
);
|
|
@@ -12191,14 +12872,110 @@ function createAcpSessionBridge(opts) {
|
|
|
12191
12872
|
const entry = byId.get(sessionId);
|
|
12192
12873
|
if (!entry) throw new SessionNotFoundError(sessionId);
|
|
12193
12874
|
resolveTrustedClientId(entry, context?.clientId);
|
|
12194
|
-
return entry.pendingPromptList.filter((p) => !p.removed).map((p) => ({
|
|
12875
|
+
return entry.pendingPromptList.filter((p) => !p.removed && !p.terminalPublished).map((p) => ({
|
|
12195
12876
|
promptId: p.promptId,
|
|
12196
12877
|
text: p.text,
|
|
12878
|
+
...p.content ? { content: p.content } : {},
|
|
12197
12879
|
queuedAt: p.queuedAt,
|
|
12198
12880
|
state: p.state,
|
|
12199
12881
|
...p.originatorClientId !== void 0 ? { originatorClientId: p.originatorClientId } : {}
|
|
12200
12882
|
}));
|
|
12201
12883
|
},
|
|
12884
|
+
async getSessionTurnStatus(sessionId, context, promptId) {
|
|
12885
|
+
const entry = byId.get(sessionId);
|
|
12886
|
+
if (!entry) throw new SessionNotFoundError(sessionId);
|
|
12887
|
+
resolveTrustedClientId(entry, context?.clientId);
|
|
12888
|
+
const liveBeforeRead = findLiveTurnStatus(entry, promptId);
|
|
12889
|
+
if (liveBeforeRead) return liveBeforeRead;
|
|
12890
|
+
if (promptId !== void 0 && entry.enrichedTerminalPromptIds.has(promptId)) {
|
|
12891
|
+
const enrichedTerminal = entry.terminalTurnStatuses.get(promptId);
|
|
12892
|
+
if (enrichedTerminal) return enrichedTerminal;
|
|
12893
|
+
}
|
|
12894
|
+
const rewindGenerationBeforeRead = entry.rewindGeneration;
|
|
12895
|
+
let result;
|
|
12896
|
+
try {
|
|
12897
|
+
result = await requestSessionStatus(
|
|
12898
|
+
sessionId,
|
|
12899
|
+
SERVE_CONTROL_EXT_METHODS.sessionTurnStatus,
|
|
12900
|
+
{ ...promptId !== void 0 ? { promptId } : {} },
|
|
12901
|
+
// Transcript scans of large histories exceed the 10s init default;
|
|
12902
|
+
// give the read the same budget as other transcript reads.
|
|
12903
|
+
SESSION_TRANSCRIPT_TIMEOUT_MS
|
|
12904
|
+
);
|
|
12905
|
+
} catch (error) {
|
|
12906
|
+
const liveAfterFailure = findLiveTurnStatus(entry, promptId);
|
|
12907
|
+
if (liveAfterFailure) return liveAfterFailure;
|
|
12908
|
+
const terminalAfterFailure = promptId !== void 0 ? entry.terminalTurnStatuses.get(promptId) : latestTerminalTurnStatus(entry);
|
|
12909
|
+
if (terminalAfterFailure) return terminalAfterFailure;
|
|
12910
|
+
throw error;
|
|
12911
|
+
}
|
|
12912
|
+
const liveAfterRead = findLiveTurnStatus(entry, promptId);
|
|
12913
|
+
if (liveAfterRead) return liveAfterRead;
|
|
12914
|
+
const terminal = promptId !== void 0 ? entry.terminalTurnStatuses.get(promptId) : latestTerminalTurnStatus(entry);
|
|
12915
|
+
const persisted = result.turnResult && entry.rewindGeneration === rewindGenerationBeforeRead ? settledTurnStatus(sessionId, result.turnResult) : void 0;
|
|
12916
|
+
if (promptId !== void 0) {
|
|
12917
|
+
if (terminal && persisted) {
|
|
12918
|
+
const merged = mergeTerminalWithPersisted(terminal, persisted);
|
|
12919
|
+
rememberEnrichedTerminalTurnStatus(entry, promptId, merged);
|
|
12920
|
+
return merged;
|
|
12921
|
+
}
|
|
12922
|
+
if (terminal) return terminal;
|
|
12923
|
+
if (persisted) {
|
|
12924
|
+
rememberEnrichedTerminalTurnStatus(entry, promptId, persisted);
|
|
12925
|
+
return persisted;
|
|
12926
|
+
}
|
|
12927
|
+
} else {
|
|
12928
|
+
if (terminal && persisted && terminal.promptId === persisted.promptId) {
|
|
12929
|
+
return mergeTerminalWithPersisted(terminal, persisted);
|
|
12930
|
+
}
|
|
12931
|
+
if (terminal && persisted) {
|
|
12932
|
+
return (terminal.endedAt ?? 0) >= (persisted.endedAt ?? 0) ? terminal : persisted;
|
|
12933
|
+
}
|
|
12934
|
+
if (terminal) return terminal;
|
|
12935
|
+
if (persisted) return persisted;
|
|
12936
|
+
}
|
|
12937
|
+
if (promptId !== void 0) {
|
|
12938
|
+
return void 0;
|
|
12939
|
+
}
|
|
12940
|
+
return { sessionId, state: "idle" };
|
|
12941
|
+
},
|
|
12942
|
+
async storeSessionMedia(sessionId, data, mimeType, context) {
|
|
12943
|
+
const entry = byId.get(sessionId);
|
|
12944
|
+
if (!entry) throw new SessionNotFoundError(sessionId);
|
|
12945
|
+
resolveTrustedClientId(entry, context?.clientId);
|
|
12946
|
+
const operation = mediaPutQueue.then(async () => {
|
|
12947
|
+
if (byId.get(sessionId) !== entry) {
|
|
12948
|
+
throw new SessionNotFoundError(sessionId);
|
|
12949
|
+
}
|
|
12950
|
+
const retainedBytes = [...new Set(retainedMedia.values())].reduce(
|
|
12951
|
+
(total, store) => total + store.sizeBytes,
|
|
12952
|
+
0
|
|
12953
|
+
);
|
|
12954
|
+
if (retainedBytes + data.byteLength > MAX_RETAINED_SESSION_MEDIA_BYTES) {
|
|
12955
|
+
throw new RangeError(
|
|
12956
|
+
`Session media exceeds the ${MAX_RETAINED_SESSION_MEDIA_BYTES}-byte daemon limit`
|
|
12957
|
+
);
|
|
12958
|
+
}
|
|
12959
|
+
return await entry.media.put(data, mimeType);
|
|
12960
|
+
});
|
|
12961
|
+
mediaPutQueue = operation.then(
|
|
12962
|
+
() => void 0,
|
|
12963
|
+
() => void 0
|
|
12964
|
+
);
|
|
12965
|
+
return await operation;
|
|
12966
|
+
},
|
|
12967
|
+
async readSessionMedia(sessionId, mediaId, context) {
|
|
12968
|
+
const entry = byId.get(sessionId);
|
|
12969
|
+
if (!entry) throw new SessionNotFoundError(sessionId);
|
|
12970
|
+
resolveTrustedClientId(entry, context?.clientId);
|
|
12971
|
+
return await entry.media.read(mediaId);
|
|
12972
|
+
},
|
|
12973
|
+
async removeSessionMedia(sessionId, mediaId, context) {
|
|
12974
|
+
const entry = byId.get(sessionId);
|
|
12975
|
+
if (!entry) throw new SessionNotFoundError(sessionId);
|
|
12976
|
+
resolveTrustedClientId(entry, context?.clientId);
|
|
12977
|
+
return await entry.media.remove(mediaId);
|
|
12978
|
+
},
|
|
12202
12979
|
removePendingPrompt(sessionId, promptId, context) {
|
|
12203
12980
|
const entry = byId.get(sessionId);
|
|
12204
12981
|
if (!entry) throw new SessionNotFoundError(sessionId);
|
|
@@ -12217,6 +12994,7 @@ function createAcpSessionBridge(opts) {
|
|
|
12217
12994
|
);
|
|
12218
12995
|
if (target.state === "queued") {
|
|
12219
12996
|
entry.pendingPromptList.splice(idx, 1);
|
|
12997
|
+
removeQueuedMedia(entry, target.content);
|
|
12220
12998
|
} else {
|
|
12221
12999
|
target.removed = true;
|
|
12222
13000
|
}
|
|
@@ -12242,7 +13020,10 @@ function createAcpSessionBridge(opts) {
|
|
|
12242
13020
|
context?.clientId
|
|
12243
13021
|
);
|
|
12244
13022
|
const trimmed = message.trim();
|
|
12245
|
-
|
|
13023
|
+
const mediaBlocks = (options?.content ?? []).filter(
|
|
13024
|
+
(block) => block.type === "image"
|
|
13025
|
+
);
|
|
13026
|
+
if (trimmed.length === 0 && mediaBlocks.length === 0) {
|
|
12246
13027
|
writeStderrLine(
|
|
12247
13028
|
`[mid-turn] session=${entry.sessionId} rejected: empty`
|
|
12248
13029
|
);
|
|
@@ -12253,11 +13034,12 @@ function createAcpSessionBridge(opts) {
|
|
|
12253
13034
|
(queued) => queued.messageId === requestedMessageId
|
|
12254
13035
|
);
|
|
12255
13036
|
if (existing) {
|
|
12256
|
-
|
|
13037
|
+
const sameMedia = JSON.stringify(existing.content ?? []) === JSON.stringify(mediaBlocks);
|
|
13038
|
+
if (existing.text === trimmed && sameMedia) {
|
|
12257
13039
|
return { accepted: true, messageId: requestedMessageId };
|
|
12258
13040
|
}
|
|
12259
13041
|
writeStderrLine(
|
|
12260
|
-
`[mid-turn] session=${JSON.stringify(entry.sessionId)} rejected id ${JSON.stringify(requestedMessageId)}: text mismatch`
|
|
13042
|
+
`[mid-turn] session=${JSON.stringify(entry.sessionId)} rejected id ${JSON.stringify(requestedMessageId)}: text or content mismatch`
|
|
12261
13043
|
);
|
|
12262
13044
|
return { accepted: false };
|
|
12263
13045
|
}
|
|
@@ -12265,11 +13047,16 @@ function createAcpSessionBridge(opts) {
|
|
|
12265
13047
|
(pending) => pending.promptId === requestedMessageId
|
|
12266
13048
|
);
|
|
12267
13049
|
if (promoted) {
|
|
12268
|
-
|
|
13050
|
+
const promotedImages = (promoted.content ?? []).filter(
|
|
13051
|
+
(block) => block.type === "image"
|
|
13052
|
+
);
|
|
13053
|
+
const sameMedia = JSON.stringify(promotedImages) === JSON.stringify(mediaBlocks);
|
|
13054
|
+
const promotedText = promoted.text === "[image]" && trimmed.length === 0 ? "" : promoted.text;
|
|
13055
|
+
if (promotedText === trimmed && sameMedia) {
|
|
12269
13056
|
return { accepted: true, messageId: requestedMessageId };
|
|
12270
13057
|
}
|
|
12271
13058
|
writeStderrLine(
|
|
12272
|
-
`[mid-turn] session=${JSON.stringify(entry.sessionId)} rejected promoted id ${JSON.stringify(requestedMessageId)}: text mismatch`
|
|
13059
|
+
`[mid-turn] session=${JSON.stringify(entry.sessionId)} rejected promoted id ${JSON.stringify(requestedMessageId)}: text or content mismatch`
|
|
12273
13060
|
);
|
|
12274
13061
|
return { accepted: false };
|
|
12275
13062
|
}
|
|
@@ -12286,7 +13073,21 @@ function createAcpSessionBridge(opts) {
|
|
|
12286
13073
|
);
|
|
12287
13074
|
return { accepted: false };
|
|
12288
13075
|
}
|
|
12289
|
-
|
|
13076
|
+
entry.media.assertReferences(mediaBlocks);
|
|
13077
|
+
const inlineBytes = inlineMediaBlockBytes(mediaBlocks);
|
|
13078
|
+
if (inlineBytes > 0) {
|
|
13079
|
+
const queuedInlineBytes = entry.midTurnMessageQueue.reduce(
|
|
13080
|
+
(total, queued) => total + inlineMediaBlockBytes(queued.content ?? []),
|
|
13081
|
+
0
|
|
13082
|
+
);
|
|
13083
|
+
if (queuedInlineBytes + inlineBytes > SESSION_MEDIA_MAX_TOTAL_BYTES) {
|
|
13084
|
+
writeStderrLine(
|
|
13085
|
+
`[mid-turn] session=${entry.sessionId} rejected: queued inline media exceeds the ${SESSION_MEDIA_MAX_TOTAL_BYTES}-byte session budget`
|
|
13086
|
+
);
|
|
13087
|
+
return { accepted: false };
|
|
13088
|
+
}
|
|
13089
|
+
}
|
|
13090
|
+
const messageId = requestedMessageId ?? randomUUID3();
|
|
12290
13091
|
if (entry.pendingPromptCount === 0) {
|
|
12291
13092
|
if (options?.queueOnly) {
|
|
12292
13093
|
writeStderrLine(
|
|
@@ -12294,7 +13095,13 @@ function createAcpSessionBridge(opts) {
|
|
|
12294
13095
|
);
|
|
12295
13096
|
return { accepted: false };
|
|
12296
13097
|
}
|
|
12297
|
-
promoteMidTurnMessage(
|
|
13098
|
+
promoteMidTurnMessage(
|
|
13099
|
+
entry,
|
|
13100
|
+
messageId,
|
|
13101
|
+
trimmed,
|
|
13102
|
+
originatorClientId,
|
|
13103
|
+
mediaBlocks.length > 0 ? mediaBlocks : void 0
|
|
13104
|
+
);
|
|
12298
13105
|
return { accepted: true, messageId };
|
|
12299
13106
|
}
|
|
12300
13107
|
if (entry.midTurnMessageQueue.length >= MAX_MID_TURN_QUEUE_DEPTH) {
|
|
@@ -12306,6 +13113,7 @@ function createAcpSessionBridge(opts) {
|
|
|
12306
13113
|
const queuedMessage = {
|
|
12307
13114
|
messageId,
|
|
12308
13115
|
text: trimmed,
|
|
13116
|
+
...mediaBlocks.length > 0 ? { content: mediaBlocks } : {},
|
|
12309
13117
|
originatorClientId,
|
|
12310
13118
|
...options?.queueOnly ? {
|
|
12311
13119
|
queueOnly: true,
|
|
@@ -12365,6 +13173,7 @@ function createAcpSessionBridge(opts) {
|
|
|
12365
13173
|
const [removed] = entry.midTurnMessageQueue.splice(index, 1);
|
|
12366
13174
|
rememberMidTurnId(entry.settledMidTurnMessageIds, messageId);
|
|
12367
13175
|
if (removed) {
|
|
13176
|
+
removeQueuedMedia(entry, removed.content);
|
|
12368
13177
|
try {
|
|
12369
13178
|
entry.events.publish({
|
|
12370
13179
|
type: "pending_prompt_completed",
|
|
@@ -12414,7 +13223,11 @@ function createAcpSessionBridge(opts) {
|
|
|
12414
13223
|
// should restore into their queue views.
|
|
12415
13224
|
messages: entry.midTurnMessageQueue.filter((message) => message.originatorClientId !== void 0).map((message) => ({
|
|
12416
13225
|
messageId: message.messageId,
|
|
12417
|
-
text: message.text
|
|
13226
|
+
text: message.text,
|
|
13227
|
+
// Carry the media blocks so a refreshed client can rebuild the
|
|
13228
|
+
// queued row with its attachments (the snapshot is the only
|
|
13229
|
+
// recovery source once the client's in-memory copy is gone).
|
|
13230
|
+
...message.content ? { content: message.content } : {}
|
|
12418
13231
|
})),
|
|
12419
13232
|
settledMessageIds: [...entry.settledMidTurnMessageIds],
|
|
12420
13233
|
promotedMessageIds: [...entry.promotedMidTurnMessageIds]
|
|
@@ -12716,6 +13529,9 @@ function createAcpSessionBridge(opts) {
|
|
|
12716
13529
|
}
|
|
12717
13530
|
throw err;
|
|
12718
13531
|
}
|
|
13532
|
+
entry.terminalTurnStatuses.clear();
|
|
13533
|
+
entry.enrichedTerminalPromptIds.clear();
|
|
13534
|
+
entry.rewindGeneration += 1;
|
|
12719
13535
|
const targetTurnIndex = response["targetTurnIndex"] ?? 0;
|
|
12720
13536
|
const filesChanged = response["filesChanged"] ?? [];
|
|
12721
13537
|
const filesFailed = response["filesFailed"] ?? [];
|
|
@@ -12919,7 +13735,7 @@ function createAcpSessionBridge(opts) {
|
|
|
12919
13735
|
]);
|
|
12920
13736
|
},
|
|
12921
13737
|
generateWorkspaceContent(prompt, signal, _originatorClientId) {
|
|
12922
|
-
const requestId =
|
|
13738
|
+
const requestId = randomUUID3();
|
|
12923
13739
|
const queue = new GenerationStreamQueue(
|
|
12924
13740
|
GENERATION_STREAM_QUEUE_CAPACITY
|
|
12925
13741
|
);
|
|
@@ -13098,6 +13914,11 @@ function createAcpSessionBridge(opts) {
|
|
|
13098
13914
|
closingChannel,
|
|
13099
13915
|
`force kill closing session ${JSON.stringify(sessionId)}`
|
|
13100
13916
|
);
|
|
13917
|
+
await releaseSessionMedia(sessionId).catch((releaseError) => {
|
|
13918
|
+
writeStderrLine(
|
|
13919
|
+
`qwen serve: failed to release media for killed session ${JSON.stringify(sessionId)}: ${releaseError instanceof Error ? releaseError.message : String(releaseError)}`
|
|
13920
|
+
);
|
|
13921
|
+
});
|
|
13101
13922
|
return true;
|
|
13102
13923
|
}
|
|
13103
13924
|
entry.closing = true;
|
|
@@ -13125,6 +13946,11 @@ function createAcpSessionBridge(opts) {
|
|
|
13125
13946
|
ci,
|
|
13126
13947
|
`force kill session ${JSON.stringify(sessionId)}`
|
|
13127
13948
|
);
|
|
13949
|
+
await releaseSessionMedia(sessionId).catch((releaseError) => {
|
|
13950
|
+
writeStderrLine(
|
|
13951
|
+
`qwen serve: failed to release media for killed session ${JSON.stringify(sessionId)}: ${releaseError instanceof Error ? releaseError.message : String(releaseError)}`
|
|
13952
|
+
);
|
|
13953
|
+
});
|
|
13128
13954
|
return true;
|
|
13129
13955
|
}
|
|
13130
13956
|
entry.closing = false;
|
|
@@ -13161,6 +13987,11 @@ function createAcpSessionBridge(opts) {
|
|
|
13161
13987
|
} catch {
|
|
13162
13988
|
}
|
|
13163
13989
|
entry.events.close();
|
|
13990
|
+
await releaseSessionMedia(sessionId).catch((error) => {
|
|
13991
|
+
writeStderrLine(
|
|
13992
|
+
`qwen serve: failed to release media for killed session ${JSON.stringify(sessionId)}: ${error instanceof Error ? error.message : String(error)}`
|
|
13993
|
+
);
|
|
13994
|
+
});
|
|
13164
13995
|
if (ci && hasNoChannelWork(ci)) {
|
|
13165
13996
|
await reapPendingEmptyChannel(ci);
|
|
13166
13997
|
if (!ci.isDying) {
|
|
@@ -13265,6 +14096,8 @@ function createAcpSessionBridge(opts) {
|
|
|
13265
14096
|
) : Promise.resolve();
|
|
13266
14097
|
const teardownResults = await Promise.allSettled([
|
|
13267
14098
|
...channels.map((ci) => ci.channel.kill()),
|
|
14099
|
+
...[...retainedMedia.values()].map((store) => store.close()),
|
|
14100
|
+
mediaPutQueue,
|
|
13268
14101
|
...inFlightSessionAwaits,
|
|
13269
14102
|
...inFlightRestoreAwaits,
|
|
13270
14103
|
inFlightChannelAwait
|