@qwen-code/qwen-code 0.21.14 → 0.21.15
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/features/channels/dingtalk.md +1 -1
- package/bundled/qc-helper/docs/features/code-review.md +20 -2
- package/bundled/qc-helper/docs/qwen-serve.md +1 -1
- package/bundled/review/SKILL.md +66 -36
- package/chunks/{MaxSizedBox-67IDQILY.js → MaxSizedBox-E7CUU3UN.js} +43 -43
- package/chunks/{StandaloneSessionPicker-G4QJIRMH.js → StandaloneSessionPicker-XYUB75AQ.js} +63 -63
- package/chunks/{acp-startup-profiler-HUYGO57H.js → acp-startup-profiler-DDVSJKJK.js} +2 -2
- package/chunks/{acpAgent-BS3YYO33.js → acpAgent-5QZS4VMN.js} +507 -176
- package/chunks/{agent-EHHEXKWN.js → agent-242BTA6Q.js} +40 -40
- package/chunks/{agent-headless-UT2ZF76T.js → agent-headless-4BF7W4TJ.js} +40 -40
- package/chunks/{anthropicContentGenerator-M7XRJMSK.js → anthropicContentGenerator-CU3G53RX.js} +7 -7
- package/chunks/{artifact-tool-GEXTOPVO.js → artifact-tool-LIUSI4XK.js} +3 -3
- package/chunks/{askUserQuestion-B33XRSB7.js → askUserQuestion-454X3UIV.js} +3 -3
- package/chunks/{bridge-WQ4IL2RF.js → bridge-MG4F5NOH.js} +46 -45
- package/chunks/{channel-management-service-X6LCQUAD.js → channel-management-service-KHPAWCX7.js} +1 -1
- package/chunks/{channel-settings-store-ZDFXY7VY.js → channel-settings-store-GQUCL2YM.js} +47 -47
- package/chunks/{channel-worker-group-TJ35JDPE.js → channel-worker-group-IN2UPYHP.js} +6 -5
- package/chunks/{channel-worker-manager-G5LKWGOG.js → channel-worker-manager-4CQPHVD4.js} +6 -5
- package/chunks/{channel-worker-supervisor-OEVWBHGT.js → channel-worker-supervisor-CPPSL7ZH.js} +4 -3
- package/chunks/{chunk-3EZLLVDF.js → chunk-263JC66E.js} +3 -3
- package/chunks/{chunk-OO4FKHLO.js → chunk-2GM44E7D.js} +10 -298
- package/chunks/{chunk-LSO6EL4Y.js → chunk-2MDUS4XE.js} +2 -2
- package/chunks/{chunk-WGHHA7ZH.js → chunk-3C55EUJX.js} +1 -1
- package/chunks/{chunk-47L5MLB5.js → chunk-3EAGKRLN.js} +5 -5
- package/chunks/{chunk-WPVUOVYX.js → chunk-3EQHT3IC.js} +2 -2
- package/chunks/{chunk-OEZCXK7Y.js → chunk-3JZ2AZC6.js} +4 -4
- package/chunks/{chunk-PCETXVVV.js → chunk-3X6KVX37.js} +1 -1
- package/chunks/{chunk-J63PKMYA.js → chunk-435GZDTF.js} +2 -2
- package/chunks/{chunk-I3N2Z25H.js → chunk-47VTGCYK.js} +3 -3
- package/chunks/{chunk-3PWNVF6N.js → chunk-4APB4SP2.js} +1 -1
- package/chunks/{chunk-MA2HEDVP.js → chunk-4CKU5K2R.js} +1 -1
- package/chunks/{chunk-OJB5FYVK.js → chunk-4IOBHNV2.js} +1 -1
- package/chunks/{chunk-MIPFDQAF.js → chunk-4W4BROUS.js} +1 -1
- package/chunks/{chunk-ZIGC3MUS.js → chunk-55P2ESI6.js} +1 -1
- package/chunks/{chunk-CHHABXPE.js → chunk-5AAW6E3C.js} +1 -1
- package/chunks/{chunk-J6YS7Z25.js → chunk-5I2U4PDY.js} +12 -12
- package/chunks/{chunk-NWNEANAT.js → chunk-5M7YKTYX.js} +6 -6
- package/chunks/{chunk-RXHBTKMG.js → chunk-5MA4E4EG.js} +3 -3
- package/chunks/{chunk-CEXU72GE.js → chunk-5NAJDTVP.js} +3 -3
- package/chunks/{chunk-U657UZJN.js → chunk-5WEMSDPR.js} +5 -5
- package/chunks/{chunk-73JUK3ZW.js → chunk-63AIQ2IZ.js} +96 -15
- package/chunks/{chunk-E5WQMF3K.js → chunk-67L6PVD6.js} +2 -2
- package/chunks/{chunk-CZK622ZK.js → chunk-6IFWBM24.js} +3 -3
- package/chunks/{chunk-CPHEPGAO.js → chunk-722JBVVW.js} +1 -1
- package/chunks/chunk-7NLDU6J2.js +367 -0
- package/chunks/{chunk-AKBOLMUF.js → chunk-7S22SX2L.js} +2 -2
- package/chunks/{chunk-SCZU65AI.js → chunk-7VRNXKKK.js} +8 -8
- package/chunks/{chunk-XUJNK7Y6.js → chunk-7WVB4FMG.js} +1 -1
- package/chunks/{chunk-55VKMB7X.js → chunk-A7MIUCUQ.js} +6 -6
- package/chunks/{chunk-NVRMCWTP.js → chunk-A7NBZBGQ.js} +3 -3
- package/chunks/{chunk-N6RSOOWJ.js → chunk-AAG7I5CR.js} +7 -7
- package/chunks/{chunk-EOPBFLA5.js → chunk-AKN26LMT.js} +3 -3
- package/chunks/{chunk-UC67T4SF.js → chunk-AQFWV4YF.js} +2 -1
- package/chunks/{chunk-DVR7XKO5.js → chunk-B5LEKTE7.js} +2 -2
- package/chunks/{chunk-V6WEMZPD.js → chunk-B72KNVKO.js} +3 -3
- package/chunks/{chunk-544KT7X4.js → chunk-BBMVUTXO.js} +1 -1
- package/chunks/{chunk-DHUPMYMC.js → chunk-BORX4PBQ.js} +12 -12
- package/chunks/{chunk-5IJSFWQO.js → chunk-BUZESYJT.js} +4 -4
- package/chunks/{chunk-Y4RVDOXV.js → chunk-DF7KFKCL.js} +4 -4
- package/chunks/{chunk-K2Y45XXS.js → chunk-DFOKBPH5.js} +108 -26
- package/chunks/{chunk-3SL2P3WX.js → chunk-DIHJXVT4.js} +1 -1
- package/chunks/{chunk-WAO53ZQF.js → chunk-DITDNF3D.js} +22 -2
- package/chunks/{chunk-2A6VQJYK.js → chunk-DK4HL3IB.js} +7 -7
- package/chunks/{chunk-6BJSYAML.js → chunk-DPXZUGDQ.js} +46 -21
- package/chunks/{chunk-MVHJZ3FZ.js → chunk-DZNQHKZZ.js} +2 -2
- package/chunks/{chunk-SNQZZ765.js → chunk-EB27VF5Z.js} +2 -2
- package/chunks/{chunk-KC4WMLZO.js → chunk-EXY6APEA.js} +81 -50
- package/chunks/{chunk-7VNHO4MN.js → chunk-F3FRTY4Q.js} +16 -7
- package/chunks/{chunk-FS5NGKWC.js → chunk-F5JZDC4O.js} +3 -3
- package/chunks/{chunk-6QFDQMQX.js → chunk-F7ZK5VMA.js} +1 -1
- package/chunks/{chunk-2B2BF7P7.js → chunk-FAIJ5UIU.js} +3 -3
- package/chunks/{chunk-G6KI5UOJ.js → chunk-FQ6G527Y.js} +3 -3
- package/chunks/{chunk-WSSH2BNO.js → chunk-FQZBD3PY.js} +1 -1
- package/chunks/{chunk-OVY67CYC.js → chunk-G32ESUUC.js} +1 -1
- package/chunks/{chunk-OBJYN4MX.js → chunk-G64PEZZ5.js} +2 -2
- package/chunks/{chunk-QRVHGEVY.js → chunk-GCWILQKA.js} +3 -3
- package/chunks/{chunk-QUGAUQGJ.js → chunk-GX2THELY.js} +1 -0
- package/chunks/{chunk-L3T4V5GZ.js → chunk-GYVB4P5B.js} +721 -331
- package/chunks/{chunk-FAAUPSY2.js → chunk-HEMFCAHG.js} +1 -1
- package/chunks/{chunk-AZQ3DT76.js → chunk-HGGMEDDY.js} +2 -2
- package/chunks/{chunk-SG7ZP5PG.js → chunk-HHNSO2Y4.js} +4 -4
- package/chunks/{chunk-YHXQK4SR.js → chunk-HSCPOEBL.js} +3 -3
- package/chunks/{chunk-H3SHU2XU.js → chunk-I3AB5DOZ.js} +3 -3
- package/chunks/{chunk-SFJMFZT5.js → chunk-IBUXQJHH.js} +1 -1
- package/chunks/{chunk-FN6M5WUL.js → chunk-IFOR6I5C.js} +4 -4
- package/chunks/{chunk-PHN4R2ZV.js → chunk-IU2XWUSI.js} +1 -1
- package/chunks/{chunk-OJOP26ET.js → chunk-J2LZ5OCH.js} +3 -3
- package/chunks/{chunk-4ZMS3JCR.js → chunk-JBSW7JA6.js} +83 -4
- package/chunks/{chunk-QAVTWAHL.js → chunk-JIR6JDGE.js} +3 -3
- package/chunks/{chunk-UGK4K2N2.js → chunk-JS73NNWF.js} +8 -0
- package/chunks/{chunk-2M55OBEB.js → chunk-JV443R5X.js} +1 -1
- package/chunks/{chunk-QEHH23OM.js → chunk-K6GQS2WN.js} +1 -1
- package/chunks/{chunk-6LAPGPVA.js → chunk-KCUGOZPL.js} +2 -2
- package/chunks/{chunk-KV27IEHM.js → chunk-L5JHSPET.js} +1 -1
- package/chunks/{chunk-OFTPCOGR.js → chunk-L7RG5PVT.js} +2902 -1393
- package/chunks/{chunk-TSMPNGBC.js → chunk-LBQBFRFN.js} +2 -2
- package/chunks/chunk-LJZSMWOH.js +18 -0
- package/chunks/{chunk-IA2K2HJE.js → chunk-M53UJS6H.js} +2 -2
- package/chunks/{chunk-KBXKR5R2.js → chunk-M5AIO24H.js} +1 -1
- package/chunks/{chunk-ROIYNTHJ.js → chunk-MD7XDTW7.js} +3 -3
- package/chunks/{chunk-3PWCMXIR.js → chunk-MGEWDLRO.js} +1 -1
- package/chunks/{chunk-4ZS3BLER.js → chunk-NAGJPIPW.js} +22 -7
- package/chunks/{chunk-3YRVPHT3.js → chunk-NCTHX2Z3.js} +14 -14
- package/chunks/{chunk-YP5KH5Y7.js → chunk-ND7NOI4P.js} +1 -1
- package/chunks/{chunk-4W5U2TUT.js → chunk-NGY7B7VF.js} +1 -1
- package/chunks/{chunk-S7N3HUIB.js → chunk-NMSSH43P.js} +6 -6
- package/chunks/{chunk-UYDGFWIJ.js → chunk-NYN4RD3K.js} +66 -7
- package/chunks/{chunk-DGJ7O55J.js → chunk-O327G3QW.js} +3 -3
- package/chunks/{chunk-2C6HJMG3.js → chunk-O75QDGQF.js} +3 -3
- package/chunks/{chunk-SFTKAX4O.js → chunk-OFJ6OFIT.js} +1 -1
- package/chunks/{chunk-6HY6IF3Z.js → chunk-OUYRA764.js} +1 -1
- package/chunks/{chunk-OEYAK5O6.js → chunk-OVS33JJM.js} +5 -5
- package/chunks/{chunk-VFP5YOHJ.js → chunk-PRIX4D6T.js} +6 -6
- package/chunks/{chunk-H4A72DE5.js → chunk-PTMVPFCZ.js} +1 -1
- package/chunks/{chunk-W7EYJGN7.js → chunk-PWQPWISR.js} +8 -8
- package/chunks/{chunk-QFJ5JHQR.js → chunk-PXOIRYE5.js} +1 -1
- package/chunks/{chunk-4SR45OM4.js → chunk-Q5QDZXKL.js} +1 -1
- package/chunks/{chunk-YECDICIO.js → chunk-Q6ETBOWF.js} +1 -1
- package/chunks/{chunk-WP4WIUOJ.js → chunk-QQUVPMMZ.js} +2 -2
- package/chunks/{chunk-C3T6M24E.js → chunk-RLYXWNS3.js} +3 -3
- package/chunks/{chunk-XT4RKHVE.js → chunk-RZ4PE3ER.js} +512 -24
- package/chunks/{chunk-6RDZLBSJ.js → chunk-SGKUVDBX.js} +80 -44
- package/chunks/{chunk-YZHRN3CF.js → chunk-SWOKDPS5.js} +2 -2
- package/chunks/{chunk-SLILKYV2.js → chunk-T2LUUKRI.js} +3 -3
- package/chunks/{chunk-5CVO7YES.js → chunk-U4GL4WDY.js} +1 -1
- package/chunks/{chunk-QEJZUXSK.js → chunk-U53XZHAE.js} +1 -1
- package/chunks/{chunk-XYRBK56E.js → chunk-U7U3CX4K.js} +3353 -1306
- package/chunks/{chunk-HIBNSEJE.js → chunk-UDG5EZJI.js} +0 -2
- package/chunks/{chunk-BQWNIPTE.js → chunk-V4UBYT3Y.js} +1 -1
- package/chunks/{chunk-XITLNXLX.js → chunk-VWS7DWY6.js} +3 -3
- package/chunks/{chunk-PT4I7NBA.js → chunk-VX7TFATF.js} +1 -1
- package/chunks/{chunk-VTOLYFWM.js → chunk-W3M6P3UR.js} +2 -2
- package/chunks/{chunk-CH5OFRV7.js → chunk-W4MLKRZD.js} +3 -3
- package/chunks/chunk-W5YD3QRT.js +367 -0
- package/chunks/{chunk-5IYS4WWR.js → chunk-WAPL2PHU.js} +1 -1
- package/chunks/{chunk-NRPXRNN4.js → chunk-WXFFCRKG.js} +1 -1
- package/chunks/{chunk-E3DYKPYZ.js → chunk-X7EQHW5L.js} +3 -3
- package/chunks/{chunk-BUQDLC2G.js → chunk-XFRYCCVC.js} +3 -3
- package/chunks/{chunk-DRAONPUW.js → chunk-XZ3J6E5Z.js} +2 -2
- package/chunks/{chunk-P3AA6S7O.js → chunk-Y7JGWFTK.js} +1 -1
- package/chunks/{chunk-SXCOEJO4.js → chunk-YLFFVY3G.js} +1 -1
- package/chunks/{chunk-YZOSNW4R.js → chunk-YO7PNVBJ.js} +1 -1
- package/chunks/{chunk-MDIGJH5X.js → chunk-ZL3HKVEQ.js} +4 -4
- package/chunks/{chunk-Y7QY6DKW.js → chunk-ZTLSYXFY.js} +4 -4
- package/chunks/{chunk-RWDNJBWN.js → chunk-ZUISK67X.js} +2 -2
- package/chunks/{chunk-PJSD2FOR.js → chunk-ZVJ5R5LM.js} +33 -33
- package/chunks/{chunk-XLLKYULU.js → chunk-ZWWU6KNS.js} +2 -2
- package/chunks/{computer-use-YORZJQE5.js → computer-use-34X5XJMV.js} +40 -40
- package/chunks/{config-utils-NJQA5YLJ.js → config-utils-XJTGZVY3.js} +2 -2
- package/chunks/{contextCommand-PACHGIF4.js → contextCommand-Q54VMGPA.js} +42 -42
- package/chunks/{core-runtime-6HD5DSPX.js → core-runtime-TIWTFHOR.js} +45 -44
- package/chunks/{create-sub-session-IQFIPUQA.js → create-sub-session-DPEBT657.js} +40 -40
- package/chunks/{create-sub-session-KRQULJE6.js → create-sub-session-TCKWBXEM.js} +6 -4
- package/chunks/{cron-create-NFRZEOQX.js → cron-create-PUCRMWQ6.js} +5 -5
- package/chunks/{cron-delete-GFVSVO7C.js → cron-delete-EOQR5CXU.js} +5 -5
- package/chunks/{cron-list-NRW34CLU.js → cron-list-7O22SQBF.js} +5 -5
- package/chunks/{daemon-XH76IXOC.js → daemon-JE2UIWSY.js} +304 -160
- package/chunks/{daemon-git-worktree-guard-6P27GKSU.js → daemon-git-worktree-guard-XSZ3362V.js} +40 -40
- package/chunks/daemon-status-provider-JBEST4SF.js +104 -0
- package/chunks/{daemon-trust-policy-5QJHAS3N.js → daemon-trust-policy-S6LBG4WN.js} +46 -46
- package/chunks/{daemon-trust-policy-monitor-JA2WZRZ3.js → daemon-trust-policy-monitor-NFO3OIBN.js} +46 -46
- package/chunks/{deferred-core-runtime-R2VWOVG3.js → deferred-core-runtime-Z2TLD2L7.js} +40 -40
- package/chunks/{display-image-ON3EYFRD.js → display-image-6FCICTXS.js} +5 -5
- package/chunks/{dist-IYYN3RUT.js → dist-IELOWDOT.js} +81 -17
- package/chunks/{earlyInputCapture-PQEEOFKJ.js → earlyInputCapture-KCZDAQWY.js} +41 -41
- package/chunks/{edit-RASZHTU2.js → edit-3UADXGNC.js} +41 -41
- package/chunks/{enter-worktree-CH5OMHJE.js → enter-worktree-J66YDAJE.js} +40 -40
- package/chunks/{enterPlanMode-AQKR3CAH.js → enterPlanMode-YUZUKY5F.js} +40 -40
- package/chunks/{environment-7QRYIEBA.js → environment-6IEK2353.js} +42 -42
- package/chunks/{errors-P2LL5452.js → errors-RVLRX7XI.js} +42 -42
- package/chunks/{exit-worktree-WUDL26CY.js → exit-worktree-SNMPATZE.js} +40 -40
- package/chunks/{exitPlanMode-JM75SAUI.js → exitPlanMode-DP4TURUC.js} +40 -40
- package/chunks/{fast-path-KVNSOHVA.js → fast-path-5CC6RKES.js} +2 -2
- package/chunks/{gemini-ADMD2EOS.js → gemini-F64ZP4SG.js} +83 -82
- package/chunks/{geminiContentGenerator-CS3M7SOS.js → geminiContentGenerator-KAFSMFA6.js} +7 -7
- package/chunks/{getMachineId-bsd-FG7IUY6U.js → getMachineId-bsd-LSY4WMOF.js} +1 -1
- package/chunks/{getMachineId-darwin-GLCJI2RA.js → getMachineId-darwin-JOFR4UIT.js} +1 -1
- package/chunks/{getMachineId-linux-O6OPPAKO.js → getMachineId-linux-QEDBS6GI.js} +1 -1
- package/chunks/{getMachineId-unsupported-S6CKYVGC.js → getMachineId-unsupported-IPZ3YRKP.js} +1 -1
- package/chunks/{getMachineId-win-X5SRNEH7.js → getMachineId-win-TJ2OZ7AA.js} +1 -1
- package/chunks/{glob-WIJOGYVV.js → glob-OE27ZGK4.js} +40 -40
- package/chunks/{goal-tools-K5OHOJ6B.js → goal-tools-YIADM4RZ.js} +5 -5
- package/chunks/{grep-CIFRQBR7.js → grep-VBV6BWSP.js} +40 -40
- package/chunks/{handleAutoUpdate-KJ4SN7DM.js → handleAutoUpdate-YDMS57ZN.js} +46 -44
- package/chunks/{i18n-36SZUO4C.js → i18n-JIW77MSO.js} +41 -41
- package/chunks/{image-gen-R4B5VUYB.js → image-gen-L4A2ISEH.js} +11 -11
- package/chunks/{initializer-CW5YCAOL.js → initializer-F7I7QDHK.js} +47 -47
- package/chunks/{installationInfo-NMQIOUGY.js → installationInfo-KOUBU7MH.js} +43 -41
- package/chunks/{keychain-token-storage-3XFJ5ZB2.js → keychain-token-storage-7SL4ZWQQ.js} +3 -3
- package/chunks/{list-HHGT3S4P.js → list-AJ5BRB7C.js} +49 -49
- package/chunks/{list-agents-OSVDFI6S.js → list-agents-XO4EONWC.js} +6 -6
- package/chunks/{loadedSettingsAdapter-SJ2MJF35.js → loadedSettingsAdapter-X7FC5332.js} +46 -46
- package/chunks/{loggingContentGenerator-GR2QQ2C5.js → loggingContentGenerator-5G4ZR5D5.js} +22 -22
- package/chunks/{loop-wakeup-HWVUU5CF.js → loop-wakeup-HWSTFUTQ.js} +6 -6
- package/chunks/{ls-D3HUFHDP.js → ls-52HUW4B6.js} +5 -5
- package/chunks/{lsp-3QDDJTCS.js → lsp-VJESYEC6.js} +3 -3
- package/chunks/{managed-npm-update-ADQJHKTO.js → managed-npm-update-ZR2T2ST3.js} +41 -41
- package/chunks/{mcp-QW3OTL5W.js → mcp-TZNHG7CF.js} +46 -46
- package/chunks/{monitor-RJKPVERH.js → monitor-TN6Z4SXF.js} +40 -40
- package/chunks/{nonInteractiveCli-MROMHSTL.js → nonInteractiveCli-I7K6KH5U.js} +81 -80
- package/chunks/{notebook-edit-2ENWDBZO.js → notebook-edit-77V2IP3Y.js} +40 -40
- package/chunks/{openaiContentGenerator-Z3GPWJU4.js → openaiContentGenerator-2S2UT4RR.js} +25 -26
- package/chunks/{pidfile-5G42YSTP.js → pidfile-WDSDXBY3.js} +41 -41
- package/chunks/{processUtils-ZDMXYKQY.js → processUtils-JOJNZOW4.js} +2 -2
- package/chunks/prompt-terminal-ledger-RW62JIPP.js +93 -0
- package/chunks/{qwenContentGenerator-NLEMBZVU.js → qwenContentGenerator-G3H2TCXF.js} +45 -45
- package/chunks/{qwenOAuth2-EBV52DWJ.js → qwenOAuth2-UI2OC2RN.js} +10 -10
- package/chunks/{read-file-5BYIF53O.js → read-file-DI64TNOE.js} +13 -14
- package/chunks/{read-mcp-resource-XD54ZQMC.js → read-mcp-resource-6VFF47Z3.js} +3 -3
- package/chunks/{record-artifact-GLU3UWBV.js → record-artifact-TJTN2GBV.js} +5 -5
- package/chunks/{resumeHistoryUtils-AFTBRS3G.js → resumeHistoryUtils-3FIDQ6YQ.js} +46 -46
- package/chunks/{ripGrep-NN7AOLQY.js → ripGrep-EUTGRCN3.js} +40 -40
- package/chunks/{run-qwen-serve-UR3DYDAF.js → run-qwen-serve-SQBF7QZM.js} +505 -161
- package/chunks/{runtime-PR5RKGNH.js → runtime-7QGB6SY4.js} +49 -49
- package/chunks/{scheduler-GPMLVKJM.js → scheduler-V6AZCQVU.js} +42 -42
- package/chunks/{sdk-exporters-grpc-54L4LS5L.js → sdk-exporters-grpc-P3LA24AV.js} +3 -3
- package/chunks/{sdk-exporters-http-NC746HLT.js → sdk-exporters-http-K3LH2SD7.js} +9 -11
- package/chunks/{sdk-impl-YVL7BP6Y.js → sdk-impl-WCUNMLVX.js} +11 -6
- package/chunks/{send-message-TNBG5EVA.js → send-message-NUK5DTTI.js} +7 -7
- package/chunks/{serve-E7V2JVA2.js → serve-WVNAO2NA.js} +46 -46
- package/chunks/{server-YXB3DBN7.js → server-ZMZPHJEC.js} +992 -271
- package/chunks/{session-DZEAUT7S.js → session-JV74G6EZ.js} +82 -81
- package/chunks/{settings-ESZ3NWAP.js → settings-GBBVKBQ2.js} +45 -45
- package/chunks/{shell-JMSK5WIL.js → shell-JNNRUZPA.js} +40 -40
- package/chunks/{skill-5K5CSUJV.js → skill-JRGRCWD5.js} +18 -18
- package/chunks/{skill-settings-V64NIOTI.js → skill-settings-VEC7C44Z.js} +45 -45
- package/chunks/{spawnChannel-S63APBZZ.js → spawnChannel-TVKIFXXA.js} +42 -42
- package/chunks/{standalone-update-P42HDFXX.js → standalone-update-OSHF2CX3.js} +42 -42
- package/chunks/{startInteractiveUI-LFBLFHJ4.js → startInteractiveUI-2HTUHVQO.js} +310 -156
- package/chunks/{syntheticOutput-7GWFIDXT.js → syntheticOutput-GZV6O6UL.js} +4 -4
- package/chunks/{task-create-EILHJJB7.js → task-create-BXGKNND4.js} +11 -11
- package/chunks/{task-list-WGJR6YL5.js → task-list-4ZMIDYGD.js} +6 -6
- package/chunks/{task-stop-X37KYTKB.js → task-stop-WBO7LWTS.js} +3 -3
- package/chunks/{task-update-XZAHVXJ5.js → task-update-UFO3BI7O.js} +11 -11
- package/chunks/{team-create-EDNOUM2U.js → team-create-DTPGJ6RH.js} +40 -40
- package/chunks/{team-delete-UEP4QOOT.js → team-delete-OCFJS444.js} +6 -6
- package/chunks/{team-plan-approval-QRSNK2DX.js → team-plan-approval-4433RWHB.js} +40 -40
- package/chunks/{terminal-image-renderer-6J2NPL32.js → terminal-image-renderer-QZLIKIVA.js} +42 -42
- package/chunks/{theme-manager-WJMLRBXS.js → theme-manager-RM7C7Q3L.js} +41 -41
- package/chunks/{todoWrite-ATS62CAP.js → todoWrite-BGM5MCPY.js} +5 -5
- package/chunks/{tool-search-MZ6WU7DM.js → tool-search-4NQJASFC.js} +17 -18
- package/chunks/{total-session-admission-DQVW2LIP.js → total-session-admission-NZNCU5NU.js} +46 -45
- package/chunks/{trustedFolders-QMH25GOX.js → trustedFolders-FDJ2Q4ZK.js} +41 -41
- package/chunks/{update-relaunch-EG75LLW5.js → update-relaunch-HZMDPRTF.js} +5 -5
- package/chunks/{updateCheck-MTZIVGT5.js → updateCheck-ZB2CRVVG.js} +43 -43
- package/chunks/{useAutoAcceptIndicator-IGCW5EPO.js → useAutoAcceptIndicator-O3JI4KTR.js} +48 -48
- package/chunks/{validateNonInterActiveAuth-D5FPAB2C.js → validateNonInterActiveAuth-7Z4KG4N5.js} +78 -77
- package/chunks/{version-UOLDLLRB.js → version-RFVS6QDY.js} +1 -1
- package/chunks/{web-fetch-QKKW6CWH.js → web-fetch-RAN377BH.js} +17 -18
- package/chunks/{web-search-JYRBZMCW.js → web-search-XKS6ZPY7.js} +10 -10
- package/chunks/{workflow-SR7SEAU7.js → workflow-HF6G5XNX.js} +232 -73
- package/chunks/{workspace-providers-status-OXGV4EFF.js → workspace-providers-status-LNMP7NED.js} +49 -49
- package/chunks/{workspace-registration-store-V5EGKLBH.js → workspace-registration-store-QZ3P3ILN.js} +1 -1
- package/chunks/{workspace-registry-KJVIYTF5.js → workspace-registry-KWPGC2LG.js} +46 -45
- package/chunks/{workspace-service-6RLSGUB5.js → workspace-service-RWB4KMY3.js} +51 -51
- package/chunks/{workspace-skills-status-BHFEPDGH.js → workspace-skills-status-P3XXZY7C.js} +47 -47
- package/chunks/{workspace-trust-reconciler-DB5ERSUN.js → workspace-trust-reconciler-XU6WB2MF.js} +52 -51
- package/chunks/{write-file-IUP4GTZ4.js → write-file-V7Y6KUPR.js} +40 -40
- package/chunks/{zoom-image-SRBDTIVA.js → zoom-image-N4RSASH7.js} +13 -14
- package/cli.js +13 -13
- package/package.json +3 -3
- package/web-shell/assets/{arc-DItbX0DI.js → arc-CN-xeqBM.js} +1 -1
- package/web-shell/assets/{architectureDiagram-3BPJPVTR-CmnIlH8y.js → architectureDiagram-3BPJPVTR-XQJ6hBnv.js} +1 -1
- package/web-shell/assets/{blockDiagram-GPEHLZMM-pObnB9kw.js → blockDiagram-GPEHLZMM-n35AKogw.js} +1 -1
- package/web-shell/assets/{c4Diagram-AAUBKEIU-BNBmMS0Y.js → c4Diagram-AAUBKEIU-DXeDVokb.js} +1 -1
- package/web-shell/assets/channel-BdTBh3qf.js +1 -0
- package/web-shell/assets/{chunk-2J33WTMH-Dz4JBOO6.js → chunk-2J33WTMH-BYcmYjz_.js} +1 -1
- package/web-shell/assets/{chunk-4BX2VUAB-Cz2GnvAR.js → chunk-4BX2VUAB-w3UyeGtt.js} +1 -1
- package/web-shell/assets/{chunk-55IACEB6-CC6kOQYx.js → chunk-55IACEB6-Td3JbOH_.js} +1 -1
- package/web-shell/assets/{chunk-727SXJPM-Z4lY4gbh.js → chunk-727SXJPM-gC_NR7u6.js} +1 -1
- package/web-shell/assets/{chunk-AQP2D5EJ-Yz0hZr3D.js → chunk-AQP2D5EJ-aD7bI3c3.js} +1 -1
- package/web-shell/assets/{chunk-FMBD7UC4-nKmTWTv9.js → chunk-FMBD7UC4-sHMhD16X.js} +1 -1
- package/web-shell/assets/{chunk-ND2GUHAM-CjZz0f6Y.js → chunk-ND2GUHAM-DiV49BLl.js} +1 -1
- package/web-shell/assets/{chunk-QZHKN3VN-Bab3FpuS.js → chunk-QZHKN3VN-Dnoagqin.js} +1 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-qVxLMMuK.js +1 -0
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-qVxLMMuK.js +1 -0
- package/web-shell/assets/{cose-bilkent-S5V4N54A-BuSAGFox.js → cose-bilkent-S5V4N54A-K6l_zsrZ.js} +1 -1
- package/web-shell/assets/{dagre-BM42HDAG-CRZXTg3g.js → dagre-BM42HDAG-Chh9hQ0a.js} +1 -1
- package/web-shell/assets/{diagram-2AECGRRQ-BFx1Ayrz.js → diagram-2AECGRRQ-Clrbd8SB.js} +1 -1
- package/web-shell/assets/{diagram-5GNKFQAL-B2hMZ3gS.js → diagram-5GNKFQAL-BkNExywD.js} +1 -1
- package/web-shell/assets/{diagram-KO2AKTUF-DKxAQLmc.js → diagram-KO2AKTUF-kTX14ngI.js} +1 -1
- package/web-shell/assets/{diagram-LMA3HP47-Bo1xGqVY.js → diagram-LMA3HP47-Ba1QOCJy.js} +1 -1
- package/web-shell/assets/{diagram-OG6HWLK6-B9NG78d-.js → diagram-OG6HWLK6-CtH5BVYm.js} +1 -1
- package/web-shell/assets/{erDiagram-TEJ5UH35-DltQKiqQ.js → erDiagram-TEJ5UH35-DCxSIC83.js} +1 -1
- package/web-shell/assets/{flowDiagram-I6XJVG4X-5xXGmS4I.js → flowDiagram-I6XJVG4X-C4rNAypQ.js} +1 -1
- package/web-shell/assets/{ganttDiagram-6RSMTGT7-bhGL5n0l.js → ganttDiagram-6RSMTGT7-s3P5tBwL.js} +1 -1
- package/web-shell/assets/{gitGraphDiagram-PVQCEYII-ZYnz9hgh.js → gitGraphDiagram-PVQCEYII-C7Eg-1ok.js} +1 -1
- package/web-shell/assets/index-BXoIYIJg.css +5 -0
- package/web-shell/assets/{index-CBBeUArD.js → index-CszoC8cN.js} +1 -1
- package/web-shell/assets/index-Dxj7Naa0.js +1788 -0
- package/web-shell/assets/{infoDiagram-5YYISTIA-Cg-jamQf.js → infoDiagram-5YYISTIA-BDKsgMt6.js} +1 -1
- package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-CcmvKlyq.js → ishikawaDiagram-YF4QCWOH-CkcSHbvL.js} +1 -1
- package/web-shell/assets/{journeyDiagram-JHISSGLW-BRsOQZp1.js → journeyDiagram-JHISSGLW-CDWt-t81.js} +1 -1
- package/web-shell/assets/{kanban-definition-UN3LZRKU-xW-dmEHK.js → kanban-definition-UN3LZRKU-FI2owcEa.js} +1 -1
- package/web-shell/assets/{linear-ClBfEZH2.js → linear-BQzLqkJi.js} +1 -1
- package/web-shell/assets/{mermaid.core-D65NDkzc.js → mermaid.core-CvV91DP1.js} +5 -5
- package/web-shell/assets/{mindmap-definition-RKZ34NQL-CyvFslYa.js → mindmap-definition-RKZ34NQL-Dx2kLUpN.js} +1 -1
- package/web-shell/assets/{pieDiagram-4H26LBE5-BwSefMyG.js → pieDiagram-4H26LBE5-CMXOmBrj.js} +1 -1
- package/web-shell/assets/{quadrantDiagram-W4KKPZXB-GqBJspFS.js → quadrantDiagram-W4KKPZXB-Bziww7Co.js} +1 -1
- package/web-shell/assets/{requirementDiagram-4Y6WPE33-B137PlTJ.js → requirementDiagram-4Y6WPE33-DMOXAxzp.js} +1 -1
- package/web-shell/assets/{sankeyDiagram-5OEKKPKP-maHkkt8i.js → sankeyDiagram-5OEKKPKP-B3y1cfVV.js} +1 -1
- package/web-shell/assets/{sequenceDiagram-3UESZ5HK-DJ1mRaG3.js → sequenceDiagram-3UESZ5HK-ChrV1jiM.js} +1 -1
- package/web-shell/assets/{stateDiagram-AJRCARHV-aRmP7Q4i.js → stateDiagram-AJRCARHV-CWuLzLFE.js} +1 -1
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-DEDPMLgq.js +1 -0
- package/web-shell/assets/{timeline-definition-PNZ67QCA-CIQ3BRPA.js → timeline-definition-PNZ67QCA-Cl6am_to.js} +1 -1
- package/web-shell/assets/{vennDiagram-CIIHVFJN-DR9VPd5h.js → vennDiagram-CIIHVFJN-OuocxGAu.js} +1 -1
- package/web-shell/assets/{wardley-L42UT6IY-ZcfIbT4D.js → wardley-L42UT6IY-DLYdvSJW.js} +1 -1
- package/web-shell/assets/{wardleyDiagram-YWT4CUSO-D0jgPi4T.js → wardleyDiagram-YWT4CUSO-7a3DreXX.js} +1 -1
- package/web-shell/assets/{xychartDiagram-2RQKCTM6-BGWU4s5o.js → xychartDiagram-2RQKCTM6-CgfjUxW_.js} +1 -1
- package/web-shell/index.html +2 -2
- package/chunks/chunk-D34RDOLP.js +0 -529
- package/chunks/daemon-status-provider-SXS66ZIR.js +0 -103
- package/web-shell/assets/channel-hZnMfWA9.js +0 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-BRnxm8DX.js +0 -1
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-BRnxm8DX.js +0 -1
- package/web-shell/assets/index-CbgU-jUo.css +0 -5
- package/web-shell/assets/index-_nhzXqab.js +0 -1750
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-Db39gvZ_.js +0 -1
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
} from "./chunk-OCPBI7J5.js";
|
|
20
20
|
import {
|
|
21
21
|
defaultSpawnChannelFactory
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-V4UBYT3Y.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-AQFWV4YF.js";
|
|
33
33
|
import {
|
|
34
34
|
ACTIVE_WORK_CLOSE_IF_UNHELD_PARAM,
|
|
35
35
|
ACTIVE_WORK_CLOSE_TIMEOUT_MS,
|
|
@@ -44,8 +44,8 @@ import {
|
|
|
44
44
|
CHANNEL_PROMPT_META_KEY,
|
|
45
45
|
CHANNEL_STARTUP_PROFILE_META_KEY,
|
|
46
46
|
CHANNEL_STARTUP_PROFILE_VERSION,
|
|
47
|
+
DAEMON_ATTACHMENT_REFERENCES_META_KEY,
|
|
47
48
|
DAEMON_CHANNEL_DELIVERY_META_KEY,
|
|
48
|
-
DAEMON_MEDIA_REFERENCES_META_KEY,
|
|
49
49
|
DAEMON_MODEL_PROMPT_META_KEY,
|
|
50
50
|
DAEMON_PROMPT_DISPLAY_TEXT_META_KEY,
|
|
51
51
|
LOAD_REPLAY_BULK_MODE,
|
|
@@ -65,7 +65,7 @@ import {
|
|
|
65
65
|
clampActiveWorkIntervalMs,
|
|
66
66
|
isValidTrustedModelPrompt,
|
|
67
67
|
sessionCloseDrainBudgetMs
|
|
68
|
-
} from "./chunk-
|
|
68
|
+
} from "./chunk-QQUVPMMZ.js";
|
|
69
69
|
import {
|
|
70
70
|
BranchWhilePromptActiveError,
|
|
71
71
|
BridgeChannelQuarantinedError,
|
|
@@ -97,9 +97,8 @@ import {
|
|
|
97
97
|
LIVE_TASK_TOOL_NAMES,
|
|
98
98
|
MAX_LIVE_SCREEN_CONTEXT_TEXT_CHARS,
|
|
99
99
|
MAX_LIVE_SPEAK_TO_USER_MESSAGE_CHARS,
|
|
100
|
-
MAX_SUB_SESSION_NAME_CHARS
|
|
101
|
-
|
|
102
|
-
} from "./chunk-HIBNSEJE.js";
|
|
100
|
+
MAX_SUB_SESSION_NAME_CHARS
|
|
101
|
+
} from "./chunk-UDG5EZJI.js";
|
|
103
102
|
import {
|
|
104
103
|
EXTERNAL_TOOL_GUARD_READY_META_KEY,
|
|
105
104
|
EXTERNAL_TOOL_GUARD_REQUIRED_VALUE,
|
|
@@ -110,6 +109,9 @@ import {
|
|
|
110
109
|
PROTOCOL_VERSION,
|
|
111
110
|
RequestError
|
|
112
111
|
} from "./chunk-IW6RQPQB.js";
|
|
112
|
+
import {
|
|
113
|
+
MAX_SUB_SESSION_PROMPT_CHARS
|
|
114
|
+
} from "./chunk-LJZSMWOH.js";
|
|
113
115
|
import {
|
|
114
116
|
SESSION_ARTIFACT_PERSISTENCE_VERSION,
|
|
115
117
|
SESSION_TRANSCRIPT_MAX_LIMIT,
|
|
@@ -125,16 +127,19 @@ import {
|
|
|
125
127
|
normalizeSnapshotPayload,
|
|
126
128
|
normalizeTurnResultError,
|
|
127
129
|
stableSessionArtifactId
|
|
128
|
-
} from "./chunk-
|
|
130
|
+
} from "./chunk-L7RG5PVT.js";
|
|
129
131
|
import {
|
|
130
132
|
DAEMON_TRACEPARENT_META_KEY,
|
|
131
133
|
DAEMON_TRACESTATE_META_KEY
|
|
132
|
-
} from "./chunk-
|
|
134
|
+
} from "./chunk-7NLDU6J2.js";
|
|
133
135
|
import {
|
|
134
136
|
INVOCATION_CONTEXT_META_KEY,
|
|
135
137
|
PRIVATE_ACP_CAPABILITY_ENV,
|
|
136
138
|
PRIVATE_PARENT_CAPABILITY_META_KEY
|
|
137
|
-
} from "./chunk-
|
|
139
|
+
} from "./chunk-EXY6APEA.js";
|
|
140
|
+
import {
|
|
141
|
+
getSpecificMimeType
|
|
142
|
+
} from "./chunk-MGEWDLRO.js";
|
|
138
143
|
import {
|
|
139
144
|
init_esbuild_shims
|
|
140
145
|
} from "./chunk-5O2XNYP6.js";
|
|
@@ -144,7 +149,7 @@ import {
|
|
|
144
149
|
|
|
145
150
|
// packages/acp-bridge/src/bridge.ts
|
|
146
151
|
init_esbuild_shims();
|
|
147
|
-
import { randomBytes, randomUUID as
|
|
152
|
+
import { randomBytes, randomUUID as randomUUID2 } from "node:crypto";
|
|
148
153
|
import * as path4 from "node:path";
|
|
149
154
|
import { inspect } from "node:util";
|
|
150
155
|
|
|
@@ -1284,161 +1289,276 @@ function getChannelStartupProfileAttributes(response, receivedAtEpochMs, initial
|
|
|
1284
1289
|
}
|
|
1285
1290
|
__name(getChannelStartupProfileAttributes, "getChannelStartupProfileAttributes");
|
|
1286
1291
|
|
|
1287
|
-
// packages/acp-bridge/src/
|
|
1292
|
+
// packages/acp-bridge/src/sessionAttachments.ts
|
|
1288
1293
|
init_esbuild_shims();
|
|
1289
|
-
import {
|
|
1290
|
-
import { promises as fs } from "node:fs";
|
|
1294
|
+
import { promises as fs, statSync } from "node:fs";
|
|
1291
1295
|
import { tmpdir } from "node:os";
|
|
1292
1296
|
import * as path from "node:path";
|
|
1293
|
-
var
|
|
1294
|
-
var
|
|
1295
|
-
var
|
|
1296
|
-
|
|
1297
|
-
|
|
1297
|
+
var SESSION_ATTACHMENT_MAX_ITEM_BYTES = 8 * 1024 * 1024;
|
|
1298
|
+
var SESSION_ATTACHMENT_MAX_NAME_BYTES = 255;
|
|
1299
|
+
var SUPPORTED_IMAGE_MIME_TYPES = /* @__PURE__ */ new Set([
|
|
1300
|
+
"image/bmp",
|
|
1301
|
+
"image/gif",
|
|
1302
|
+
"image/jpeg",
|
|
1303
|
+
"image/png",
|
|
1304
|
+
"image/webp"
|
|
1305
|
+
]);
|
|
1306
|
+
var SESSION_ATTACHMENT_UNAVAILABLE_TEXT = "[Attachment is no longer available]";
|
|
1307
|
+
var SessionAttachmentReferenceError = class extends Error {
|
|
1298
1308
|
constructor(message, code) {
|
|
1299
1309
|
super(message);
|
|
1300
1310
|
this.code = code;
|
|
1301
|
-
this.name = "
|
|
1311
|
+
this.name = "SessionAttachmentReferenceError";
|
|
1302
1312
|
}
|
|
1303
1313
|
static {
|
|
1304
|
-
__name(this, "
|
|
1314
|
+
__name(this, "SessionAttachmentReferenceError");
|
|
1305
1315
|
}
|
|
1306
1316
|
};
|
|
1307
|
-
function
|
|
1317
|
+
function isSessionAttachmentReference(value) {
|
|
1308
1318
|
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
1309
1319
|
const record = value;
|
|
1310
|
-
return record["type"] === "image" && typeof record["
|
|
1320
|
+
return (record["type"] === "image" || record["type"] === "resource") && typeof record["attachmentId"] === "string" && record["attachmentId"].length > 0 && typeof record["mimeType"] === "string" && record["mimeType"].length > 0 && (record["type"] !== "image" || record["mimeType"].startsWith("image/")) && typeof record["size"] === "number" && Number.isSafeInteger(record["size"]) && record["size"] >= 0 && (record["type"] !== "image" || record["size"] > 0);
|
|
1321
|
+
}
|
|
1322
|
+
__name(isSessionAttachmentReference, "isSessionAttachmentReference");
|
|
1323
|
+
function safeAttachmentName(name) {
|
|
1324
|
+
const safeName = path.basename(name.replaceAll("\\", "/")).trim();
|
|
1325
|
+
const isWindowsReserved = /^(?:con|prn|aux|nul|com[1-9]|lpt[1-9])(?:\.|$)/i.test(safeName);
|
|
1326
|
+
const hasInvalidCharacter = Array.from(safeName).some((character) => {
|
|
1327
|
+
const codePoint = character.codePointAt(0);
|
|
1328
|
+
return codePoint !== void 0 && (codePoint <= 31 || codePoint === 127 || codePoint >= 55296 && codePoint <= 57343);
|
|
1329
|
+
});
|
|
1330
|
+
return !safeName || safeName === "." || safeName === ".." || safeName.endsWith(".") || isWindowsReserved || /[<>:"|?*]/.test(safeName) || hasInvalidCharacter || Buffer.byteLength(safeName) > SESSION_ATTACHMENT_MAX_NAME_BYTES ? void 0 : safeName;
|
|
1331
|
+
}
|
|
1332
|
+
__name(safeAttachmentName, "safeAttachmentName");
|
|
1333
|
+
function truncateUtf8(value, maxBytes) {
|
|
1334
|
+
let bytes = 0;
|
|
1335
|
+
let result = "";
|
|
1336
|
+
for (const character of value) {
|
|
1337
|
+
const characterBytes = Buffer.byteLength(character);
|
|
1338
|
+
if (bytes + characterBytes > maxBytes) break;
|
|
1339
|
+
result += character;
|
|
1340
|
+
bytes += characterBytes;
|
|
1341
|
+
}
|
|
1342
|
+
return result;
|
|
1343
|
+
}
|
|
1344
|
+
__name(truncateUtf8, "truncateUtf8");
|
|
1345
|
+
function deduplicatedName(name, suffix) {
|
|
1346
|
+
if (suffix === 0) return name;
|
|
1347
|
+
const extension = path.extname(name);
|
|
1348
|
+
const suffixText = ` (${suffix})`;
|
|
1349
|
+
const stem = name.slice(0, -extension.length || void 0);
|
|
1350
|
+
const extensionBudget = SESSION_ATTACHMENT_MAX_NAME_BYTES - Buffer.byteLength(suffixText) - 1;
|
|
1351
|
+
const safeExtension = truncateUtf8(extension, extensionBudget).replace(
|
|
1352
|
+
/[. ]+$/u,
|
|
1353
|
+
""
|
|
1354
|
+
);
|
|
1355
|
+
const stemBudget = SESSION_ATTACHMENT_MAX_NAME_BYTES - Buffer.byteLength(suffixText) - Buffer.byteLength(safeExtension);
|
|
1356
|
+
return `${truncateUtf8(stem, stemBudget)}${suffixText}${safeExtension}`;
|
|
1357
|
+
}
|
|
1358
|
+
__name(deduplicatedName, "deduplicatedName");
|
|
1359
|
+
function imageName(mimeType) {
|
|
1360
|
+
const extension = mimeType.slice("image/".length).split(/[;+]/, 1)[0];
|
|
1361
|
+
return `image.${extension === "jpg" ? "jpeg" : extension || "img"}`;
|
|
1362
|
+
}
|
|
1363
|
+
__name(imageName, "imageName");
|
|
1364
|
+
function mimeTypeForName(name) {
|
|
1365
|
+
if ([".ts", ".mts", ".cts", ".tsx"].includes(path.extname(name).toLowerCase())) {
|
|
1366
|
+
return "text/plain";
|
|
1367
|
+
}
|
|
1368
|
+
return getSpecificMimeType(name) ?? "application/octet-stream";
|
|
1369
|
+
}
|
|
1370
|
+
__name(mimeTypeForName, "mimeTypeForName");
|
|
1371
|
+
function isSupportedImageMimeType(mimeType) {
|
|
1372
|
+
return SUPPORTED_IMAGE_MIME_TYPES.has(mimeType);
|
|
1311
1373
|
}
|
|
1312
|
-
__name(
|
|
1313
|
-
function
|
|
1374
|
+
__name(isSupportedImageMimeType, "isSupportedImageMimeType");
|
|
1375
|
+
function isTextMimeType(mimeType) {
|
|
1376
|
+
return mimeType.startsWith("text/") || mimeType === "application/json" || mimeType.endsWith("+json") || mimeType === "application/xml" || mimeType.endsWith("+xml") || mimeType === "application/javascript" || mimeType === "application/typescript" || mimeType === "application/yaml" || mimeType === "application/x-yaml" || mimeType === "application/toml";
|
|
1377
|
+
}
|
|
1378
|
+
__name(isTextMimeType, "isTextMimeType");
|
|
1379
|
+
function isTextAttachment(data, mimeType) {
|
|
1380
|
+
if (isTextMimeType(mimeType)) return true;
|
|
1381
|
+
if (mimeType.startsWith("image/") || mimeType.startsWith("audio/") || mimeType.startsWith("video/") || mimeType.startsWith("font/") || mimeType === "application/pdf" || data.includes(0)) {
|
|
1382
|
+
return false;
|
|
1383
|
+
}
|
|
1384
|
+
return Buffer.from(data.toString("utf8"), "utf8").equals(data);
|
|
1385
|
+
}
|
|
1386
|
+
__name(isTextAttachment, "isTextAttachment");
|
|
1387
|
+
function withAttachmentDegradationMarker(blocks) {
|
|
1314
1388
|
for (let i = blocks.length - 1; i >= 0; i--) {
|
|
1315
1389
|
const block = blocks[i];
|
|
1316
1390
|
if (block.type === "text") {
|
|
1317
|
-
if (block.text.endsWith(
|
|
1391
|
+
if (block.text.endsWith(SESSION_ATTACHMENT_UNAVAILABLE_TEXT)) {
|
|
1318
1392
|
return [...blocks];
|
|
1319
1393
|
}
|
|
1320
1394
|
const next = [...blocks];
|
|
1321
1395
|
next[i] = {
|
|
1322
1396
|
type: "text",
|
|
1323
1397
|
text: `${block.text}
|
|
1324
|
-
${
|
|
1398
|
+
${SESSION_ATTACHMENT_UNAVAILABLE_TEXT}`
|
|
1325
1399
|
};
|
|
1326
1400
|
return next;
|
|
1327
1401
|
}
|
|
1328
1402
|
}
|
|
1329
1403
|
return [
|
|
1330
1404
|
...blocks,
|
|
1331
|
-
{ type: "text", text:
|
|
1405
|
+
{ type: "text", text: SESSION_ATTACHMENT_UNAVAILABLE_TEXT }
|
|
1332
1406
|
];
|
|
1333
1407
|
}
|
|
1334
|
-
__name(
|
|
1335
|
-
var
|
|
1408
|
+
__name(withAttachmentDegradationMarker, "withAttachmentDegradationMarker");
|
|
1409
|
+
var SessionAttachmentStore = class {
|
|
1410
|
+
constructor(directoryRoot, sessionId) {
|
|
1411
|
+
this.directoryRoot = directoryRoot;
|
|
1412
|
+
if (!directoryRoot || !sessionId) return;
|
|
1413
|
+
this.persistentDirectory = path.join(
|
|
1414
|
+
directoryRoot,
|
|
1415
|
+
`session-${encodeURIComponent(sessionId)}`
|
|
1416
|
+
);
|
|
1417
|
+
}
|
|
1336
1418
|
static {
|
|
1337
|
-
__name(this, "
|
|
1419
|
+
__name(this, "SessionAttachmentStore");
|
|
1338
1420
|
}
|
|
1339
|
-
records = /* @__PURE__ */ new Map();
|
|
1340
1421
|
directoryPromise;
|
|
1341
|
-
|
|
1422
|
+
persistentDirectory;
|
|
1423
|
+
activeDirectory;
|
|
1342
1424
|
pendingItems = 0;
|
|
1425
|
+
pendingNames = /* @__PURE__ */ new Map();
|
|
1426
|
+
pendingDrainWaiters = [];
|
|
1427
|
+
copyDrainWaiters = [];
|
|
1428
|
+
copying = false;
|
|
1429
|
+
closing = false;
|
|
1343
1430
|
closed = false;
|
|
1344
|
-
async
|
|
1345
|
-
|
|
1346
|
-
const
|
|
1347
|
-
|
|
1348
|
-
|
|
1431
|
+
async putAttachment(data, mimeType, name) {
|
|
1432
|
+
const isImage = isSupportedImageMimeType(mimeType);
|
|
1433
|
+
const safeName = safeAttachmentName(
|
|
1434
|
+
name ?? (isImage ? imageName(mimeType) : "")
|
|
1435
|
+
);
|
|
1436
|
+
if (!safeName) {
|
|
1437
|
+
throw new TypeError("Session attachment name is invalid");
|
|
1349
1438
|
}
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
);
|
|
1439
|
+
const storedMimeType = mimeTypeForName(safeName);
|
|
1440
|
+
if (isImage && storedMimeType !== mimeType || isSupportedImageMimeType(storedMimeType) && !isImage) {
|
|
1441
|
+
throw new TypeError("Attachment name and Content-Type do not match");
|
|
1354
1442
|
}
|
|
1355
|
-
if (this.
|
|
1356
|
-
throw new
|
|
1357
|
-
`Session media exceeds the ${SESSION_MEDIA_MAX_TOTAL_BYTES}-byte session limit`
|
|
1358
|
-
);
|
|
1443
|
+
if (this.closed || this.closing) {
|
|
1444
|
+
throw new Error("Session attachment store is closed");
|
|
1359
1445
|
}
|
|
1360
|
-
if (this.
|
|
1446
|
+
if (this.copying) throw new Error("Session attachments are being copied");
|
|
1447
|
+
if (isImage && data.byteLength === 0 || data.byteLength > SESSION_ATTACHMENT_MAX_ITEM_BYTES) {
|
|
1361
1448
|
throw new RangeError(
|
|
1362
|
-
`Session
|
|
1449
|
+
`Session attachment must be at most ${SESSION_ATTACHMENT_MAX_ITEM_BYTES} bytes and images cannot be empty`
|
|
1363
1450
|
);
|
|
1364
1451
|
}
|
|
1365
|
-
const mediaId = randomUUID();
|
|
1366
1452
|
let filePath;
|
|
1367
|
-
|
|
1453
|
+
let pendingName = safeName;
|
|
1454
|
+
let removeFileOnFailure = false;
|
|
1368
1455
|
this.pendingItems += 1;
|
|
1456
|
+
this.reservePendingName(safeName);
|
|
1369
1457
|
try {
|
|
1370
1458
|
const directory = await this.directory();
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1459
|
+
let suffix = 0;
|
|
1460
|
+
for (; ; ) {
|
|
1461
|
+
const candidateName = deduplicatedName(safeName, suffix);
|
|
1462
|
+
if (safeAttachmentName(candidateName) !== candidateName) {
|
|
1463
|
+
throw new TypeError("Session attachment name is invalid");
|
|
1464
|
+
}
|
|
1465
|
+
if (pendingName !== candidateName) {
|
|
1466
|
+
if (pendingName) this.releasePendingName(pendingName);
|
|
1467
|
+
this.reservePendingName(candidateName);
|
|
1468
|
+
pendingName = candidateName;
|
|
1469
|
+
}
|
|
1470
|
+
filePath = path.join(directory, candidateName);
|
|
1471
|
+
removeFileOnFailure = true;
|
|
1472
|
+
try {
|
|
1473
|
+
await fs.writeFile(filePath, data, { flag: "wx" });
|
|
1474
|
+
break;
|
|
1475
|
+
} catch (error) {
|
|
1476
|
+
if (error.code !== "EEXIST") throw error;
|
|
1477
|
+
removeFileOnFailure = false;
|
|
1478
|
+
this.releasePendingName(candidateName);
|
|
1479
|
+
pendingName = void 0;
|
|
1480
|
+
filePath = void 0;
|
|
1481
|
+
suffix += 1;
|
|
1482
|
+
}
|
|
1483
|
+
}
|
|
1484
|
+
if (this.closed || this.closing) {
|
|
1485
|
+
throw new Error("Session attachment store is closed");
|
|
1486
|
+
}
|
|
1487
|
+
const name2 = path.basename(filePath);
|
|
1488
|
+
const storedMimeType2 = mimeTypeForName(name2);
|
|
1489
|
+
const reference = {
|
|
1490
|
+
type: isSupportedImageMimeType(storedMimeType2) ? "image" : "resource",
|
|
1491
|
+
attachmentId: name2,
|
|
1492
|
+
mimeType: storedMimeType2,
|
|
1493
|
+
size: data.byteLength
|
|
1382
1494
|
};
|
|
1383
|
-
|
|
1384
|
-
return { type, mediaId, mimeType, size: data.byteLength };
|
|
1495
|
+
return reference;
|
|
1385
1496
|
} catch (error) {
|
|
1386
|
-
if (
|
|
1387
|
-
|
|
1388
|
-
|
|
1497
|
+
if (removeFileOnFailure && filePath) {
|
|
1498
|
+
await fs.rm(filePath, { force: true }).catch(() => {
|
|
1499
|
+
});
|
|
1500
|
+
}
|
|
1389
1501
|
throw error;
|
|
1390
1502
|
} finally {
|
|
1391
|
-
if (
|
|
1503
|
+
if (pendingName) this.releasePendingName(pendingName);
|
|
1504
|
+
if (!this.closed) {
|
|
1505
|
+
this.pendingItems -= 1;
|
|
1506
|
+
if (this.pendingItems === 0) {
|
|
1507
|
+
this.resolvePendingDrainWaiters();
|
|
1508
|
+
}
|
|
1509
|
+
}
|
|
1392
1510
|
}
|
|
1393
1511
|
}
|
|
1394
|
-
// Validate one block against the store.
|
|
1395
|
-
//
|
|
1512
|
+
// Validate one block against the store. Ordinary ACP content passes through
|
|
1513
|
+
// untouched, matching `assertReferences`.
|
|
1396
1514
|
assertReference(block) {
|
|
1397
|
-
if (!block || typeof block !== "object" || Array.isArray(block) || !("
|
|
1515
|
+
if (!block || typeof block !== "object" || Array.isArray(block) || !("attachmentId" in block)) {
|
|
1398
1516
|
return;
|
|
1399
1517
|
}
|
|
1400
|
-
if (!
|
|
1401
|
-
throw new
|
|
1402
|
-
"Invalid session
|
|
1403
|
-
"
|
|
1518
|
+
if (!isSessionAttachmentReference(block)) {
|
|
1519
|
+
throw new SessionAttachmentReferenceError(
|
|
1520
|
+
"Invalid session attachment reference",
|
|
1521
|
+
"invalid_session_attachment_reference"
|
|
1404
1522
|
);
|
|
1405
1523
|
}
|
|
1406
1524
|
this.assertStored(block);
|
|
1407
1525
|
}
|
|
1408
1526
|
assertReferences(content) {
|
|
1409
|
-
const
|
|
1527
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
1410
1528
|
for (const block of content) {
|
|
1411
|
-
if (!block || typeof block !== "object" || Array.isArray(block) || !("
|
|
1529
|
+
if (!block || typeof block !== "object" || Array.isArray(block) || !("attachmentId" in block)) {
|
|
1412
1530
|
continue;
|
|
1413
1531
|
}
|
|
1414
|
-
if (!
|
|
1415
|
-
throw new
|
|
1416
|
-
"Invalid session
|
|
1417
|
-
"
|
|
1532
|
+
if (!isSessionAttachmentReference(block)) {
|
|
1533
|
+
throw new SessionAttachmentReferenceError(
|
|
1534
|
+
"Invalid session attachment reference",
|
|
1535
|
+
"invalid_session_attachment_reference"
|
|
1418
1536
|
);
|
|
1419
1537
|
}
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1538
|
+
const id = block.attachmentId;
|
|
1539
|
+
if (seenIds.has(id)) {
|
|
1540
|
+
throw new SessionAttachmentReferenceError(
|
|
1541
|
+
`Session attachment referenced more than once: ${id}`,
|
|
1542
|
+
"invalid_session_attachment_reference"
|
|
1424
1543
|
);
|
|
1425
1544
|
}
|
|
1426
|
-
|
|
1545
|
+
seenIds.add(id);
|
|
1427
1546
|
this.assertStored(block);
|
|
1428
1547
|
}
|
|
1429
1548
|
}
|
|
1430
1549
|
async resolveContent(content, memo) {
|
|
1431
|
-
const
|
|
1550
|
+
const pendingById = memo ?? /* @__PURE__ */ new Map();
|
|
1432
1551
|
return await Promise.all(
|
|
1433
1552
|
content.map(async (block) => {
|
|
1434
|
-
if (!
|
|
1435
|
-
|
|
1553
|
+
if (!isSessionAttachmentReference(block)) return block;
|
|
1554
|
+
const id = block.attachmentId;
|
|
1555
|
+
let pending = pendingById.get(id);
|
|
1436
1556
|
if (!pending) {
|
|
1437
1557
|
const created = this.resolve(block);
|
|
1438
|
-
|
|
1558
|
+
pendingById.set(id, created);
|
|
1439
1559
|
void created.catch(() => {
|
|
1440
|
-
if (
|
|
1441
|
-
|
|
1560
|
+
if (pendingById.get(id) === created) {
|
|
1561
|
+
pendingById.delete(id);
|
|
1442
1562
|
}
|
|
1443
1563
|
});
|
|
1444
1564
|
pending = created;
|
|
@@ -1449,13 +1569,13 @@ var SessionMediaStore = class {
|
|
|
1449
1569
|
}
|
|
1450
1570
|
// Per-block variant of `resolveContent` for degrade paths: one unresolvable
|
|
1451
1571
|
// reference drops only itself, keeping the sibling blocks a wholesale
|
|
1452
|
-
// fallback would discard.
|
|
1572
|
+
// fallback would discard. Other errors still propagate.
|
|
1453
1573
|
async resolveContentDegrading(content, memo) {
|
|
1454
1574
|
const retainedBlocks = [];
|
|
1455
1575
|
const resolvedBlocks = [];
|
|
1456
1576
|
let degraded = 0;
|
|
1457
1577
|
for (const block of content) {
|
|
1458
|
-
if (!
|
|
1578
|
+
if (!isSessionAttachmentReference(block)) {
|
|
1459
1579
|
retainedBlocks.push(block);
|
|
1460
1580
|
resolvedBlocks.push(block);
|
|
1461
1581
|
continue;
|
|
@@ -1465,79 +1585,220 @@ var SessionMediaStore = class {
|
|
|
1465
1585
|
if (resolved) resolvedBlocks.push(resolved);
|
|
1466
1586
|
retainedBlocks.push(block);
|
|
1467
1587
|
} catch (error) {
|
|
1468
|
-
if (!(error instanceof
|
|
1588
|
+
if (!(error instanceof SessionAttachmentReferenceError)) throw error;
|
|
1469
1589
|
degraded += 1;
|
|
1470
1590
|
}
|
|
1471
1591
|
}
|
|
1472
1592
|
return { retainedBlocks, resolvedBlocks, degraded };
|
|
1473
1593
|
}
|
|
1474
|
-
async read(
|
|
1475
|
-
const
|
|
1476
|
-
if (!
|
|
1594
|
+
async read(attachmentId) {
|
|
1595
|
+
const name = safeAttachmentName(attachmentId);
|
|
1596
|
+
if (!name || name !== attachmentId) return void 0;
|
|
1597
|
+
const filePath = path.join(await this.directory(), name);
|
|
1477
1598
|
try {
|
|
1478
1599
|
return {
|
|
1479
|
-
data: await fs.readFile(
|
|
1480
|
-
mimeType:
|
|
1600
|
+
data: await fs.readFile(filePath),
|
|
1601
|
+
mimeType: mimeTypeForName(name)
|
|
1481
1602
|
};
|
|
1482
1603
|
} catch (error) {
|
|
1483
1604
|
if (error.code === "ENOENT") {
|
|
1484
|
-
if (this.records.delete(mediaId)) this.totalBytes -= record.size;
|
|
1485
1605
|
return void 0;
|
|
1486
1606
|
}
|
|
1487
1607
|
throw error;
|
|
1488
1608
|
}
|
|
1489
1609
|
}
|
|
1490
|
-
async
|
|
1491
|
-
|
|
1492
|
-
if (
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1610
|
+
async copyFrom(source) {
|
|
1611
|
+
if (source === this) return;
|
|
1612
|
+
if (this.closed || this.closing) {
|
|
1613
|
+
throw new Error("Session attachment store is closed");
|
|
1614
|
+
}
|
|
1615
|
+
if (this.copying) throw new Error("Session attachments are being copied");
|
|
1616
|
+
if (source.closed || source.closing) {
|
|
1617
|
+
throw new Error("Session attachment store is closed");
|
|
1618
|
+
}
|
|
1619
|
+
if (source.copying) {
|
|
1620
|
+
throw new Error("Session attachments are being copied");
|
|
1621
|
+
}
|
|
1622
|
+
this.copying = true;
|
|
1623
|
+
source.copying = true;
|
|
1624
|
+
try {
|
|
1625
|
+
if (this.pendingItems > 0) {
|
|
1626
|
+
await new Promise(
|
|
1627
|
+
(resolve2) => this.pendingDrainWaiters.push(resolve2)
|
|
1628
|
+
);
|
|
1629
|
+
}
|
|
1630
|
+
if (source.pendingItems > 0) {
|
|
1631
|
+
await new Promise(
|
|
1632
|
+
(resolve2) => source.pendingDrainWaiters.push(resolve2)
|
|
1633
|
+
);
|
|
1634
|
+
}
|
|
1635
|
+
if (this.closed) throw new Error("Session attachment store is closed");
|
|
1636
|
+
const sourceDirectory = source.persistentDirectory ?? source.activeDirectory;
|
|
1637
|
+
if (!sourceDirectory) return;
|
|
1638
|
+
let entries;
|
|
1639
|
+
try {
|
|
1640
|
+
entries = await fs.readdir(sourceDirectory, { withFileTypes: true });
|
|
1641
|
+
} catch (error) {
|
|
1642
|
+
if (error.code === "ENOENT") return;
|
|
1643
|
+
throw error;
|
|
1644
|
+
}
|
|
1645
|
+
const targetDirectory = await this.directory();
|
|
1646
|
+
await Promise.all(
|
|
1647
|
+
entries.filter(
|
|
1648
|
+
(entry) => entry.isFile() && !source.pendingNames.has(entry.name)
|
|
1649
|
+
).map(async (entry) => {
|
|
1650
|
+
const sourcePath = path.join(sourceDirectory, entry.name);
|
|
1651
|
+
try {
|
|
1652
|
+
await fs.copyFile(
|
|
1653
|
+
sourcePath,
|
|
1654
|
+
path.join(targetDirectory, entry.name)
|
|
1655
|
+
);
|
|
1656
|
+
} catch (error) {
|
|
1657
|
+
if (error.code === "ENOENT") {
|
|
1658
|
+
try {
|
|
1659
|
+
await fs.stat(sourcePath);
|
|
1660
|
+
} catch (sourceError) {
|
|
1661
|
+
if (sourceError.code === "ENOENT") {
|
|
1662
|
+
return;
|
|
1663
|
+
}
|
|
1664
|
+
}
|
|
1665
|
+
}
|
|
1666
|
+
throw error;
|
|
1667
|
+
}
|
|
1668
|
+
})
|
|
1669
|
+
);
|
|
1670
|
+
} finally {
|
|
1671
|
+
source.copying = false;
|
|
1672
|
+
this.copying = false;
|
|
1673
|
+
source.resolveCopyDrainWaiters();
|
|
1674
|
+
this.resolveCopyDrainWaiters();
|
|
1675
|
+
}
|
|
1497
1676
|
}
|
|
1498
|
-
|
|
1499
|
-
|
|
1677
|
+
async remove(attachmentId) {
|
|
1678
|
+
const name = safeAttachmentName(attachmentId);
|
|
1679
|
+
if (!name || name !== attachmentId || this.copying || this.pendingNames.has(name)) {
|
|
1680
|
+
return false;
|
|
1681
|
+
}
|
|
1682
|
+
const directory = await this.directory();
|
|
1683
|
+
const filePath = path.join(directory, name);
|
|
1684
|
+
try {
|
|
1685
|
+
await fs.unlink(filePath);
|
|
1686
|
+
return true;
|
|
1687
|
+
} catch (error) {
|
|
1688
|
+
if (error.code === "ENOENT") {
|
|
1689
|
+
return false;
|
|
1690
|
+
}
|
|
1691
|
+
throw error;
|
|
1692
|
+
}
|
|
1500
1693
|
}
|
|
1501
1694
|
async close() {
|
|
1695
|
+
this.closing = true;
|
|
1696
|
+
await this.waitForCopy();
|
|
1502
1697
|
if (this.closed) return;
|
|
1503
1698
|
this.closed = true;
|
|
1504
|
-
this.records.clear();
|
|
1505
|
-
this.totalBytes = 0;
|
|
1506
1699
|
this.pendingItems = 0;
|
|
1507
|
-
|
|
1700
|
+
this.pendingNames.clear();
|
|
1701
|
+
this.resolvePendingDrainWaiters();
|
|
1702
|
+
if (this.persistentDirectory || !this.directoryPromise) return;
|
|
1508
1703
|
const directory = await this.directoryPromise.catch(() => void 0);
|
|
1509
1704
|
if (!directory) return;
|
|
1510
1705
|
await fs.rm(directory, { recursive: true, force: true });
|
|
1511
1706
|
}
|
|
1707
|
+
async delete() {
|
|
1708
|
+
this.closing = true;
|
|
1709
|
+
await this.waitForCopy();
|
|
1710
|
+
if (!this.closed) {
|
|
1711
|
+
this.closed = true;
|
|
1712
|
+
this.pendingItems = 0;
|
|
1713
|
+
this.pendingNames.clear();
|
|
1714
|
+
this.resolvePendingDrainWaiters();
|
|
1715
|
+
}
|
|
1716
|
+
const directory = this.persistentDirectory ?? await this.directoryPromise?.catch(() => void 0);
|
|
1717
|
+
if (directory) await fs.rm(directory, { recursive: true, force: true });
|
|
1718
|
+
}
|
|
1512
1719
|
assertStored(reference) {
|
|
1513
|
-
const
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1720
|
+
const id = reference.attachmentId;
|
|
1721
|
+
const name = safeAttachmentName(id);
|
|
1722
|
+
let size;
|
|
1723
|
+
const directory = this.persistentDirectory ?? this.activeDirectory;
|
|
1724
|
+
if (name && name === id && directory) {
|
|
1725
|
+
try {
|
|
1726
|
+
size = statSync(path.join(directory, name)).size;
|
|
1727
|
+
} catch {
|
|
1728
|
+
size = void 0;
|
|
1729
|
+
}
|
|
1730
|
+
}
|
|
1731
|
+
const storedMimeType = name ? mimeTypeForName(name) : void 0;
|
|
1732
|
+
const storedType = storedMimeType ? isSupportedImageMimeType(storedMimeType) ? "image" : "resource" : void 0;
|
|
1733
|
+
if (size !== reference.size || storedMimeType !== reference.mimeType || storedType !== reference.type) {
|
|
1734
|
+
throw new SessionAttachmentReferenceError(
|
|
1735
|
+
`Unknown or unavailable session attachment: ${id}`,
|
|
1736
|
+
"session_attachment_gone"
|
|
1518
1737
|
);
|
|
1519
1738
|
}
|
|
1520
1739
|
}
|
|
1740
|
+
releasePendingName(name) {
|
|
1741
|
+
const count = this.pendingNames.get(name) ?? 0;
|
|
1742
|
+
if (count <= 1) this.pendingNames.delete(name);
|
|
1743
|
+
else this.pendingNames.set(name, count - 1);
|
|
1744
|
+
}
|
|
1745
|
+
reservePendingName(name) {
|
|
1746
|
+
this.pendingNames.set(name, (this.pendingNames.get(name) ?? 0) + 1);
|
|
1747
|
+
}
|
|
1748
|
+
async waitForCopy() {
|
|
1749
|
+
while (this.copying) {
|
|
1750
|
+
await new Promise((resolve2) => this.copyDrainWaiters.push(resolve2));
|
|
1751
|
+
}
|
|
1752
|
+
}
|
|
1753
|
+
resolveCopyDrainWaiters() {
|
|
1754
|
+
for (const resolve2 of this.copyDrainWaiters.splice(0)) resolve2();
|
|
1755
|
+
}
|
|
1756
|
+
resolvePendingDrainWaiters() {
|
|
1757
|
+
for (const resolve2 of this.pendingDrainWaiters.splice(0)) resolve2();
|
|
1758
|
+
}
|
|
1521
1759
|
async resolve(reference) {
|
|
1522
|
-
const
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1760
|
+
const id = reference.attachmentId;
|
|
1761
|
+
const attachment = await this.read(id);
|
|
1762
|
+
if (!attachment) {
|
|
1763
|
+
throw new SessionAttachmentReferenceError(
|
|
1764
|
+
`Unknown or unavailable session attachment: ${id}`,
|
|
1765
|
+
"session_attachment_gone"
|
|
1766
|
+
);
|
|
1767
|
+
}
|
|
1768
|
+
if (reference.type === "resource") {
|
|
1769
|
+
const resource = {
|
|
1770
|
+
uri: `attachment:///${encodeURIComponent(reference.attachmentId)}`,
|
|
1771
|
+
mimeType: attachment.mimeType,
|
|
1772
|
+
...isTextAttachment(attachment.data, attachment.mimeType) ? { text: attachment.data.toString("utf8") } : { blob: attachment.data.toString("base64") }
|
|
1773
|
+
};
|
|
1774
|
+
return {
|
|
1775
|
+
type: "resource",
|
|
1776
|
+
resource
|
|
1777
|
+
};
|
|
1528
1778
|
}
|
|
1529
1779
|
return {
|
|
1530
|
-
type:
|
|
1531
|
-
data:
|
|
1532
|
-
mimeType:
|
|
1780
|
+
type: "image",
|
|
1781
|
+
data: attachment.data.toString("base64"),
|
|
1782
|
+
mimeType: attachment.mimeType
|
|
1533
1783
|
};
|
|
1534
1784
|
}
|
|
1535
1785
|
async directory() {
|
|
1536
1786
|
if (!this.directoryPromise) {
|
|
1537
|
-
const pending = fs.
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1787
|
+
const pending = this.persistentDirectory ? fs.mkdir(this.persistentDirectory, {
|
|
1788
|
+
recursive: true,
|
|
1789
|
+
mode: 448
|
|
1790
|
+
}).then(() => this.persistentDirectory) : this.directoryRoot ? fs.mkdir(this.directoryRoot, { recursive: true, mode: 448 }).then(
|
|
1791
|
+
() => fs.mkdtemp(
|
|
1792
|
+
path.join(this.directoryRoot, "session-attachment-")
|
|
1793
|
+
)
|
|
1794
|
+
) : fs.mkdtemp(path.join(tmpdir(), "qwen-session-attachment-"));
|
|
1795
|
+
const directoryPromise = pending.then((directory) => {
|
|
1796
|
+
this.activeDirectory = directory;
|
|
1797
|
+
return directory;
|
|
1798
|
+
});
|
|
1799
|
+
this.directoryPromise = directoryPromise;
|
|
1800
|
+
void directoryPromise.catch(() => {
|
|
1801
|
+
if (this.directoryPromise === directoryPromise)
|
|
1541
1802
|
this.directoryPromise = void 0;
|
|
1542
1803
|
});
|
|
1543
1804
|
}
|
|
@@ -1555,7 +1816,7 @@ __name(writeStderrLine, "writeStderrLine");
|
|
|
1555
1816
|
|
|
1556
1817
|
// packages/acp-bridge/src/bridgeClient.ts
|
|
1557
1818
|
init_esbuild_shims();
|
|
1558
|
-
import { randomUUID
|
|
1819
|
+
import { randomUUID } from "node:crypto";
|
|
1559
1820
|
import { promises as fs2 } from "node:fs";
|
|
1560
1821
|
import * as path2 from "node:path";
|
|
1561
1822
|
|
|
@@ -2543,7 +2804,7 @@ function sliceLineRange(content, startLine, endLine) {
|
|
|
2543
2804
|
}
|
|
2544
2805
|
__name(sliceLineRange, "sliceLineRange");
|
|
2545
2806
|
var BridgeClient = class {
|
|
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) {
|
|
2807
|
+
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, onGoalTurnEnded) {
|
|
2547
2808
|
this.resolveEntry = resolveEntry;
|
|
2548
2809
|
this.resolvePendingRestoreEvents = resolvePendingRestoreEvents;
|
|
2549
2810
|
this.mediator = mediator;
|
|
@@ -2566,6 +2827,7 @@ var BridgeClient = class {
|
|
|
2566
2827
|
this.externalToolGuard = externalToolGuard;
|
|
2567
2828
|
this.onActiveWork = onActiveWork;
|
|
2568
2829
|
this.onSessionCatalogChanged = onSessionCatalogChanged;
|
|
2830
|
+
this.onGoalTurnEnded = onGoalTurnEnded;
|
|
2569
2831
|
}
|
|
2570
2832
|
static {
|
|
2571
2833
|
__name(this, "BridgeClient");
|
|
@@ -2584,7 +2846,7 @@ var BridgeClient = class {
|
|
|
2584
2846
|
options.map((o) => String(o.optionId ?? ""))
|
|
2585
2847
|
);
|
|
2586
2848
|
allowedOptionIds.delete("");
|
|
2587
|
-
const requestId =
|
|
2849
|
+
const requestId = randomUUID();
|
|
2588
2850
|
if (allowedOptionIds.has(CANCEL_VOTE_SENTINEL)) {
|
|
2589
2851
|
throw new CancelSentinelCollisionError(requestId, CANCEL_VOTE_SENTINEL);
|
|
2590
2852
|
}
|
|
@@ -2883,38 +3145,41 @@ var BridgeClient = class {
|
|
|
2883
3145
|
);
|
|
2884
3146
|
}
|
|
2885
3147
|
}
|
|
2886
|
-
const
|
|
2887
|
-
const
|
|
3148
|
+
const attachmentMemo = /* @__PURE__ */ new Map();
|
|
3149
|
+
const serializedAttachmentIds = /* @__PURE__ */ new Set();
|
|
2888
3150
|
const items = [];
|
|
2889
3151
|
try {
|
|
2890
3152
|
for (const item of drained) {
|
|
2891
3153
|
let degraded = 0;
|
|
2892
3154
|
const planned = (item.content ?? []).filter((block) => {
|
|
2893
|
-
if (!
|
|
2894
|
-
if (
|
|
3155
|
+
if (!isSessionAttachmentReference(block)) return true;
|
|
3156
|
+
if (serializedAttachmentIds.has(block.attachmentId)) {
|
|
2895
3157
|
degraded += 1;
|
|
2896
3158
|
return false;
|
|
2897
3159
|
}
|
|
2898
|
-
|
|
3160
|
+
serializedAttachmentIds.add(block.attachmentId);
|
|
2899
3161
|
return true;
|
|
2900
3162
|
});
|
|
2901
3163
|
let resolvedBlocks;
|
|
2902
|
-
let
|
|
3164
|
+
let attachmentReferences;
|
|
2903
3165
|
try {
|
|
2904
|
-
resolvedBlocks = await entry.
|
|
2905
|
-
|
|
3166
|
+
resolvedBlocks = await entry.attachments.resolveContent(
|
|
3167
|
+
planned,
|
|
3168
|
+
attachmentMemo
|
|
3169
|
+
);
|
|
3170
|
+
attachmentReferences = planned.filter(isSessionAttachmentReference);
|
|
2906
3171
|
} catch (error) {
|
|
2907
|
-
if (!(error instanceof
|
|
3172
|
+
if (!(error instanceof SessionAttachmentReferenceError)) throw error;
|
|
2908
3173
|
writeStderrLine(
|
|
2909
|
-
`[mid-turn] session=${JSON.stringify(entry.sessionId)} degraded
|
|
3174
|
+
`[mid-turn] session=${JSON.stringify(entry.sessionId)} degraded attachment for message ${JSON.stringify(item.messageId)}: ${JSON.stringify(error instanceof Error ? error.message : String(error))}`
|
|
2910
3175
|
);
|
|
2911
|
-
const perBlock = await entry.
|
|
3176
|
+
const perBlock = await entry.attachments.resolveContentDegrading(
|
|
2912
3177
|
planned,
|
|
2913
|
-
|
|
3178
|
+
attachmentMemo
|
|
2914
3179
|
);
|
|
2915
3180
|
resolvedBlocks = perBlock.resolvedBlocks;
|
|
2916
|
-
|
|
2917
|
-
|
|
3181
|
+
attachmentReferences = perBlock.retainedBlocks.filter(
|
|
3182
|
+
isSessionAttachmentReference
|
|
2918
3183
|
);
|
|
2919
3184
|
degraded += perBlock.degraded;
|
|
2920
3185
|
}
|
|
@@ -2922,12 +3187,12 @@ var BridgeClient = class {
|
|
|
2922
3187
|
...item.text ? [{ type: "text", text: item.text }] : [],
|
|
2923
3188
|
...resolvedBlocks
|
|
2924
3189
|
];
|
|
2925
|
-
if (degraded > 0) content =
|
|
3190
|
+
if (degraded > 0) content = withAttachmentDegradationMarker(content);
|
|
2926
3191
|
items.push({
|
|
2927
3192
|
messageId: item.messageId,
|
|
2928
3193
|
displayText: item.text,
|
|
2929
3194
|
content,
|
|
2930
|
-
...
|
|
3195
|
+
...attachmentReferences.length > 0 ? { attachmentReferences } : {}
|
|
2931
3196
|
});
|
|
2932
3197
|
}
|
|
2933
3198
|
} catch (error) {
|
|
@@ -3356,7 +3621,7 @@ var BridgeClient = class {
|
|
|
3356
3621
|
* `qwen/notify/session/prompt-suggestion` (followup assist),
|
|
3357
3622
|
* `qwen/notify/session/artifact-event` (hook artifacts),
|
|
3358
3623
|
* `qwen/notify/session/terminal-sequence`, and
|
|
3359
|
-
* `_qwencode/end_turn` (background-notification turns), and
|
|
3624
|
+
* `_qwencode/end_turn` (background-notification and goal turns), and
|
|
3360
3625
|
* `qwen/notify/session/mcp-budget-event` — each translated into a
|
|
3361
3626
|
* session-scoped SSE frame. Unknown methods are dropped silently for
|
|
3362
3627
|
* forward-compat.
|
|
@@ -3379,14 +3644,39 @@ var BridgeClient = class {
|
|
|
3379
3644
|
}
|
|
3380
3645
|
return;
|
|
3381
3646
|
}
|
|
3647
|
+
if (method === "_qwencode/start_turn") {
|
|
3648
|
+
const sessionId2 = params["sessionId"];
|
|
3649
|
+
if (typeof sessionId2 !== "string" || sessionId2.length === 0 || params["source"] !== "goal") {
|
|
3650
|
+
return;
|
|
3651
|
+
}
|
|
3652
|
+
const entry = this.resolveEntry(sessionId2);
|
|
3653
|
+
if (!entry || !this.ownsSession(sessionId2)) return;
|
|
3654
|
+
entry.goalTurnActive = true;
|
|
3655
|
+
return;
|
|
3656
|
+
}
|
|
3382
3657
|
if (method === "_qwencode/end_turn") {
|
|
3383
3658
|
const sessionId2 = params["sessionId"];
|
|
3384
3659
|
const reason = params["reason"];
|
|
3385
|
-
|
|
3660
|
+
const source = params["source"];
|
|
3661
|
+
if (typeof sessionId2 !== "string" || sessionId2.length === 0 || typeof reason !== "string" || reason.length === 0 || reason.length > 128 || source !== "background_notification" && source !== "goal") {
|
|
3386
3662
|
return;
|
|
3387
3663
|
}
|
|
3388
3664
|
const entry = this.resolveEntry(sessionId2);
|
|
3389
3665
|
if (!entry || !this.ownsSession(sessionId2)) return;
|
|
3666
|
+
if (source === "goal") {
|
|
3667
|
+
entry.goalTurnActive = false;
|
|
3668
|
+
this.onGoalTurnEnded?.(sessionId2);
|
|
3669
|
+
const promptId = params["promptId"];
|
|
3670
|
+
if (typeof promptId !== "string" || promptId.length === 0 || promptId.length > 256) {
|
|
3671
|
+
return;
|
|
3672
|
+
}
|
|
3673
|
+
entry.events.publish({
|
|
3674
|
+
type: "turn_complete",
|
|
3675
|
+
promptId,
|
|
3676
|
+
data: { sessionId: sessionId2, stopReason: reason, promptId }
|
|
3677
|
+
});
|
|
3678
|
+
return;
|
|
3679
|
+
}
|
|
3390
3680
|
entry.events.publish({
|
|
3391
3681
|
type: "background_notification_turn_complete",
|
|
3392
3682
|
data: { sessionId: sessionId2, reason }
|
|
@@ -3947,7 +4237,7 @@ var BridgeClient = class {
|
|
|
3947
4237
|
} catch {
|
|
3948
4238
|
}
|
|
3949
4239
|
}
|
|
3950
|
-
const tmp = `${realTarget}.${process.pid}.${Date.now()}.${
|
|
4240
|
+
const tmp = `${realTarget}.${process.pid}.${Date.now()}.${randomUUID()}.tmp`;
|
|
3951
4241
|
let preserveMode;
|
|
3952
4242
|
try {
|
|
3953
4243
|
const targetStat = await fs2.stat(realTarget);
|
|
@@ -7276,6 +7566,56 @@ function rememberEnrichedTerminalTurnStatus(entry, promptId, status) {
|
|
|
7276
7566
|
}
|
|
7277
7567
|
}
|
|
7278
7568
|
__name(rememberEnrichedTerminalTurnStatus, "rememberEnrichedTerminalTurnStatus");
|
|
7569
|
+
function advanceTurnActivity(entry) {
|
|
7570
|
+
const createdAtMs = Date.parse(entry.createdAt);
|
|
7571
|
+
const previous = entry.lastTurnEndedAtMs ?? (Number.isFinite(createdAtMs) ? createdAtMs : void 0);
|
|
7572
|
+
entry.lastTurnEndedAtMs = previous === void 0 ? Date.now() : Math.max(Date.now(), previous + 1);
|
|
7573
|
+
}
|
|
7574
|
+
__name(advanceTurnActivity, "advanceTurnActivity");
|
|
7575
|
+
function appendPromptLedgerBestEffort(entry, record) {
|
|
7576
|
+
const ledger = entry.promptLedger;
|
|
7577
|
+
if (!ledger) return;
|
|
7578
|
+
try {
|
|
7579
|
+
ledger.appendSync(entry.sessionId, record);
|
|
7580
|
+
} catch (error) {
|
|
7581
|
+
writeStderrLine(
|
|
7582
|
+
`qwen serve: prompt ledger append failed for session=${entry.sessionId} promptId=${record.promptId}: ${error instanceof Error ? error.message : String(error)}`
|
|
7583
|
+
);
|
|
7584
|
+
}
|
|
7585
|
+
}
|
|
7586
|
+
__name(appendPromptLedgerBestEffort, "appendPromptLedgerBestEffort");
|
|
7587
|
+
function promptLedgerTerminalRecord(pendingEntry, terminal) {
|
|
7588
|
+
const at = Date.now();
|
|
7589
|
+
if (terminal.kind === "complete") {
|
|
7590
|
+
if (terminal.result.stopReason === "cancelled") {
|
|
7591
|
+
return {
|
|
7592
|
+
v: 1,
|
|
7593
|
+
promptId: pendingEntry.promptId,
|
|
7594
|
+
terminal: "cancelled",
|
|
7595
|
+
at
|
|
7596
|
+
};
|
|
7597
|
+
}
|
|
7598
|
+
return {
|
|
7599
|
+
v: 1,
|
|
7600
|
+
promptId: pendingEntry.promptId,
|
|
7601
|
+
terminal: "completed",
|
|
7602
|
+
...terminal.result.stopReason !== void 0 ? { stopReason: terminal.result.stopReason } : {},
|
|
7603
|
+
at
|
|
7604
|
+
};
|
|
7605
|
+
}
|
|
7606
|
+
if (terminal.kind === "cancelled") {
|
|
7607
|
+
return { v: 1, promptId: pendingEntry.promptId, terminal: "cancelled", at };
|
|
7608
|
+
}
|
|
7609
|
+
const normalized = normalizeTurnResultError(terminal.err);
|
|
7610
|
+
return {
|
|
7611
|
+
v: 1,
|
|
7612
|
+
promptId: pendingEntry.promptId,
|
|
7613
|
+
terminal: "error",
|
|
7614
|
+
...normalized.code !== void 0 ? { code: normalized.code } : {},
|
|
7615
|
+
at
|
|
7616
|
+
};
|
|
7617
|
+
}
|
|
7618
|
+
__name(promptLedgerTerminalRecord, "promptLedgerTerminalRecord");
|
|
7279
7619
|
function publishPromptTerminal(entry, pendingEntry, terminal) {
|
|
7280
7620
|
if (pendingEntry.terminalPublished) {
|
|
7281
7621
|
writeServeDebugLine(
|
|
@@ -7284,9 +7624,16 @@ function publishPromptTerminal(entry, pendingEntry, terminal) {
|
|
|
7284
7624
|
return;
|
|
7285
7625
|
}
|
|
7286
7626
|
pendingEntry.terminalPublished = true;
|
|
7627
|
+
appendPromptLedgerBestEffort(
|
|
7628
|
+
entry,
|
|
7629
|
+
promptLedgerTerminalRecord(pendingEntry, terminal)
|
|
7630
|
+
);
|
|
7287
7631
|
rememberTerminalTurnStatus(entry, pendingEntry, terminal);
|
|
7288
7632
|
const originatorClientId = pendingEntry.originatorClientId;
|
|
7289
7633
|
const mutateTurnState = pendingEntry.state === "running";
|
|
7634
|
+
if (mutateTurnState) {
|
|
7635
|
+
advanceTurnActivity(entry);
|
|
7636
|
+
}
|
|
7290
7637
|
if (!mutateTurnState && entry.turnErrorEvent) {
|
|
7291
7638
|
const journal = entry.events.liveJournalSnapshot() ?? [];
|
|
7292
7639
|
if (journal.some(isRefreshAppendTurnContent)) {
|
|
@@ -7448,7 +7795,7 @@ function extractMediaBlocks(prompt) {
|
|
|
7448
7795
|
const media = [];
|
|
7449
7796
|
for (const block of prompt) {
|
|
7450
7797
|
if (!block || typeof block !== "object") continue;
|
|
7451
|
-
if (block.type === "image" || block.type === "audio") {
|
|
7798
|
+
if (block.type === "image" || block.type === "audio" || block.type === "resource" && "attachmentId" in block) {
|
|
7452
7799
|
media.push(block);
|
|
7453
7800
|
}
|
|
7454
7801
|
}
|
|
@@ -7472,15 +7819,22 @@ var MAX_EMPTY_TRANSCRIPT_PAGES = 20;
|
|
|
7472
7819
|
var SHELL_COMMAND_TIMEOUT_MS = 12e4;
|
|
7473
7820
|
var MAX_SHELL_OUTPUT_FOR_HISTORY = 1e4;
|
|
7474
7821
|
var MAX_MID_TURN_QUEUE_DEPTH = 20;
|
|
7475
|
-
var
|
|
7822
|
+
var MAX_QUEUED_INLINE_ATTACHMENT_BYTES = 100 * 1024 * 1024;
|
|
7823
|
+
function inlineAttachmentBlockBytes(blocks) {
|
|
7476
7824
|
let total = 0;
|
|
7477
7825
|
for (const block of blocks) {
|
|
7478
7826
|
if (block.type === "image" && "data" in block) {
|
|
7479
|
-
total += block.data
|
|
7827
|
+
total += Buffer.byteLength(block.data);
|
|
7828
|
+
continue;
|
|
7480
7829
|
}
|
|
7830
|
+
if (block.type !== "resource" || !("resource" in block)) continue;
|
|
7831
|
+
const resource = block.resource;
|
|
7832
|
+
if ("blob" in resource) total += Buffer.byteLength(resource.blob);
|
|
7833
|
+
else if ("text" in resource) total += Buffer.byteLength(resource.text);
|
|
7481
7834
|
}
|
|
7482
7835
|
return total;
|
|
7483
|
-
}
|
|
7836
|
+
}
|
|
7837
|
+
__name(inlineAttachmentBlockBytes, "inlineAttachmentBlockBytes");
|
|
7484
7838
|
var DEFAULT_MAX_SESSIONS = 32;
|
|
7485
7839
|
var DEFAULT_MAX_PENDING_PROMPTS_PER_SESSION = 5;
|
|
7486
7840
|
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;
|
|
@@ -7489,8 +7843,6 @@ var DEFAULT_PERMISSION_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
|
7489
7843
|
var DEFAULT_MAX_PENDING_PER_SESSION = 64;
|
|
7490
7844
|
var DEFAULT_SESSION_REAP_INTERVAL_MS = 6e4;
|
|
7491
7845
|
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;
|
|
7494
7846
|
function createAcpSessionBridge(opts) {
|
|
7495
7847
|
let liveScreenContextCaptureHandler;
|
|
7496
7848
|
let liveTaskToolRequestHandler;
|
|
@@ -7549,7 +7901,7 @@ function createAcpSessionBridge(opts) {
|
|
|
7549
7901
|
);
|
|
7550
7902
|
}
|
|
7551
7903
|
}, "releaseFreshSessionReservation");
|
|
7552
|
-
const sessionCatalogGeneration =
|
|
7904
|
+
const sessionCatalogGeneration = randomUUID2();
|
|
7553
7905
|
let sessionCatalogRevision = 0;
|
|
7554
7906
|
const getSessionCatalogVersion = /* @__PURE__ */ __name(() => ({
|
|
7555
7907
|
generation: sessionCatalogGeneration,
|
|
@@ -7652,7 +8004,6 @@ function createAcpSessionBridge(opts) {
|
|
|
7652
8004
|
DEFAULT_SESSION_IDLE_TIMEOUT_MS
|
|
7653
8005
|
);
|
|
7654
8006
|
let sessionReaper;
|
|
7655
|
-
let mediaSweeper;
|
|
7656
8007
|
let lastActivityTimestamp = null;
|
|
7657
8008
|
let activePromptCounter = 0;
|
|
7658
8009
|
function touchActivity() {
|
|
@@ -7969,34 +8320,8 @@ function createAcpSessionBridge(opts) {
|
|
|
7969
8320
|
}
|
|
7970
8321
|
}
|
|
7971
8322
|
__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");
|
|
7988
8323
|
function startSessionReaper() {
|
|
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();
|
|
7998
|
-
return;
|
|
7999
|
-
}
|
|
8324
|
+
if (sessionReapIntervalMs <= 0) return;
|
|
8000
8325
|
writeStderrLine(
|
|
8001
8326
|
`qwen serve: session reaper started (interval ${sessionReapIntervalMs}ms, idle threshold ${sessionIdleTimeoutMs}ms)`
|
|
8002
8327
|
);
|
|
@@ -8017,7 +8342,6 @@ function createAcpSessionBridge(opts) {
|
|
|
8017
8342
|
closeReason: "idle_timeout"
|
|
8018
8343
|
});
|
|
8019
8344
|
}
|
|
8020
|
-
sweepRetainedMedia();
|
|
8021
8345
|
}, sessionReapIntervalMs);
|
|
8022
8346
|
sessionReaper.unref();
|
|
8023
8347
|
}
|
|
@@ -8027,29 +8351,11 @@ function createAcpSessionBridge(opts) {
|
|
|
8027
8351
|
clearInterval(sessionReaper);
|
|
8028
8352
|
sessionReaper = void 0;
|
|
8029
8353
|
}
|
|
8030
|
-
if (mediaSweeper !== void 0) {
|
|
8031
|
-
clearInterval(mediaSweeper);
|
|
8032
|
-
mediaSweeper = void 0;
|
|
8033
|
-
}
|
|
8034
8354
|
}
|
|
8035
8355
|
__name(stopSessionReaper, "stopSessionReaper");
|
|
8036
8356
|
const aliveChannels = /* @__PURE__ */ new Set();
|
|
8037
8357
|
let inFlightChannelSpawn;
|
|
8038
8358
|
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");
|
|
8053
8359
|
const forwardRunningPromptCancel = /* @__PURE__ */ __name(async (entry, pending, notification) => {
|
|
8054
8360
|
if (pending.cancelForwardInitial) {
|
|
8055
8361
|
return pending.cancelForwardInitial;
|
|
@@ -8121,12 +8427,13 @@ function createAcpSessionBridge(opts) {
|
|
|
8121
8427
|
sessionId: entry.sessionId,
|
|
8122
8428
|
workspaceCwd: entry.workspaceCwd,
|
|
8123
8429
|
createdAt: entry.createdAt,
|
|
8430
|
+
...entry.lastTurnEndedAtMs !== void 0 ? { updatedAt: new Date(entry.lastTurnEndedAtMs).toISOString() } : {},
|
|
8124
8431
|
displayName: entry.displayName,
|
|
8125
8432
|
...entry.parentSessionId ? { parentSessionId: entry.parentSessionId } : {},
|
|
8126
8433
|
...entry.sourceType ? { sourceType: entry.sourceType } : {},
|
|
8127
8434
|
...entry.sourceId !== void 0 ? { sourceId: entry.sourceId } : {},
|
|
8128
8435
|
clientCount: entry.clientIds.size,
|
|
8129
|
-
hasActivePrompt: entry.promptActive,
|
|
8436
|
+
hasActivePrompt: entry.promptActive || entry.goalTurnActive === true,
|
|
8130
8437
|
isWaitingForPermission,
|
|
8131
8438
|
isWaitingForUserQuestion,
|
|
8132
8439
|
pendingInteractionCount: entry.pendingInteractions.size,
|
|
@@ -8189,7 +8496,7 @@ function createAcpSessionBridge(opts) {
|
|
|
8189
8496
|
return limits;
|
|
8190
8497
|
}, "journalSessionLimits");
|
|
8191
8498
|
const unregisterJournalGrowthSessionLimits = journalGrowthPolicy !== void 0 && opts.registerJournalGrowthSessionLimits !== void 0 ? opts.registerJournalGrowthSessionLimits(journalSessionLimits) : void 0;
|
|
8192
|
-
const createClientId = /* @__PURE__ */ __name(() => `client_${
|
|
8499
|
+
const createClientId = /* @__PURE__ */ __name(() => `client_${randomUUID2()}`, "createClientId");
|
|
8193
8500
|
const registerClient = /* @__PURE__ */ __name((entry, requestedClientId) => {
|
|
8194
8501
|
if (requestedClientId && entry.clientIds.has(requestedClientId)) {
|
|
8195
8502
|
entry.clientIds.set(
|
|
@@ -8248,7 +8555,7 @@ function createAcpSessionBridge(opts) {
|
|
|
8248
8555
|
if (inFlightChannelSpawn) return await inFlightChannelSpawn;
|
|
8249
8556
|
const promise = (async () => {
|
|
8250
8557
|
const privateParentCapability = randomBytes(32).toString("base64url");
|
|
8251
|
-
const acpChannelId =
|
|
8558
|
+
const acpChannelId = randomUUID2();
|
|
8252
8559
|
const channel = await telemetry.withSpan(
|
|
8253
8560
|
"channel.spawn",
|
|
8254
8561
|
{
|
|
@@ -8372,7 +8679,10 @@ function createAcpSessionBridge(opts) {
|
|
|
8372
8679
|
},
|
|
8373
8680
|
// Child-side automatic title updates change persisted catalog
|
|
8374
8681
|
// metadata the bridge never sees; forward the catalog-clock mark.
|
|
8375
|
-
markSessionCatalogChanged
|
|
8682
|
+
markSessionCatalogChanged,
|
|
8683
|
+
// A Goal turn drains the mid-turn queue but owns no prompt slot, so
|
|
8684
|
+
// nothing else would settle what its last drain missed.
|
|
8685
|
+
settleMidTurnQueueAfterGoalTurn
|
|
8376
8686
|
);
|
|
8377
8687
|
const rawConnection = new ClientSideConnection(
|
|
8378
8688
|
() => channel.transportGuard ? createLogSafeAcpClient(client, channel.transportGuard) : client,
|
|
@@ -8510,9 +8820,11 @@ function createAcpSessionBridge(opts) {
|
|
|
8510
8820
|
touchActivity();
|
|
8511
8821
|
}
|
|
8512
8822
|
byId.delete(sid);
|
|
8513
|
-
|
|
8514
|
-
|
|
8515
|
-
|
|
8823
|
+
void sessEntry.attachments.close().catch((error) => {
|
|
8824
|
+
writeStderrLine(
|
|
8825
|
+
`qwen serve: failed to close attachments for closed channel session ${JSON.stringify(sid)}: ${error instanceof Error ? error.message : String(error)}`
|
|
8826
|
+
);
|
|
8827
|
+
});
|
|
8516
8828
|
telemetry.metrics?.sessionLifecycle("die");
|
|
8517
8829
|
emitSessionLifecycle({
|
|
8518
8830
|
type: "removed",
|
|
@@ -9260,6 +9572,41 @@ function createAcpSessionBridge(opts) {
|
|
|
9260
9572
|
}
|
|
9261
9573
|
return response;
|
|
9262
9574
|
}, "requestWorkspaceStatus");
|
|
9575
|
+
const MAX_CHILD_HEAP_UNCLASSIFIED_NAMES = 64;
|
|
9576
|
+
const MAX_CHILD_HEAP_SPACE_NAME_LENGTH = 64;
|
|
9577
|
+
const parseChildHeapReport = /* @__PURE__ */ __name((value) => {
|
|
9578
|
+
if (typeof value !== "object" || value === null) return void 0;
|
|
9579
|
+
const raw = value;
|
|
9580
|
+
const counts = [
|
|
9581
|
+
"peakOldGenerationBytes",
|
|
9582
|
+
"peakLiveSetBytes",
|
|
9583
|
+
"peakTotalHeapBytes",
|
|
9584
|
+
"majorGcCount",
|
|
9585
|
+
"majorGcMs"
|
|
9586
|
+
];
|
|
9587
|
+
const parsed = {};
|
|
9588
|
+
for (const key of counts) {
|
|
9589
|
+
const n = raw[key];
|
|
9590
|
+
if (typeof n !== "number" || !Number.isFinite(n) || n < 0) {
|
|
9591
|
+
return void 0;
|
|
9592
|
+
}
|
|
9593
|
+
parsed[key] = n;
|
|
9594
|
+
}
|
|
9595
|
+
const names = raw["unclassifiedSpaceNames"];
|
|
9596
|
+
if (!Array.isArray(names) || names.length > MAX_CHILD_HEAP_UNCLASSIFIED_NAMES || names.some(
|
|
9597
|
+
(name) => typeof name !== "string" || name.length > MAX_CHILD_HEAP_SPACE_NAME_LENGTH
|
|
9598
|
+
)) {
|
|
9599
|
+
return void 0;
|
|
9600
|
+
}
|
|
9601
|
+
return {
|
|
9602
|
+
peakOldGenerationBytes: parsed["peakOldGenerationBytes"],
|
|
9603
|
+
peakLiveSetBytes: parsed["peakLiveSetBytes"],
|
|
9604
|
+
peakTotalHeapBytes: parsed["peakTotalHeapBytes"],
|
|
9605
|
+
majorGcCount: parsed["majorGcCount"],
|
|
9606
|
+
majorGcMs: parsed["majorGcMs"],
|
|
9607
|
+
unclassifiedSpaceNames: names
|
|
9608
|
+
};
|
|
9609
|
+
}, "parseChildHeapReport");
|
|
9263
9610
|
const STALE_CHILD_RESOURCE_MS = 3e4;
|
|
9264
9611
|
let childResourceRefreshing = false;
|
|
9265
9612
|
const refreshChildResource = /* @__PURE__ */ __name(async () => {
|
|
@@ -9276,6 +9623,8 @@ function createAcpSessionBridge(opts) {
|
|
|
9276
9623
|
if (typeof res.cpuPercent === "number" && Number.isFinite(res.cpuPercent)) {
|
|
9277
9624
|
info.childCpuPercent = Math.min(100, Math.max(0, res.cpuPercent));
|
|
9278
9625
|
}
|
|
9626
|
+
const heap = parseChildHeapReport(res.heap);
|
|
9627
|
+
if (heap) info.childHeap = heap;
|
|
9279
9628
|
info.childResourceAt = Date.now();
|
|
9280
9629
|
} catch (err) {
|
|
9281
9630
|
teeServeDebugLine(
|
|
@@ -9295,6 +9644,10 @@ function createAcpSessionBridge(opts) {
|
|
|
9295
9644
|
return {
|
|
9296
9645
|
rssBytes: info.childRssBytes ?? 0,
|
|
9297
9646
|
cpuPercent: info.childCpuPercent ?? 0,
|
|
9647
|
+
// Deliberately not defaulted. Unlike rss/cpu, where 0 is a plausible
|
|
9648
|
+
// reading, a zeroed heap report would assert the child needed no old
|
|
9649
|
+
// generation — the one conclusion that must never be manufactured.
|
|
9650
|
+
heap: info.childHeap,
|
|
9298
9651
|
// Bounded by the guard above, so a caller summing several children's
|
|
9299
9652
|
// readings can say how far apart they were taken. Without it a sum of
|
|
9300
9653
|
// readings up to `STALE_CHILD_RESOURCE_MS` apart looks instantaneous.
|
|
@@ -9550,13 +9903,17 @@ function createAcpSessionBridge(opts) {
|
|
|
9550
9903
|
workspaceCwd,
|
|
9551
9904
|
persistence: createSessionArtifactPersistence(ci.connection, sessionId)
|
|
9552
9905
|
}),
|
|
9553
|
-
|
|
9906
|
+
attachments: new SessionAttachmentStore(
|
|
9907
|
+
opts.sessionAttachmentsRoot,
|
|
9908
|
+
sessionId
|
|
9909
|
+
),
|
|
9554
9910
|
recordingDegraded: false,
|
|
9555
9911
|
closing: false,
|
|
9556
9912
|
cwdChangeQueue: Promise.resolve(),
|
|
9557
9913
|
promptQueue: Promise.resolve(),
|
|
9558
9914
|
pendingPromptCount: 0,
|
|
9559
9915
|
pendingAgentNotificationCount: 0,
|
|
9916
|
+
...opts.promptLedger ? { promptLedger: opts.promptLedger } : {},
|
|
9560
9917
|
pendingPromptList: [],
|
|
9561
9918
|
terminalTurnStatuses: /* @__PURE__ */ new Map(),
|
|
9562
9919
|
enrichedTerminalPromptIds: /* @__PURE__ */ new Set(),
|
|
@@ -9974,7 +10331,7 @@ function createAcpSessionBridge(opts) {
|
|
|
9974
10331
|
// Late attachers get the same ACP state the original restore
|
|
9975
10332
|
// caller saw; spawn-only sessions don't carry a state payload.
|
|
9976
10333
|
state: existing.restoreState ?? {},
|
|
9977
|
-
hasActivePrompt: existing.promptActive,
|
|
10334
|
+
hasActivePrompt: existing.promptActive || existing.goalTurnActive === true,
|
|
9978
10335
|
...replayFields,
|
|
9979
10336
|
...historyAnchorRecordId !== void 0 ? { historyAnchorRecordId } : {}
|
|
9980
10337
|
};
|
|
@@ -10056,7 +10413,7 @@ function createAcpSessionBridge(opts) {
|
|
|
10056
10413
|
attached: true,
|
|
10057
10414
|
clientId,
|
|
10058
10415
|
createdAt: entry.createdAt,
|
|
10059
|
-
hasActivePrompt: entry.promptActive,
|
|
10416
|
+
hasActivePrompt: entry.promptActive || entry.goalTurnActive === true,
|
|
10060
10417
|
...waiterReplayFields ?? {}
|
|
10061
10418
|
};
|
|
10062
10419
|
}
|
|
@@ -10419,7 +10776,7 @@ function createAcpSessionBridge(opts) {
|
|
|
10419
10776
|
...racedEntry.sourceType ? { sourceType: racedEntry.sourceType } : {},
|
|
10420
10777
|
...racedEntry.sourceId !== void 0 ? { sourceId: racedEntry.sourceId } : {},
|
|
10421
10778
|
state: racedEntry.restoreState ?? {},
|
|
10422
|
-
hasActivePrompt: racedEntry.promptActive,
|
|
10779
|
+
hasActivePrompt: racedEntry.promptActive || racedEntry.goalTurnActive === true,
|
|
10423
10780
|
...replayFieldsFor(racedEntry, action, liveReplayMode)
|
|
10424
10781
|
};
|
|
10425
10782
|
}
|
|
@@ -10495,7 +10852,7 @@ function createAcpSessionBridge(opts) {
|
|
|
10495
10852
|
...entry.sourceId !== void 0 ? { sourceId: entry.sourceId } : {},
|
|
10496
10853
|
state: publicState,
|
|
10497
10854
|
...artifactRestoreWarnings.length > 0 ? { artifactWarnings: artifactRestoreWarnings } : {},
|
|
10498
|
-
hasActivePrompt: entry.promptActive,
|
|
10855
|
+
hasActivePrompt: entry.promptActive || entry.goalTurnActive === true,
|
|
10499
10856
|
...replayFieldsFor(entry, action, liveReplayMode)
|
|
10500
10857
|
};
|
|
10501
10858
|
})().finally(async () => {
|
|
@@ -10510,9 +10867,11 @@ function createAcpSessionBridge(opts) {
|
|
|
10510
10867
|
const restoreEntry = byId.get(req.sessionId);
|
|
10511
10868
|
if (restoreEntry?.events === restoreEvents) {
|
|
10512
10869
|
byId.delete(req.sessionId);
|
|
10513
|
-
|
|
10514
|
-
|
|
10515
|
-
|
|
10870
|
+
await restoreEntry.attachments.close().catch((error) => {
|
|
10871
|
+
writeStderrLine(
|
|
10872
|
+
`qwen serve: failed to close attachments after restoring session ${JSON.stringify(req.sessionId)}: ${error instanceof Error ? error.message : String(error)}`
|
|
10873
|
+
);
|
|
10874
|
+
});
|
|
10516
10875
|
ci?.sessionIds.delete(req.sessionId);
|
|
10517
10876
|
emitSessionLifecycle({
|
|
10518
10877
|
type: "removed",
|
|
@@ -10676,15 +11035,11 @@ function createAcpSessionBridge(opts) {
|
|
|
10676
11035
|
} catch {
|
|
10677
11036
|
}
|
|
10678
11037
|
entry.events.close();
|
|
10679
|
-
|
|
10680
|
-
|
|
10681
|
-
|
|
10682
|
-
|
|
10683
|
-
|
|
10684
|
-
`qwen serve: failed to release media for closed session ${JSON.stringify(sessionId)}: ${error instanceof Error ? error.message : String(error)}`
|
|
10685
|
-
);
|
|
10686
|
-
});
|
|
10687
|
-
}
|
|
11038
|
+
await entry.attachments.close().catch((error) => {
|
|
11039
|
+
writeStderrLine(
|
|
11040
|
+
`qwen serve: failed to close attachments for session ${JSON.stringify(sessionId)}: ${error instanceof Error ? error.message : String(error)}`
|
|
11041
|
+
);
|
|
11042
|
+
});
|
|
10688
11043
|
if (!agentSessionClosed) {
|
|
10689
11044
|
try {
|
|
10690
11045
|
await telemetry.withSpan(
|
|
@@ -10713,25 +11068,15 @@ function createAcpSessionBridge(opts) {
|
|
|
10713
11068
|
ring.splice(0, ring.length - MID_TURN_RECONCILIATION_RING_SIZE);
|
|
10714
11069
|
}
|
|
10715
11070
|
}, "rememberMidTurnId");
|
|
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
11071
|
const promoteMidTurnMessage = /* @__PURE__ */ __name((entry, messageId, text, originatorClientId, content) => {
|
|
10727
11072
|
const resolvableBlocks = [];
|
|
10728
11073
|
let degraded = 0;
|
|
10729
11074
|
for (const block of content ?? []) {
|
|
10730
11075
|
try {
|
|
10731
|
-
entry.
|
|
11076
|
+
entry.attachments.assertReference(block);
|
|
10732
11077
|
resolvableBlocks.push(block);
|
|
10733
11078
|
} catch (error) {
|
|
10734
|
-
if (!(error instanceof
|
|
11079
|
+
if (!(error instanceof SessionAttachmentReferenceError)) throw error;
|
|
10735
11080
|
degraded += 1;
|
|
10736
11081
|
}
|
|
10737
11082
|
}
|
|
@@ -10740,7 +11085,7 @@ function createAcpSessionBridge(opts) {
|
|
|
10740
11085
|
...resolvableBlocks
|
|
10741
11086
|
];
|
|
10742
11087
|
if (degraded > 0) {
|
|
10743
|
-
prompt =
|
|
11088
|
+
prompt = withAttachmentDegradationMarker(prompt);
|
|
10744
11089
|
}
|
|
10745
11090
|
const context = {
|
|
10746
11091
|
promptId: messageId,
|
|
@@ -10753,7 +11098,7 @@ function createAcpSessionBridge(opts) {
|
|
|
10753
11098
|
entry.sessionId,
|
|
10754
11099
|
{
|
|
10755
11100
|
sessionId: entry.sessionId,
|
|
10756
|
-
prompt:
|
|
11101
|
+
prompt: withAttachmentDegradationMarker(
|
|
10757
11102
|
text ? [{ type: "text", text }] : []
|
|
10758
11103
|
)
|
|
10759
11104
|
},
|
|
@@ -10773,7 +11118,7 @@ function createAcpSessionBridge(opts) {
|
|
|
10773
11118
|
);
|
|
10774
11119
|
} catch (error) {
|
|
10775
11120
|
try {
|
|
10776
|
-
if (!(error instanceof
|
|
11121
|
+
if (!(error instanceof SessionAttachmentReferenceError)) throw error;
|
|
10777
11122
|
result = sendFallback();
|
|
10778
11123
|
} catch (fallbackError) {
|
|
10779
11124
|
writeStderrLine(
|
|
@@ -10788,6 +11133,37 @@ function createAcpSessionBridge(opts) {
|
|
|
10788
11133
|
);
|
|
10789
11134
|
});
|
|
10790
11135
|
}, "promoteMidTurnMessage");
|
|
11136
|
+
const settleUndrainedMidTurnMessages = /* @__PURE__ */ __name((entry, messages) => {
|
|
11137
|
+
for (const message of messages) {
|
|
11138
|
+
if (message.queueOnly) {
|
|
11139
|
+
try {
|
|
11140
|
+
message.onSettledWithoutDrain?.();
|
|
11141
|
+
} catch (error) {
|
|
11142
|
+
writeStderrLine(
|
|
11143
|
+
`[mid-turn] session=${JSON.stringify(entry.sessionId)} failed to hand undrained queue-only message ${JSON.stringify(message.messageId)} back to its caller: ${JSON.stringify(error instanceof Error ? error.message : String(error))}`
|
|
11144
|
+
);
|
|
11145
|
+
}
|
|
11146
|
+
continue;
|
|
11147
|
+
}
|
|
11148
|
+
promoteMidTurnMessage(
|
|
11149
|
+
entry,
|
|
11150
|
+
message.messageId,
|
|
11151
|
+
message.text,
|
|
11152
|
+
message.originatorClientId,
|
|
11153
|
+
message.content
|
|
11154
|
+
);
|
|
11155
|
+
}
|
|
11156
|
+
}, "settleUndrainedMidTurnMessages");
|
|
11157
|
+
const settleMidTurnQueueAfterGoalTurn = /* @__PURE__ */ __name((sessionId) => {
|
|
11158
|
+
const entry = byId.get(sessionId);
|
|
11159
|
+
if (!entry) return;
|
|
11160
|
+
if (entry.goalTurnActive === true || entry.pendingPromptCount > 0 || entry.closing) {
|
|
11161
|
+
return;
|
|
11162
|
+
}
|
|
11163
|
+
const undrained = entry.midTurnMessageQueue.splice(0);
|
|
11164
|
+
if (undrained.length === 0) return;
|
|
11165
|
+
settleUndrainedMidTurnMessages(entry, undrained);
|
|
11166
|
+
}, "settleMidTurnQueueAfterGoalTurn");
|
|
10791
11167
|
const bridgeApi = {
|
|
10792
11168
|
setLiveScreenContextCaptureHandler(handler) {
|
|
10793
11169
|
liveScreenContextCaptureHandler = handler;
|
|
@@ -10830,7 +11206,7 @@ function createAcpSessionBridge(opts) {
|
|
|
10830
11206
|
attachCount: entry.attachCount,
|
|
10831
11207
|
pendingPromptCount: entry.pendingPromptCount,
|
|
10832
11208
|
pendingPermissionCount: entry.pendingPermissionIds.size,
|
|
10833
|
-
hasActivePrompt: entry.promptActive,
|
|
11209
|
+
hasActivePrompt: entry.promptActive || entry.goalTurnActive === true,
|
|
10834
11210
|
lastEventId: entry.events.lastEventId,
|
|
10835
11211
|
...entry.sessionLastSeenAt !== void 0 ? { lastSeenAt: entry.sessionLastSeenAt } : {},
|
|
10836
11212
|
...entry.currentModelId ? { currentModelId: entry.currentModelId } : {},
|
|
@@ -10983,7 +11359,7 @@ function createAcpSessionBridge(opts) {
|
|
|
10983
11359
|
createdAt: existing.createdAt,
|
|
10984
11360
|
...existing.sourceType ? { sourceType: existing.sourceType } : {},
|
|
10985
11361
|
...existing.sourceId !== void 0 ? { sourceId: existing.sourceId } : {},
|
|
10986
|
-
hasActivePrompt: existing.promptActive
|
|
11362
|
+
hasActivePrompt: existing.promptActive || existing.goalTurnActive === true
|
|
10987
11363
|
};
|
|
10988
11364
|
}
|
|
10989
11365
|
const inFlight = inFlightSpawns.get(workspaceKey);
|
|
@@ -11034,7 +11410,7 @@ function createAcpSessionBridge(opts) {
|
|
|
11034
11410
|
...session,
|
|
11035
11411
|
attached: true,
|
|
11036
11412
|
clientId,
|
|
11037
|
-
hasActivePrompt: attachedEntry.promptActive
|
|
11413
|
+
hasActivePrompt: attachedEntry.promptActive || attachedEntry.goalTurnActive === true
|
|
11038
11414
|
};
|
|
11039
11415
|
}
|
|
11040
11416
|
}
|
|
@@ -11102,7 +11478,7 @@ function createAcpSessionBridge(opts) {
|
|
|
11102
11478
|
req.branch,
|
|
11103
11479
|
req.sessionId
|
|
11104
11480
|
);
|
|
11105
|
-
const tracker = effectiveScope === "single" ? workspaceKey : `${workspaceKey}#${
|
|
11481
|
+
const tracker = effectiveScope === "single" ? workspaceKey : `${workspaceKey}#${randomUUID2()}`;
|
|
11106
11482
|
inFlightSpawns.set(tracker, promise);
|
|
11107
11483
|
try {
|
|
11108
11484
|
return await promise;
|
|
@@ -11140,7 +11516,7 @@ function createAcpSessionBridge(opts) {
|
|
|
11140
11516
|
const promotedMidTurn = context?.promotedMidTurn;
|
|
11141
11517
|
const isPromotedMidTurn = promotedMidTurn !== void 0;
|
|
11142
11518
|
const originatorClientId = promotedMidTurn ? promotedMidTurn.originatorClientId : resolveTrustedClientId(entry, context?.clientId);
|
|
11143
|
-
entry.
|
|
11519
|
+
entry.attachments.assertReferences(req.prompt);
|
|
11144
11520
|
const modelPrompt = context?.modelPrompt;
|
|
11145
11521
|
if (modelPrompt !== void 0 && !isValidTrustedModelPrompt(modelPrompt)) {
|
|
11146
11522
|
throw new TypeError(
|
|
@@ -11164,7 +11540,7 @@ function createAcpSessionBridge(opts) {
|
|
|
11164
11540
|
promptSlotReleased = true;
|
|
11165
11541
|
entry.pendingPromptCount = Math.max(0, entry.pendingPromptCount - 1);
|
|
11166
11542
|
}, "releasePromptSlot");
|
|
11167
|
-
const promptId = context?.promptId ??
|
|
11543
|
+
const promptId = context?.promptId ?? randomUUID2();
|
|
11168
11544
|
const invocationContext = Object.freeze({
|
|
11169
11545
|
version: 1,
|
|
11170
11546
|
sessionId,
|
|
@@ -11202,6 +11578,22 @@ function createAcpSessionBridge(opts) {
|
|
|
11202
11578
|
state: isQueued ? "queued" : "running"
|
|
11203
11579
|
};
|
|
11204
11580
|
entry.pendingPromptList.push(pendingEntry);
|
|
11581
|
+
let tailUuid;
|
|
11582
|
+
try {
|
|
11583
|
+
tailUuid = entry.promptLedger?.transcriptTailUuid?.(sessionId);
|
|
11584
|
+
} catch (error) {
|
|
11585
|
+
opts.onDiagnosticLine?.(
|
|
11586
|
+
`qwen serve: prompt ledger dispatch marker failed for session=${sessionId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
11587
|
+
"warn"
|
|
11588
|
+
);
|
|
11589
|
+
}
|
|
11590
|
+
appendPromptLedgerBestEffort(entry, {
|
|
11591
|
+
v: 1,
|
|
11592
|
+
promptId,
|
|
11593
|
+
state: "in_flight",
|
|
11594
|
+
...tailUuid !== void 0 ? { tailUuid } : {},
|
|
11595
|
+
at: queuedAt
|
|
11596
|
+
});
|
|
11205
11597
|
try {
|
|
11206
11598
|
context?.onPromptAdmitted?.();
|
|
11207
11599
|
} catch (error) {
|
|
@@ -11321,14 +11713,16 @@ function createAcpSessionBridge(opts) {
|
|
|
11321
11713
|
let dispatchBlocks = req.prompt;
|
|
11322
11714
|
let resolvedPrompt;
|
|
11323
11715
|
try {
|
|
11324
|
-
resolvedPrompt = await entry.
|
|
11716
|
+
resolvedPrompt = await entry.attachments.resolveContent(dispatchBlocks);
|
|
11325
11717
|
} catch (error) {
|
|
11326
|
-
if (!isPromotedMidTurn || !(error instanceof
|
|
11718
|
+
if (!isPromotedMidTurn || !(error instanceof SessionAttachmentReferenceError)) {
|
|
11327
11719
|
throw error;
|
|
11328
11720
|
}
|
|
11329
|
-
const perBlock = await entry.
|
|
11721
|
+
const perBlock = await entry.attachments.resolveContentDegrading(
|
|
11722
|
+
dispatchBlocks
|
|
11723
|
+
);
|
|
11330
11724
|
dispatchBlocks = perBlock.retainedBlocks;
|
|
11331
|
-
resolvedPrompt =
|
|
11725
|
+
resolvedPrompt = withAttachmentDegradationMarker(
|
|
11332
11726
|
perBlock.resolvedBlocks
|
|
11333
11727
|
);
|
|
11334
11728
|
}
|
|
@@ -11359,7 +11753,7 @@ function createAcpSessionBridge(opts) {
|
|
|
11359
11753
|
delete meta[DAEMON_CHANNEL_DELIVERY_META_KEY];
|
|
11360
11754
|
delete meta[DAEMON_PROMPT_DISPLAY_TEXT_META_KEY];
|
|
11361
11755
|
delete meta[DAEMON_MODEL_PROMPT_META_KEY];
|
|
11362
|
-
delete meta[
|
|
11756
|
+
delete meta[DAEMON_ATTACHMENT_REFERENCES_META_KEY];
|
|
11363
11757
|
delete meta[CHANNEL_PROMPT_META_KEY];
|
|
11364
11758
|
if (isRetry) {
|
|
11365
11759
|
meta[DAEMON_RETRY_META_KEY] = true;
|
|
@@ -11376,11 +11770,11 @@ function createAcpSessionBridge(opts) {
|
|
|
11376
11770
|
if (modelPrompt !== void 0) {
|
|
11377
11771
|
meta[DAEMON_MODEL_PROMPT_META_KEY] = modelPrompt;
|
|
11378
11772
|
}
|
|
11379
|
-
const
|
|
11380
|
-
|
|
11773
|
+
const attachmentReferences = dispatchBlocks.filter(
|
|
11774
|
+
isSessionAttachmentReference
|
|
11381
11775
|
);
|
|
11382
|
-
if (
|
|
11383
|
-
meta[
|
|
11776
|
+
if (attachmentReferences.length > 0) {
|
|
11777
|
+
meta[DAEMON_ATTACHMENT_REFERENCES_META_KEY] = attachmentReferences;
|
|
11384
11778
|
}
|
|
11385
11779
|
if (context?.channelPrompt === true) {
|
|
11386
11780
|
meta[CHANNEL_PROMPT_META_KEY] = true;
|
|
@@ -11394,6 +11788,7 @@ function createAcpSessionBridge(opts) {
|
|
|
11394
11788
|
return copy;
|
|
11395
11789
|
})();
|
|
11396
11790
|
entry.promptActive = true;
|
|
11791
|
+
entry.goalTurnActive = false;
|
|
11397
11792
|
entry.activePromptId = pendingEntry.promptId;
|
|
11398
11793
|
delete entry.cancelBroadcastWithoutPrompt;
|
|
11399
11794
|
delete entry.turnError;
|
|
@@ -11554,25 +11949,7 @@ function createAcpSessionBridge(opts) {
|
|
|
11554
11949
|
const shouldSettleMidTurnQueue = entry.pendingPromptCount === 1 && !entry.closing && byId.get(entry.sessionId) === entry;
|
|
11555
11950
|
const undrainedMessages = shouldSettleMidTurnQueue ? entry.midTurnMessageQueue.splice(0) : [];
|
|
11556
11951
|
releasePromptSlot();
|
|
11557
|
-
|
|
11558
|
-
if (message.queueOnly) {
|
|
11559
|
-
try {
|
|
11560
|
-
message.onSettledWithoutDrain?.();
|
|
11561
|
-
} catch (error) {
|
|
11562
|
-
writeStderrLine(
|
|
11563
|
-
`[mid-turn] session=${JSON.stringify(entry.sessionId)} failed to hand undrained queue-only message ${JSON.stringify(message.messageId)} back to its caller: ${JSON.stringify(error instanceof Error ? error.message : String(error))}`
|
|
11564
|
-
);
|
|
11565
|
-
}
|
|
11566
|
-
continue;
|
|
11567
|
-
}
|
|
11568
|
-
promoteMidTurnMessage(
|
|
11569
|
-
entry,
|
|
11570
|
-
message.messageId,
|
|
11571
|
-
message.text,
|
|
11572
|
-
message.originatorClientId,
|
|
11573
|
-
message.content
|
|
11574
|
-
);
|
|
11575
|
-
}
|
|
11952
|
+
settleUndrainedMidTurnMessages(entry, undrainedMessages);
|
|
11576
11953
|
void maybeCloseIdleSession(entry, "prompt_settled");
|
|
11577
11954
|
}).catch(() => {
|
|
11578
11955
|
});
|
|
@@ -11818,6 +12195,21 @@ function createAcpSessionBridge(opts) {
|
|
|
11818
12195
|
);
|
|
11819
12196
|
}
|
|
11820
12197
|
markSessionCatalogChanged();
|
|
12198
|
+
if (opts.sessionAttachmentsRoot) {
|
|
12199
|
+
const branchAttachments = new SessionAttachmentStore(
|
|
12200
|
+
opts.sessionAttachmentsRoot,
|
|
12201
|
+
result.newSessionId
|
|
12202
|
+
);
|
|
12203
|
+
try {
|
|
12204
|
+
await branchAttachments.copyFrom(entry.attachments);
|
|
12205
|
+
} catch (error) {
|
|
12206
|
+
writeStderrLine(
|
|
12207
|
+
`qwen serve: failed to copy attachments for branched session ${result.newSessionId}: ${error instanceof Error ? error.message : String(error)}`
|
|
12208
|
+
);
|
|
12209
|
+
} finally {
|
|
12210
|
+
await branchAttachments.close();
|
|
12211
|
+
}
|
|
12212
|
+
}
|
|
11821
12213
|
const rawBranchName = result.displayName ?? result.title;
|
|
11822
12214
|
const branchDisplayName = typeof rawBranchName === "string" ? rawBranchName : result.newSessionId.slice(0, 8);
|
|
11823
12215
|
if (!restoreBranch) {
|
|
@@ -11884,6 +12276,15 @@ function createAcpSessionBridge(opts) {
|
|
|
11884
12276
|
throw restoreErr;
|
|
11885
12277
|
}
|
|
11886
12278
|
const newEntry = byId.get(result.newSessionId);
|
|
12279
|
+
if (newEntry && !opts.sessionAttachmentsRoot) {
|
|
12280
|
+
try {
|
|
12281
|
+
await newEntry.attachments.copyFrom(entry.attachments);
|
|
12282
|
+
} catch (error) {
|
|
12283
|
+
writeStderrLine(
|
|
12284
|
+
`qwen serve: failed to copy attachments for branched session ${result.newSessionId}: ${error instanceof Error ? error.message : String(error)}`
|
|
12285
|
+
);
|
|
12286
|
+
}
|
|
12287
|
+
}
|
|
11887
12288
|
if (newEntry) newEntry.displayName = branchDisplayName;
|
|
11888
12289
|
let sourcePersisted;
|
|
11889
12290
|
if (newEntry?.sourceType) {
|
|
@@ -12429,6 +12830,18 @@ function createAcpSessionBridge(opts) {
|
|
|
12429
12830
|
{ taskId, taskKind }
|
|
12430
12831
|
);
|
|
12431
12832
|
},
|
|
12833
|
+
async controlSessionGoal(sessionId, request, context) {
|
|
12834
|
+
const entry = byId.get(sessionId);
|
|
12835
|
+
if (!entry) throw new SessionNotFoundError(sessionId);
|
|
12836
|
+
const info = channelInfoForEntry(entry);
|
|
12837
|
+
if (!info || info.isDying) throw new SessionNotFoundError(sessionId);
|
|
12838
|
+
resolveTrustedClientId(entry, context?.clientId);
|
|
12839
|
+
return requestSessionStatus(
|
|
12840
|
+
sessionId,
|
|
12841
|
+
SERVE_CONTROL_EXT_METHODS.sessionGoalControl,
|
|
12842
|
+
{ request }
|
|
12843
|
+
);
|
|
12844
|
+
},
|
|
12432
12845
|
async clearSessionGoal(sessionId) {
|
|
12433
12846
|
return requestSessionStatus(
|
|
12434
12847
|
sessionId,
|
|
@@ -12805,7 +13218,7 @@ function createAcpSessionBridge(opts) {
|
|
|
12805
13218
|
const info = channelInfoForEntry(entry);
|
|
12806
13219
|
if (!info || info.isDying) throw new SessionNotFoundError(sessionId);
|
|
12807
13220
|
resolveTrustedClientId(entry, context?.clientId);
|
|
12808
|
-
const requestId =
|
|
13221
|
+
const requestId = randomUUID2();
|
|
12809
13222
|
const queue = new GenerationStreamQueue(
|
|
12810
13223
|
GENERATION_STREAM_QUEUE_CAPACITY
|
|
12811
13224
|
);
|
|
@@ -12939,42 +13352,27 @@ function createAcpSessionBridge(opts) {
|
|
|
12939
13352
|
}
|
|
12940
13353
|
return { sessionId, state: "idle" };
|
|
12941
13354
|
},
|
|
12942
|
-
async
|
|
13355
|
+
async storeSessionAttachment(sessionId, data, mimeType, context, name) {
|
|
12943
13356
|
const entry = byId.get(sessionId);
|
|
12944
13357
|
if (!entry) throw new SessionNotFoundError(sessionId);
|
|
12945
13358
|
resolveTrustedClientId(entry, context?.clientId);
|
|
12946
|
-
|
|
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;
|
|
13359
|
+
return await entry.attachments.putAttachment(data, mimeType, name);
|
|
12966
13360
|
},
|
|
12967
|
-
async
|
|
13361
|
+
async readSessionAttachment(sessionId, attachmentId, context) {
|
|
12968
13362
|
const entry = byId.get(sessionId);
|
|
12969
13363
|
if (!entry) throw new SessionNotFoundError(sessionId);
|
|
12970
13364
|
resolveTrustedClientId(entry, context?.clientId);
|
|
12971
|
-
return await entry.
|
|
13365
|
+
return await entry.attachments.read(attachmentId);
|
|
12972
13366
|
},
|
|
12973
|
-
async
|
|
13367
|
+
async removeSessionAttachment(sessionId, attachmentId, context) {
|
|
12974
13368
|
const entry = byId.get(sessionId);
|
|
12975
13369
|
if (!entry) throw new SessionNotFoundError(sessionId);
|
|
12976
13370
|
resolveTrustedClientId(entry, context?.clientId);
|
|
12977
|
-
return await entry.
|
|
13371
|
+
return await entry.attachments.remove(attachmentId);
|
|
13372
|
+
},
|
|
13373
|
+
async deleteSessionAttachments(sessionId) {
|
|
13374
|
+
const store = byId.get(sessionId)?.attachments ?? new SessionAttachmentStore(opts.sessionAttachmentsRoot, sessionId);
|
|
13375
|
+
await store.delete();
|
|
12978
13376
|
},
|
|
12979
13377
|
removePendingPrompt(sessionId, promptId, context) {
|
|
12980
13378
|
const entry = byId.get(sessionId);
|
|
@@ -12994,7 +13392,6 @@ function createAcpSessionBridge(opts) {
|
|
|
12994
13392
|
);
|
|
12995
13393
|
if (target.state === "queued") {
|
|
12996
13394
|
entry.pendingPromptList.splice(idx, 1);
|
|
12997
|
-
removeQueuedMedia(entry, target.content);
|
|
12998
13395
|
} else {
|
|
12999
13396
|
target.removed = true;
|
|
13000
13397
|
}
|
|
@@ -13021,7 +13418,7 @@ function createAcpSessionBridge(opts) {
|
|
|
13021
13418
|
);
|
|
13022
13419
|
const trimmed = message.trim();
|
|
13023
13420
|
const mediaBlocks = (options?.content ?? []).filter(
|
|
13024
|
-
(block) => block.type === "image"
|
|
13421
|
+
(block) => block.type === "image" || block.type === "resource"
|
|
13025
13422
|
);
|
|
13026
13423
|
if (trimmed.length === 0 && mediaBlocks.length === 0) {
|
|
13027
13424
|
writeStderrLine(
|
|
@@ -13047,10 +13444,10 @@ function createAcpSessionBridge(opts) {
|
|
|
13047
13444
|
(pending) => pending.promptId === requestedMessageId
|
|
13048
13445
|
);
|
|
13049
13446
|
if (promoted) {
|
|
13050
|
-
const
|
|
13051
|
-
(block) => block.type === "image"
|
|
13447
|
+
const promotedMedia = (promoted.content ?? []).filter(
|
|
13448
|
+
(block) => block.type === "image" || block.type === "resource"
|
|
13052
13449
|
);
|
|
13053
|
-
const sameMedia = JSON.stringify(
|
|
13450
|
+
const sameMedia = JSON.stringify(promotedMedia) === JSON.stringify(mediaBlocks);
|
|
13054
13451
|
const promotedText = promoted.text === "[image]" && trimmed.length === 0 ? "" : promoted.text;
|
|
13055
13452
|
if (promotedText === trimmed && sameMedia) {
|
|
13056
13453
|
return { accepted: true, messageId: requestedMessageId };
|
|
@@ -13073,23 +13470,23 @@ function createAcpSessionBridge(opts) {
|
|
|
13073
13470
|
);
|
|
13074
13471
|
return { accepted: false };
|
|
13075
13472
|
}
|
|
13076
|
-
entry.
|
|
13077
|
-
const inlineBytes =
|
|
13473
|
+
entry.attachments.assertReferences(mediaBlocks);
|
|
13474
|
+
const inlineBytes = inlineAttachmentBlockBytes(mediaBlocks);
|
|
13078
13475
|
if (inlineBytes > 0) {
|
|
13079
13476
|
const queuedInlineBytes = entry.midTurnMessageQueue.reduce(
|
|
13080
|
-
(total, queued) => total +
|
|
13477
|
+
(total, queued) => total + inlineAttachmentBlockBytes(queued.content ?? []),
|
|
13081
13478
|
0
|
|
13082
13479
|
);
|
|
13083
|
-
if (queuedInlineBytes + inlineBytes >
|
|
13480
|
+
if (queuedInlineBytes + inlineBytes > MAX_QUEUED_INLINE_ATTACHMENT_BYTES) {
|
|
13084
13481
|
writeStderrLine(
|
|
13085
|
-
`[mid-turn] session=${entry.sessionId} rejected: queued inline
|
|
13482
|
+
`[mid-turn] session=${entry.sessionId} rejected: queued inline attachments exceed the ${MAX_QUEUED_INLINE_ATTACHMENT_BYTES}-byte session budget`
|
|
13086
13483
|
);
|
|
13087
13484
|
return { accepted: false };
|
|
13088
13485
|
}
|
|
13089
13486
|
}
|
|
13090
|
-
const messageId = requestedMessageId ??
|
|
13091
|
-
if (entry.pendingPromptCount === 0) {
|
|
13092
|
-
if (options?.queueOnly) {
|
|
13487
|
+
const messageId = requestedMessageId ?? randomUUID2();
|
|
13488
|
+
if (entry.pendingPromptCount === 0 && entry.goalTurnActive !== true) {
|
|
13489
|
+
if (options?.queueOnly || options?.rejectIfIdle) {
|
|
13093
13490
|
writeStderrLine(
|
|
13094
13491
|
`[mid-turn] session=${JSON.stringify(entry.sessionId)} rejected id ${JSON.stringify(messageId)}: session idle`
|
|
13095
13492
|
);
|
|
@@ -13173,7 +13570,6 @@ function createAcpSessionBridge(opts) {
|
|
|
13173
13570
|
const [removed] = entry.midTurnMessageQueue.splice(index, 1);
|
|
13174
13571
|
rememberMidTurnId(entry.settledMidTurnMessageIds, messageId);
|
|
13175
13572
|
if (removed) {
|
|
13176
|
-
removeQueuedMedia(entry, removed.content);
|
|
13177
13573
|
try {
|
|
13178
13574
|
entry.events.publish({
|
|
13179
13575
|
type: "pending_prompt_completed",
|
|
@@ -13735,7 +14131,7 @@ function createAcpSessionBridge(opts) {
|
|
|
13735
14131
|
]);
|
|
13736
14132
|
},
|
|
13737
14133
|
generateWorkspaceContent(prompt, signal, _originatorClientId) {
|
|
13738
|
-
const requestId =
|
|
14134
|
+
const requestId = randomUUID2();
|
|
13739
14135
|
const queue = new GenerationStreamQueue(
|
|
13740
14136
|
GENERATION_STREAM_QUEUE_CAPACITY
|
|
13741
14137
|
);
|
|
@@ -13914,9 +14310,9 @@ function createAcpSessionBridge(opts) {
|
|
|
13914
14310
|
closingChannel,
|
|
13915
14311
|
`force kill closing session ${JSON.stringify(sessionId)}`
|
|
13916
14312
|
);
|
|
13917
|
-
await
|
|
14313
|
+
await entry.attachments.close().catch((releaseError) => {
|
|
13918
14314
|
writeStderrLine(
|
|
13919
|
-
`qwen serve: failed to
|
|
14315
|
+
`qwen serve: failed to close attachments for killed session ${JSON.stringify(sessionId)}: ${releaseError instanceof Error ? releaseError.message : String(releaseError)}`
|
|
13920
14316
|
);
|
|
13921
14317
|
});
|
|
13922
14318
|
return true;
|
|
@@ -13946,11 +14342,6 @@ function createAcpSessionBridge(opts) {
|
|
|
13946
14342
|
ci,
|
|
13947
14343
|
`force kill session ${JSON.stringify(sessionId)}`
|
|
13948
14344
|
);
|
|
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
|
-
});
|
|
13954
14345
|
return true;
|
|
13955
14346
|
}
|
|
13956
14347
|
entry.closing = false;
|
|
@@ -13987,9 +14378,9 @@ function createAcpSessionBridge(opts) {
|
|
|
13987
14378
|
} catch {
|
|
13988
14379
|
}
|
|
13989
14380
|
entry.events.close();
|
|
13990
|
-
await
|
|
14381
|
+
await entry.attachments.close().catch((error) => {
|
|
13991
14382
|
writeStderrLine(
|
|
13992
|
-
`qwen serve: failed to
|
|
14383
|
+
`qwen serve: failed to close attachments for killed session ${JSON.stringify(sessionId)}: ${error instanceof Error ? error.message : String(error)}`
|
|
13993
14384
|
);
|
|
13994
14385
|
});
|
|
13995
14386
|
if (ci && hasNoChannelWork(ci)) {
|
|
@@ -14096,8 +14487,7 @@ function createAcpSessionBridge(opts) {
|
|
|
14096
14487
|
) : Promise.resolve();
|
|
14097
14488
|
const teardownResults = await Promise.allSettled([
|
|
14098
14489
|
...channels.map((ci) => ci.channel.kill()),
|
|
14099
|
-
...[...
|
|
14100
|
-
mediaPutQueue,
|
|
14490
|
+
...[...byId.values()].map((entry) => entry.attachments.close()),
|
|
14101
14491
|
...inFlightSessionAwaits,
|
|
14102
14492
|
...inFlightRestoreAwaits,
|
|
14103
14493
|
inFlightChannelAwait
|