@qwen-code/qwen-code 0.19.11 → 0.19.12-preview.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundled/batch/SKILL.md +6 -0
- package/bundled/qc-helper/docs/configuration/model-providers.md +11 -0
- package/bundled/qc-helper/docs/configuration/settings.md +11 -10
- package/bundled/qc-helper/docs/features/channels/overview.md +66 -11
- package/bundled/qc-helper/docs/features/sub-agents.md +8 -8
- package/bundled/qc-helper/docs/features/worktree.md +2 -2
- package/bundled/qc-helper/docs/qwen-serve-deploy-local.md +42 -7
- package/bundled/qc-helper/docs/qwen-serve.md +102 -40
- package/bundled/qc-helper/docs/reference/keyboard-shortcuts.md +1 -1
- package/bundled/review/SKILL.md +60 -49
- package/bundled/simplify/SKILL.md +1 -1
- package/chunks/{MaxSizedBox-L6TGYDM3.js → MaxSizedBox-3KIWAU6Z.js} +31 -32
- package/chunks/{StandaloneSessionPicker-AKEQHU5P.js → StandaloneSessionPicker-TF626NO7.js} +45 -46
- package/chunks/acp-startup-profiler-N3RHHXJ3.js +25 -0
- package/chunks/{acpAgent-PTNBGJDN.js → acpAgent-JDVJXVBO.js} +1863 -507
- package/chunks/{agent-AJOMOZPJ.js → agent-BONWC4VY.js} +26 -27
- package/chunks/{agent-headless-CYKOMAXS.js → agent-headless-H7HKMGLZ.js} +26 -27
- package/chunks/{anthropicContentGenerator-HBRXJSP4.js → anthropicContentGenerator-ZZRGFEES.js} +35 -12
- package/chunks/{artifact-tool-MIZLXBLF.js → artifact-tool-PHO5XEGZ.js} +5 -5
- package/chunks/{askUserQuestion-XMJVPNWM.js → askUserQuestion-CEPBT47X.js} +2 -47
- package/chunks/{bridge-QKISWPCI.js → bridge-ATN2TLWJ.js} +31 -32
- package/chunks/{ca-CODEN7TD.js → ca-2SL2BXTK.js} +3 -2
- package/chunks/{channel-worker-group-SOUWTFHC.js → channel-worker-group-S3H5QHTI.js} +4 -4
- package/chunks/{channel-worker-manager-LOVSV3WW.js → channel-worker-manager-ZJ4HTMO2.js} +4 -4
- package/chunks/{channel-worker-supervisor-XW6MHJBQ.js → channel-worker-supervisor-JA6VZ5V5.js} +3 -3
- package/chunks/{chunk-ZIXOTAPZ.js → chunk-2DZ7E27L.js} +92 -3
- package/chunks/{chunk-L5U3ELZX.js → chunk-335ECZTA.js} +1 -1
- package/chunks/{chunk-2FO5GFKZ.js → chunk-3DJY4IFO.js} +1 -1
- package/chunks/{chunk-4AGTGMCQ.js → chunk-3PE7OY2G.js} +12 -12
- package/chunks/{chunk-QOTQH4CB.js → chunk-4AGBO6RB.js} +27 -10
- package/chunks/{chunk-Y66VOBRP.js → chunk-4CA4WUMS.js} +2 -2
- package/chunks/{chunk-LQIDP6K5.js → chunk-4CHDYDG3.js} +1 -1
- package/chunks/{chunk-574PTLMU.js → chunk-4OVECYBM.js} +407 -92
- package/chunks/{chunk-TV6K2FB4.js → chunk-4RPARQ5D.js} +2 -2
- package/chunks/{chunk-TL4R5TRK.js → chunk-4W55BHOC.js} +2 -2
- package/chunks/{chunk-RCEEXIOO.js → chunk-4XCVGEEX.js} +3 -3
- package/chunks/{chunk-3DWIFU7L.js → chunk-53UMEONK.js} +1 -1
- package/chunks/{chunk-AU3MFJPL.js → chunk-54KPEDM2.js} +8 -8
- package/chunks/{chunk-T76DGHGG.js → chunk-66F4IJ4L.js} +5 -5
- package/chunks/{chunk-YLSSEUAM.js → chunk-675SVDMD.js} +354 -278
- package/chunks/{chunk-NVTQZXR7.js → chunk-6QGZVKOO.js} +91 -52
- package/chunks/{chunk-NJOFRXTM.js → chunk-6TDA4EVC.js} +4200 -3450
- package/chunks/{chunk-BYH2JRK3.js → chunk-6WZZHJSZ.js} +5 -5
- package/chunks/{chunk-7X7TEQNX.js → chunk-76BFY7AF.js} +13 -0
- package/chunks/chunk-7KS72E2N.js +883 -0
- package/chunks/{chunk-CF5VJRGC.js → chunk-7LMAKIWE.js} +1 -1
- package/chunks/{chunk-WMNXXRGL.js → chunk-7O7WZH7N.js} +31 -31
- package/chunks/{chunk-7ZYHLN67.js → chunk-7OZGMFHC.js} +26 -75
- package/chunks/{chunk-6WPJRYLZ.js → chunk-7SX6WZNO.js} +3 -3
- package/chunks/{chunk-JGUT3LWZ.js → chunk-ANRANWVE.js} +4 -1
- package/chunks/{chunk-JD44PNGJ.js → chunk-AWOU24F6.js} +10 -5
- package/chunks/{chunk-6WGZDD67.js → chunk-BEFQGC6H.js} +2 -2
- package/chunks/{chunk-KXYJPRT5.js → chunk-BEZPRKD3.js} +28 -6
- package/chunks/{chunk-FYQ22K62.js → chunk-CHVH4DVN.js} +6 -5
- package/chunks/{chunk-LS56TX3M.js → chunk-CMHJEUVB.js} +1 -1
- package/chunks/{chunk-FXKOAEXP.js → chunk-CXWUXRD5.js} +14 -14
- package/chunks/{chunk-CAHY5ABC.js → chunk-DULSE2SH.js} +1 -1
- package/chunks/{chunk-SQ5BK3GO.js → chunk-DYUPBU7H.js} +1 -1
- package/chunks/{chunk-FNX3LGAK.js → chunk-E655RDRL.js} +1 -1
- package/chunks/{chunk-N5VIZTND.js → chunk-EWPLL4OT.js} +1 -1
- package/chunks/{chunk-FSA7ERJ2.js → chunk-F2RR4HO2.js} +1 -1
- package/chunks/{chunk-S63Z5V42.js → chunk-F2YCCUXI.js} +4 -4
- package/chunks/{chunk-3AYLDB6B.js → chunk-FEZXQXW2.js} +1 -1
- package/chunks/{chunk-OWT2CAEQ.js → chunk-GEHSF7MS.js} +105 -12
- package/chunks/{chunk-LXLTBIDP.js → chunk-HCCR43AY.js} +1 -1
- package/chunks/{chunk-7NMU22Q3.js → chunk-HQ7MDVBO.js} +18 -7
- package/chunks/{chunk-KSZKSE23.js → chunk-HVWPSGDY.js} +1 -1
- package/chunks/{chunk-YFVO2HOR.js → chunk-HZXU6YZW.js} +5 -5
- package/chunks/{chunk-HASK4LMI.js → chunk-IKLWU6YS.js} +13 -6
- package/chunks/{chunk-GNBBAQ6J.js → chunk-ILQ42UG6.js} +111 -40
- package/chunks/{chunk-THXDQSTA.js → chunk-IQRQVPGN.js} +49 -154
- package/chunks/{chunk-SPJQO2CE.js → chunk-J2MKYJKZ.js} +2 -2
- package/chunks/{chunk-SUARMD4Q.js → chunk-J6NT5YTN.js} +28 -2
- package/chunks/{chunk-TYLOFD2U.js → chunk-JCJPZMJV.js} +1 -1
- package/chunks/{chunk-BYB3GF2T.js → chunk-JCYMQU5F.js} +133 -6
- package/chunks/{chunk-6EDDYPI3.js → chunk-JUNVFQVY.js} +4 -4
- package/chunks/{chunk-CH2XVB47.js → chunk-K7P34F2J.js} +3 -3
- package/chunks/{chunk-5VWYKIMW.js → chunk-KANTXY7B.js} +2 -2
- package/chunks/{chunk-K7VD4XLT.js → chunk-LHEQDKAR.js} +1 -1
- package/chunks/{chunk-A2HWMJVO.js → chunk-LKR7QQ63.js} +3 -3
- package/chunks/{chunk-4HUDDSO5.js → chunk-LLIGYAQU.js} +4 -4
- package/chunks/{chunk-5Z452MMD.js → chunk-LODZMRXC.js} +154 -83
- package/chunks/{chunk-FBU7WRZI.js → chunk-LPHGXXZX.js} +6 -1
- package/chunks/{chunk-CPFIQVZJ.js → chunk-LYFDJTXE.js} +1 -1
- package/chunks/{chunk-TIOE2OPE.js → chunk-MCYZTKBV.js} +2 -2
- package/chunks/{chunk-ZQIYGQCG.js → chunk-MHEZV3OY.js} +506 -143
- package/chunks/{chunk-JWICTOXS.js → chunk-NGTQA57Y.js} +2 -2
- package/chunks/{chunk-5CNYZ7TN.js → chunk-NJQPQ4IO.js} +7 -7
- package/chunks/chunk-NSZJQACR.js +45 -0
- package/chunks/{chunk-DOPUYNXO.js → chunk-NUHSLBJZ.js} +7 -7
- package/chunks/{chunk-CITWNIXJ.js → chunk-NVUGS23Y.js} +5 -5
- package/chunks/{chunk-2Z5UX4KI.js → chunk-OSSDHJDU.js} +1 -1
- package/chunks/{chunk-YUZI3WAC.js → chunk-OWAK7LMW.js} +7 -0
- package/chunks/{chunk-Y3KFTWVX.js → chunk-OZWJAFFE.js} +6 -6
- package/chunks/{chunk-YGYSMY2R.js → chunk-PSISZNIT.js} +1629 -1142
- package/chunks/{chunk-4ROQY23C.js → chunk-PTXVHS2O.js} +7 -7
- package/chunks/{chunk-OKAIGAYW.js → chunk-QGONRHUS.js} +3 -3
- package/chunks/{chunk-PZL23GTM.js → chunk-QR6U5QPP.js} +8 -0
- package/chunks/chunk-QSG4ZFG4.js +257 -0
- package/chunks/{chunk-BXBDC476.js → chunk-R32BTEZY.js} +5 -5
- package/chunks/{chunk-AVEOWVOM.js → chunk-R3VWUU2E.js} +1 -1
- package/chunks/{chunk-RP5R7MB6.js → chunk-R4RIMOJL.js} +12 -12
- package/chunks/{chunk-ARKANCNX.js → chunk-SGPFJMRP.js} +1 -1
- package/chunks/{chunk-3M75MSVA.js → chunk-SMASS3CY.js} +1 -1
- package/chunks/{chunk-4IJMTYCB.js → chunk-SNONG66P.js} +818 -29
- package/chunks/chunk-TDKQP3M6.js +201 -0
- package/chunks/{chunk-VFX7EZIR.js → chunk-TFV3XVAZ.js} +8 -1
- package/chunks/{chunk-4LD5APFL.js → chunk-TYQMGACW.js} +1 -0
- package/chunks/{chunk-7NFB7LBQ.js → chunk-UE5TZ55T.js} +8 -0
- package/chunks/{chunk-F333XEAU.js → chunk-UOA2IHRI.js} +4 -3
- package/chunks/{chunk-VRR65QYW.js → chunk-V4PCIS25.js} +5 -1
- package/chunks/{chunk-WIEO4CWB.js → chunk-VAJS2E2D.js} +1 -1
- package/chunks/{chunk-GLNHPRZT.js → chunk-W4DFAUAO.js} +1 -1
- package/chunks/{chunk-STZQCNN3.js → chunk-W7H223ZZ.js} +1 -1
- package/chunks/{chunk-6Y6ORE2G.js → chunk-WACI4VES.js} +288 -20
- package/chunks/{chunk-WTNZ6DXB.js → chunk-WEPXQKGP.js} +1 -1
- package/chunks/{chunk-4BJVSIS3.js → chunk-WHQNBBWW.js} +2 -2
- package/chunks/{chunk-QDJ2R4CM.js → chunk-WTHRMVKB.js} +3 -3
- package/chunks/{chunk-L4Y55KIS.js → chunk-X6YQWCIJ.js} +1 -1
- package/chunks/{chunk-Q6TUALBE.js → chunk-XAAEDML2.js} +1 -1
- package/chunks/{chunk-BUAXJVNP.js → chunk-XACBIZJB.js} +3 -3
- package/chunks/{chunk-2OG646IN.js → chunk-XFJU7SVP.js} +4 -4
- package/chunks/{chunk-KKRTYONM.js → chunk-XSPFQQRE.js} +3 -3
- package/chunks/{chunk-V2DXTLUE.js → chunk-Y5UDBQYF.js} +3 -3
- package/chunks/{chunk-MQOVXZAF.js → chunk-YN2I5I42.js} +529 -61
- package/chunks/{chunk-FMNYGWOD.js → chunk-Z4ZCVYJ5.js} +14 -8
- package/chunks/{chunk-SY7NEYX4.js → chunk-ZFHHBRRA.js} +2 -2
- package/chunks/{chunk-QYG4BY6Q.js → chunk-ZPVGEMVC.js} +1 -1
- package/chunks/{computer-use-VZZMJEQ7.js → computer-use-UY4A72X7.js} +26 -27
- package/chunks/{config-utils-IQQT3GCI.js → config-utils-KWTRFP7D.js} +3 -3
- package/chunks/{contextCommand-PORKIZSY.js → contextCommand-3DZ2SVH6.js} +30 -31
- package/chunks/{create-sub-session-EAB2U5XW.js → create-sub-session-DIJOV6HV.js} +2 -2
- package/chunks/{create-sub-session-XVFKHAFW.js → create-sub-session-OT7WXLDO.js} +27 -28
- package/chunks/{cron-create-GMVKSXZT.js → cron-create-X462ERYA.js} +4 -4
- package/chunks/{cron-delete-VDZKUAVK.js → cron-delete-SL5UJUM3.js} +4 -4
- package/chunks/{cron-list-UG7C7RAR.js → cron-list-3MD6SVXI.js} +4 -4
- package/chunks/{daemon-IHR6WSPB.js → daemon-ZW6LHOXT.js} +91 -14
- package/chunks/{daemon-status-provider-ABLBA3UJ.js → daemon-status-provider-GTZOYSBO.js} +35 -36
- package/chunks/{de-NOXPCSYN.js → de-I7ZIYXZC.js} +3 -2
- package/chunks/{dist-PX2ERZ6I.js → dist-HCUUS6IH.js} +2 -2
- package/chunks/{dist-VYWUKURL.js → dist-O2IP3G5D.js} +1 -1
- package/chunks/{dist-GXJVCOS7.js → dist-RZBJT5O2.js} +2 -1
- package/chunks/{dist-V2YVLYOW.js → dist-Y54RURGT.js} +3 -1
- package/chunks/{dist-DOPL5LSQ.js → dist-YTPTCUAD.js} +1 -1
- package/chunks/{dist-4WCQEZIN.js → dist-ZJHKKWUD.js} +1 -1
- package/chunks/{earlyInputCapture-DJCU5SPU.js → earlyInputCapture-GGWVGBZ7.js} +27 -28
- package/chunks/{edit-O4VV5AO6.js → edit-JN467GIR.js} +27 -28
- package/chunks/{en-JFVULHTB.js → en-XE34GKAA.js} +7 -3
- package/chunks/{enter-worktree-XQYDDI2I.js → enter-worktree-MMO4VBQE.js} +26 -27
- package/chunks/{enterPlanMode-CESVMQBV.js → enterPlanMode-BRZOG4DB.js} +27 -30
- package/chunks/{environment-5KXOLZNR.js → environment-LOCDCWMZ.js} +29 -30
- package/chunks/{errors-EBUTCBAQ.js → errors-XXSL5HGG.js} +29 -30
- package/chunks/{exit-worktree-MWGNSPNX.js → exit-worktree-UD7PI5H5.js} +26 -27
- package/chunks/exitPlanMode-EIUETQI6.js +389 -0
- package/chunks/{fast-path-6V73F2T2.js → fast-path-ULGAEUVK.js} +2 -2
- package/chunks/{fr-HVFNU42H.js → fr-X7KDVZIY.js} +3 -2
- package/chunks/{gemini-TEFJZCIZ.js → gemini-KW3APZ4P.js} +133 -80
- package/chunks/{geminiContentGenerator-M56BEXWI.js → geminiContentGenerator-4BQ5QHPR.js} +5 -5
- package/chunks/{glob-DMYFEEAZ.js → glob-FPKAMR6B.js} +32 -28
- package/chunks/{grep-GYE47MD4.js → grep-MOGRCYB4.js} +32 -28
- package/chunks/{handleAutoUpdate-OLUY4L7L.js → handleAutoUpdate-QUMRZZOS.js} +33 -34
- package/chunks/{i18n-462JC7IY.js → i18n-F3W6YUYP.js} +28 -29
- package/chunks/{initializer-Y7WD4D2I.js → initializer-KLU2KAIZ.js} +33 -34
- package/chunks/{installationInfo-I2Z3BKCE.js → installationInfo-P3ZP2SIZ.js} +27 -28
- package/chunks/{ja-PY5AF544.js → ja-2ICT3KXF.js} +3 -2
- package/chunks/{keychain-token-storage-AU22CQI6.js → keychain-token-storage-K23CFKGN.js} +2 -2
- package/chunks/{list-XQ5MSAXP.js → list-4X6D5JD2.js} +35 -36
- package/chunks/{loadedSettingsAdapter-TQOWYE7C.js → loadedSettingsAdapter-446B6WKA.js} +32 -33
- package/chunks/{loop-wakeup-QXWZSCYM.js → loop-wakeup-6H7OENTB.js} +5 -5
- package/chunks/{ls-2OUTG3IZ.js → ls-APTSOOS5.js} +4 -4
- package/chunks/{lsp-4VMNXZW6.js → lsp-HPACPJAN.js} +2 -2
- package/chunks/{mcp-22LLEEVM.js → mcp-JYVOJZOD.js} +32 -33
- package/chunks/{monitor-VKG324X3.js → monitor-KY7YH7TL.js} +26 -27
- package/chunks/nonInteractiveCli-EK35TLVJ.js +129 -0
- package/chunks/{notebook-edit-FJJRBQ3S.js → notebook-edit-IHGW42QK.js} +27 -28
- package/chunks/{openaiContentGenerator-4T2OGTR5.js → openaiContentGenerator-FURUCKQJ.js} +13 -14
- package/chunks/{pidfile-XL3MDCBM.js → pidfile-WKUVXDMR.js} +27 -28
- package/chunks/{processUtils-7UCFN34D.js → processUtils-LHSRN76X.js} +2 -2
- package/chunks/{pt-A3PRQXMU.js → pt-JJ4XPIBP.js} +3 -2
- package/chunks/{qwenContentGenerator-PQUXJDIZ.js → qwenContentGenerator-NRLM7R36.js} +30 -31
- package/chunks/{qwenOAuth2-LEYOU7RU.js → qwenOAuth2-5FNX3AWH.js} +22 -5
- package/chunks/{read-file-3EYQML7E.js → read-file-VLEAEXFP.js} +9 -10
- package/chunks/{read-mcp-resource-JUFHCKSC.js → read-mcp-resource-C6NT52T6.js} +2 -2
- package/chunks/{record-artifact-DWSMBXYY.js → record-artifact-ENCU7QCL.js} +2 -2
- package/chunks/{ripGrep-S6WPGQNA.js → ripGrep-MT23EIDD.js} +26 -27
- package/chunks/{ru-IBCWUTOC.js → ru-STR4KTW7.js} +3 -2
- package/chunks/{run-qwen-serve-NSKBT3HU.js → run-qwen-serve-5HWOQFLI.js} +63 -47
- package/chunks/{runtime-LG5ZZ3VH.js → runtime-6IVKJSLW.js} +38 -37
- package/chunks/{scheduler-PLX3VVTB.js → scheduler-63GJG75U.js} +26 -27
- package/chunks/{send-message-JZ752NWD.js → send-message-5GZ4FX2V.js} +3 -3
- package/chunks/{serve-S2ZLRZZR.js → serve-3LL7RRDP.js} +32 -33
- package/chunks/{server-5ECMV4TM.js → server-AA24QLPA.js} +1672 -615
- package/chunks/{session-ILSONWG4.js → session-LRVCFQQQ.js} +102 -75
- package/chunks/{settings-BOE7WWSA.js → settings-ZX3OKUT4.js} +36 -37
- package/chunks/{shell-VW664JIZ.js → shell-KR3IMYH6.js} +26 -27
- package/chunks/{skill-COHV6625.js → skill-QLM2LSF7.js} +11 -12
- package/chunks/{spawnChannel-5UUR5XOZ.js → spawnChannel-6WFOK3SA.js} +28 -29
- package/chunks/{src-XPKFZ3RN.js → src-ADLNIPHD.js} +101 -72
- package/chunks/{standalone-update-IOOJ2NZQ.js → standalone-update-C54OTJWJ.js} +29 -30
- package/chunks/{startInteractiveUI-3NGJGXXS.js → startInteractiveUI-KFAOS6HC.js} +2342 -1796
- package/chunks/{stdioHelpers-UMY72QRP.js → stdioHelpers-HGIYTWAY.js} +3 -1
- package/chunks/{syntheticOutput-LELY6HAI.js → syntheticOutput-ULOVVLY4.js} +3 -3
- package/chunks/{task-create-QY3BIMNM.js → task-create-DUE2PMNI.js} +7 -7
- package/chunks/{task-list-D2U47WBJ.js → task-list-WVPNX7BZ.js} +5 -5
- package/chunks/{task-stop-N6E5IYLH.js → task-stop-CPEQWOT6.js} +2 -2
- package/chunks/{task-update-HJCQILLB.js → task-update-HY2LNFFB.js} +7 -7
- package/chunks/{team-create-UPLVZQFX.js → team-create-Q5B5M7UD.js} +26 -27
- package/chunks/{team-delete-RCWYDRF4.js → team-delete-JJV6IUOA.js} +5 -5
- package/chunks/{team-plan-approval-F5F432RO.js → team-plan-approval-J55PXNY2.js} +26 -27
- package/chunks/{theme-manager-JJE4BJ67.js → theme-manager-QWTDRPHV.js} +27 -28
- package/chunks/todoWrite-JHHIDOIV.js +358 -0
- package/chunks/{tool-search-LRXI4JLZ.js → tool-search-LSSKWZKH.js} +10 -11
- package/chunks/{total-session-admission-I4DHN6UP.js → total-session-admission-S6ATY5HY.js} +32 -33
- package/chunks/{trustedFolders-SEH7LNX2.js → trustedFolders-CY4TUPDJ.js} +28 -29
- package/chunks/turndown.cjs-FZHGMUTY.js +17670 -0
- package/chunks/{update-relaunch-T6ZKBUA6.js → update-relaunch-IOKOUV3K.js} +6 -6
- package/chunks/{updateCheck-FWLXZPRO.js → updateCheck-YNRFE4V7.js} +30 -31
- package/chunks/{validateNonInterActiveAuth-X6K2VWYT.js → validateNonInterActiveAuth-OXTECS4B.js} +68 -68
- package/chunks/{version-LIFSOGSE.js → version-2CZQQDL5.js} +1 -1
- package/chunks/web-fetch-7QTEGJI5.js +938 -0
- package/chunks/{workflow-NX2DFWGD.js → workflow-G3CZU256.js} +29 -30
- package/chunks/{workspace-providers-status-VYD6M2NE.js → workspace-providers-status-UHQOIPAZ.js} +35 -36
- package/chunks/{workspace-registration-store-2Y6PWOEL.js → workspace-registration-store-5WPCMX4F.js} +1 -1
- package/chunks/{workspace-registry-PKBDBWCA.js → workspace-registry-LAQCRQTH.js} +32 -33
- package/chunks/{workspace-service-HHORUHTS.js → workspace-service-6ZEUJY2Z.js} +38 -39
- package/chunks/{workspace-skills-status-O5Q26LIY.js → workspace-skills-status-YG6OITSM.js} +33 -34
- package/chunks/{write-file-NVAEZ3J2.js → write-file-E7T3PU3B.js} +60 -28
- package/chunks/{zh-PAUNIMHQ.js → zh-6ANG2HTL.js} +7 -3
- package/chunks/{zh-TW-GNEUIUFF.js → zh-TW-4RR3YHNN.js} +7 -3
- package/cli-entry.js +37 -2
- package/cli.js +17 -11
- package/locales/ca.js +3 -2
- package/locales/de.js +3 -2
- package/locales/en.js +10 -5
- package/locales/fr.js +3 -2
- package/locales/ja.js +3 -2
- package/locales/pt.js +3 -2
- package/locales/ru.js +3 -2
- package/locales/zh-TW.js +9 -3
- package/locales/zh.js +9 -3
- package/package.json +3 -3
- package/web-shell/assets/{arc-H74fE8UR.js → arc-_dVIKMdB.js} +1 -1
- package/web-shell/assets/{architectureDiagram-3BPJPVTR-DN3kEq-I.js → architectureDiagram-3BPJPVTR-MuN3nKpL.js} +1 -1
- package/web-shell/assets/{blockDiagram-GPEHLZMM-BrqbsFUF.js → blockDiagram-GPEHLZMM-BtmvJjzx.js} +1 -1
- package/web-shell/assets/{c4Diagram-AAUBKEIU-ClFhU1P-.js → c4Diagram-AAUBKEIU-Dvi58_BU.js} +1 -1
- package/web-shell/assets/channel-Bi5TehaT.js +1 -0
- package/web-shell/assets/{chunk-2J33WTMH-jCIcG0_M.js → chunk-2J33WTMH-YqxOVhS1.js} +1 -1
- package/web-shell/assets/{chunk-4BX2VUAB-DSkGe62-.js → chunk-4BX2VUAB-DoBgbC9z.js} +1 -1
- package/web-shell/assets/{chunk-55IACEB6-BxBHOGTd.js → chunk-55IACEB6-3NEQrBAr.js} +1 -1
- package/web-shell/assets/{chunk-727SXJPM-v_DS7dH7.js → chunk-727SXJPM-DrCZQxp0.js} +1 -1
- package/web-shell/assets/{chunk-AQP2D5EJ-1RzEKRPq.js → chunk-AQP2D5EJ-m_g3zjgv.js} +1 -1
- package/web-shell/assets/{chunk-FMBD7UC4-DyrSbLOX.js → chunk-FMBD7UC4-D1_crABJ.js} +1 -1
- package/web-shell/assets/{chunk-ND2GUHAM-BCmdsZiy.js → chunk-ND2GUHAM-BdhgVtBx.js} +1 -1
- package/web-shell/assets/{chunk-QZHKN3VN-CphHGW2D.js → chunk-QZHKN3VN-BlmThhm-.js} +1 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-BKhhRdd1.js +1 -0
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-BKhhRdd1.js +1 -0
- package/web-shell/assets/{cose-bilkent-S5V4N54A-D5kRC7Fi.js → cose-bilkent-S5V4N54A-Cbjm_00Z.js} +1 -1
- package/web-shell/assets/{dagre-BM42HDAG-DIiyJJ0U.js → dagre-BM42HDAG-C39QNVgC.js} +1 -1
- package/web-shell/assets/{diagram-2AECGRRQ-BOcuB8xU.js → diagram-2AECGRRQ-DNXSAixC.js} +1 -1
- package/web-shell/assets/{diagram-5GNKFQAL-CMgiZ4d3.js → diagram-5GNKFQAL-BCbGUPEA.js} +1 -1
- package/web-shell/assets/{diagram-KO2AKTUF-Ctx8pfN0.js → diagram-KO2AKTUF-1eujKSDC.js} +1 -1
- package/web-shell/assets/{diagram-LMA3HP47-BT5REAWC.js → diagram-LMA3HP47-DUMKXgql.js} +1 -1
- package/web-shell/assets/{diagram-OG6HWLK6-CJkUqXcp.js → diagram-OG6HWLK6-BFktU3_u.js} +1 -1
- package/web-shell/assets/{erDiagram-TEJ5UH35-DyvNNX6v.js → erDiagram-TEJ5UH35-BvJC7DLk.js} +1 -1
- package/web-shell/assets/{flowDiagram-I6XJVG4X-VBf8_My8.js → flowDiagram-I6XJVG4X-Cgu3PlOt.js} +1 -1
- package/web-shell/assets/{ganttDiagram-6RSMTGT7-CviJnR7B.js → ganttDiagram-6RSMTGT7-DLNXN5Xh.js} +1 -1
- package/web-shell/assets/{gitGraphDiagram-PVQCEYII-BY66_Oze.js → gitGraphDiagram-PVQCEYII-BQFRDv6R.js} +1 -1
- package/web-shell/assets/index-C_ouplMQ.js +1187 -0
- package/web-shell/assets/{index-DhYuvi3j.js → index-CdC3pjP3.js} +1 -1
- package/web-shell/assets/index-XGDFJE-X.css +5 -0
- package/web-shell/assets/{infoDiagram-5YYISTIA-D2jaewWZ.js → infoDiagram-5YYISTIA-DT2mOSvp.js} +1 -1
- package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-BpnNTyi5.js → ishikawaDiagram-YF4QCWOH-9fy_K4bd.js} +1 -1
- package/web-shell/assets/{journeyDiagram-JHISSGLW-CA55GNZF.js → journeyDiagram-JHISSGLW-CoGSEuhE.js} +1 -1
- package/web-shell/assets/{kanban-definition-UN3LZRKU-DyiSl_Ts.js → kanban-definition-UN3LZRKU-BP9hHYIj.js} +1 -1
- package/web-shell/assets/{linear-B-sN3dkV.js → linear-uIroDsmp.js} +1 -1
- package/web-shell/assets/{mermaid.core-xf9SXDdb.js → mermaid.core-BUwoStsA.js} +5 -5
- package/web-shell/assets/{mindmap-definition-RKZ34NQL-DXhr2kRk.js → mindmap-definition-RKZ34NQL-DZB-FWim.js} +1 -1
- package/web-shell/assets/{pieDiagram-4H26LBE5-DUXpbfGQ.js → pieDiagram-4H26LBE5-YPptloKl.js} +1 -1
- package/web-shell/assets/{quadrantDiagram-W4KKPZXB-NeDQYeWw.js → quadrantDiagram-W4KKPZXB-dgk3DSzm.js} +1 -1
- package/web-shell/assets/{requirementDiagram-4Y6WPE33-BSbFRL1A.js → requirementDiagram-4Y6WPE33-BH2En2i9.js} +1 -1
- package/web-shell/assets/{sankeyDiagram-5OEKKPKP-gg27cAaN.js → sankeyDiagram-5OEKKPKP-BB98feeI.js} +1 -1
- package/web-shell/assets/{sequenceDiagram-3UESZ5HK-Bi_1TSs4.js → sequenceDiagram-3UESZ5HK-CunAIGh8.js} +1 -1
- package/web-shell/assets/{stateDiagram-AJRCARHV-CboCCRaf.js → stateDiagram-AJRCARHV-DTJs_-I2.js} +1 -1
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-DrfFMYta.js +1 -0
- package/web-shell/assets/{timeline-definition-PNZ67QCA-DrGpF_jn.js → timeline-definition-PNZ67QCA-Cd4AN7O0.js} +1 -1
- package/web-shell/assets/{vennDiagram-CIIHVFJN-DCaJU67x.js → vennDiagram-CIIHVFJN-xIG-rUU9.js} +1 -1
- package/web-shell/assets/{wardley-L42UT6IY-p0QcW1aP.js → wardley-L42UT6IY-D1UyjIcG.js} +1 -1
- package/web-shell/assets/{wardleyDiagram-YWT4CUSO-DiEVxj1W.js → wardleyDiagram-YWT4CUSO-BVM0Mb99.js} +1 -1
- package/web-shell/assets/{xychartDiagram-2RQKCTM6-iQB8nSlA.js → xychartDiagram-2RQKCTM6-BX31JDSz.js} +1 -1
- package/web-shell/index.html +2 -2
- package/chunks/chunk-2HRYPZT5.js +0 -25
- package/chunks/chunk-QAW7PIHT.js +0 -168
- package/chunks/chunk-RTV5TUYB.js +0 -143
- package/chunks/chunk-ZPAHLFZU.js +0 -172
- package/chunks/exitPlanMode-HYQL4XMB.js +0 -909
- package/chunks/nonInteractiveCli-UMYUT643.js +0 -129
- package/chunks/todoWrite-FKCGATPJ.js +0 -531
- package/chunks/web-fetch-CFCWTCAP.js +0 -5673
- package/web-shell/assets/channel-NFC5ADAa.js +0 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-DHgwjz3X.js +0 -1
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-DHgwjz3X.js +0 -1
- package/web-shell/assets/index-8xIBbHV3.js +0 -1143
- package/web-shell/assets/index-DLyhlZZO.css +0 -5
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-CXRqms6P.js +0 -1
|
@@ -1,58 +1,55 @@
|
|
|
1
1
|
// Force strict mode and setup for ESM
|
|
2
2
|
"use strict";
|
|
3
3
|
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
recomputeMcpGating
|
|
5
|
+
} from "./chunk-6WZZHJSZ.js";
|
|
6
|
+
import {
|
|
7
|
+
classifyApiError
|
|
8
|
+
} from "./chunk-675SVDMD.js";
|
|
7
9
|
import {
|
|
8
10
|
EXTENSION_CONTEXT_BUDGET,
|
|
9
11
|
buildExtensionMentionContext,
|
|
10
12
|
buildMcpServerContextText,
|
|
13
|
+
extractAtPathCommands,
|
|
11
14
|
matchExtensionByRef,
|
|
12
15
|
matchMcpServerByRef,
|
|
13
16
|
parseExtensionRef,
|
|
14
17
|
parseMcpServerRef
|
|
15
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-IKLWU6YS.js";
|
|
16
19
|
import {
|
|
17
20
|
getAvailableCommands,
|
|
18
21
|
handleSlashCommand,
|
|
19
22
|
insertAfterFunctionResponses,
|
|
20
23
|
isSlashCommand,
|
|
21
24
|
normalizePartList
|
|
22
|
-
} from "./chunk-
|
|
23
|
-
import {
|
|
24
|
-
collectContextData,
|
|
25
|
-
formatContextUsageText
|
|
26
|
-
} from "./chunk-FMNYGWOD.js";
|
|
27
|
-
import {
|
|
28
|
-
recomputeMcpGating
|
|
29
|
-
} from "./chunk-BYH2JRK3.js";
|
|
25
|
+
} from "./chunk-IQRQVPGN.js";
|
|
30
26
|
import {
|
|
31
27
|
appEvents,
|
|
32
28
|
buildDisabledSkillNamesProvider,
|
|
33
29
|
loadCliConfig,
|
|
34
30
|
normalizeDisabledToolList
|
|
35
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-PSISZNIT.js";
|
|
32
|
+
import "./chunk-5DTTYNB7.js";
|
|
33
|
+
import {
|
|
34
|
+
collectContextData,
|
|
35
|
+
formatContextUsageText
|
|
36
|
+
} from "./chunk-Z4ZCVYJ5.js";
|
|
36
37
|
import {
|
|
37
38
|
getCommandSubcommandNames
|
|
38
|
-
} from "./chunk-
|
|
39
|
-
import "./chunk-
|
|
39
|
+
} from "./chunk-JCYMQU5F.js";
|
|
40
|
+
import "./chunk-CHVH4DVN.js";
|
|
40
41
|
import {
|
|
41
42
|
getEffectiveSupportedModes
|
|
42
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-6QGZVKOO.js";
|
|
43
44
|
import "./chunk-4WGODMVR.js";
|
|
44
45
|
import "./chunk-KW7NOTN6.js";
|
|
45
|
-
import "./chunk-
|
|
46
|
-
import "./chunk-
|
|
46
|
+
import "./chunk-GEHSF7MS.js";
|
|
47
|
+
import "./chunk-XAAEDML2.js";
|
|
48
|
+
import "./chunk-NVUGS23Y.js";
|
|
47
49
|
import "./chunk-NHDKSOEY.js";
|
|
48
|
-
import
|
|
49
|
-
|
|
50
|
-
} from "./chunk-7X7TEQNX.js";
|
|
51
|
-
import "./chunk-HTHUX2T5.js";
|
|
52
|
-
import "./chunk-TL4R5TRK.js";
|
|
53
|
-
import "./chunk-V2DXTLUE.js";
|
|
50
|
+
import "./chunk-4W55BHOC.js";
|
|
51
|
+
import "./chunk-Y5UDBQYF.js";
|
|
54
52
|
import "./chunk-YAF2MQZ6.js";
|
|
55
|
-
import "./chunk-Q6TUALBE.js";
|
|
56
53
|
import {
|
|
57
54
|
GENERATION_MAX_PROMPT_BYTES,
|
|
58
55
|
GENERATION_TIMEOUT_MS,
|
|
@@ -71,34 +68,51 @@ import {
|
|
|
71
68
|
shouldSuppressRememberErrorDetails,
|
|
72
69
|
workspaceMemoryFailureCode,
|
|
73
70
|
workspaceMemoryFailureDiagnostics
|
|
74
|
-
} from "./chunk-
|
|
71
|
+
} from "./chunk-4AGBO6RB.js";
|
|
75
72
|
import {
|
|
76
73
|
HistoryReplayer,
|
|
77
74
|
MessageEmitter,
|
|
78
75
|
PlanEmitter,
|
|
79
|
-
ToolCallEmitter
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
76
|
+
ToolCallEmitter,
|
|
77
|
+
collectGoalStatusItemsFromRecords,
|
|
78
|
+
goalTerminalEventToHistoryItem,
|
|
79
|
+
recordGoalStatusItem,
|
|
80
|
+
restoreGoalFromHistory
|
|
81
|
+
} from "./chunk-WACI4VES.js";
|
|
82
|
+
import "./chunk-QSG4ZFG4.js";
|
|
83
|
+
import "./chunk-7LMAKIWE.js";
|
|
84
|
+
import "./chunk-J6NT5YTN.js";
|
|
83
85
|
import "./chunk-QHTIBUWB.js";
|
|
86
|
+
import {
|
|
87
|
+
isTerminalGoalStatusKind
|
|
88
|
+
} from "./chunk-76BFY7AF.js";
|
|
89
|
+
import "./chunk-HTHUX2T5.js";
|
|
84
90
|
import "./chunk-L573Z2QZ.js";
|
|
85
91
|
import {
|
|
86
92
|
computeCpuPercent
|
|
87
93
|
} from "./chunk-HGT6JR3U.js";
|
|
88
94
|
import "./chunk-RXFQM6FQ.js";
|
|
89
|
-
import "./chunk-
|
|
95
|
+
import "./chunk-OZWJAFFE.js";
|
|
90
96
|
import "./chunk-6H67XLET.js";
|
|
91
|
-
import
|
|
92
|
-
|
|
97
|
+
import {
|
|
98
|
+
beginAcpBootstrapConfigProfiling,
|
|
99
|
+
buildAndFreezeAcpStartupProfile,
|
|
100
|
+
endAcpBootstrapConfigProfiling,
|
|
101
|
+
markAcpStartup
|
|
102
|
+
} from "./chunk-TDKQP3M6.js";
|
|
103
|
+
import "./chunk-LLIGYAQU.js";
|
|
93
104
|
import "./chunk-LXXMOYPL.js";
|
|
94
|
-
import "./chunk-
|
|
105
|
+
import "./chunk-F2YCCUXI.js";
|
|
95
106
|
import "./chunk-E5Z2AVNV.js";
|
|
96
107
|
import {
|
|
97
|
-
|
|
108
|
+
ACP_ROUTE_ID_PREFIX,
|
|
109
|
+
buildAcpModelOptions,
|
|
110
|
+
getCurrentAcpModelId,
|
|
98
111
|
parseAcpBaseModelId,
|
|
99
112
|
parseAcpModelOption,
|
|
113
|
+
resolveAcpModelOption,
|
|
100
114
|
sanitizeProviderBaseUrl
|
|
101
|
-
} from "./chunk-
|
|
115
|
+
} from "./chunk-2DZ7E27L.js";
|
|
102
116
|
import {
|
|
103
117
|
mapSkillConfigToStatus
|
|
104
118
|
} from "./chunk-2W3OOD4W.js";
|
|
@@ -108,44 +122,39 @@ import {
|
|
|
108
122
|
buildPermissionSettings,
|
|
109
123
|
normalizePermissionRules,
|
|
110
124
|
readPermissionRuleSet
|
|
111
|
-
} from "./chunk-
|
|
125
|
+
} from "./chunk-LHEQDKAR.js";
|
|
112
126
|
import {
|
|
113
127
|
MAX_AUDIO_BYTES,
|
|
114
128
|
sanitizeVoiceErrorMessage,
|
|
115
129
|
transcribeVoiceAudio
|
|
116
|
-
} from "./chunk-
|
|
130
|
+
} from "./chunk-XACBIZJB.js";
|
|
117
131
|
import {
|
|
118
132
|
readVoiceModel
|
|
119
|
-
} from "./chunk-
|
|
120
|
-
import "./chunk-
|
|
133
|
+
} from "./chunk-SMASS3CY.js";
|
|
134
|
+
import "./chunk-F2RR4HO2.js";
|
|
121
135
|
import {
|
|
122
136
|
parseSessionSource
|
|
123
|
-
} from "./chunk-
|
|
137
|
+
} from "./chunk-4OVECYBM.js";
|
|
138
|
+
import "./chunk-6RLROE6G.js";
|
|
139
|
+
import "./chunk-COH43MRJ.js";
|
|
124
140
|
import {
|
|
141
|
+
CHANNEL_STARTUP_PROFILE_META_KEY,
|
|
142
|
+
CHANNEL_STARTUP_PROFILE_VERSION,
|
|
125
143
|
CLIENT_MCP_OVER_WS_CONFIG_FLAG,
|
|
126
144
|
LOAD_REPLAY_BULK_MODE,
|
|
127
145
|
LOAD_REPLAY_META_KEY,
|
|
128
146
|
LOAD_REPLAY_MODE_META_KEY,
|
|
147
|
+
LOAD_REPLAY_PAGE_SIZE_META_KEY,
|
|
129
148
|
LOAD_REPLAY_VERSION,
|
|
130
|
-
MID_TURN_QUEUE_DRAIN_METHOD
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
import "./chunk-COH43MRJ.js";
|
|
134
|
-
import {
|
|
135
|
-
NOT_CURRENTLY_GENERATING_CANCEL_MESSAGE
|
|
136
|
-
} from "./chunk-L4Y55KIS.js";
|
|
137
|
-
import "./chunk-7NMU22Q3.js";
|
|
138
|
-
import "./chunk-YFVO2HOR.js";
|
|
139
|
-
import "./chunk-57OAHC2Y.js";
|
|
140
|
-
import "./chunk-5CNYZ7TN.js";
|
|
141
|
-
import "./chunk-FNX3LGAK.js";
|
|
142
|
-
import "./chunk-V6WHFGST.js";
|
|
143
|
-
import {
|
|
144
|
-
createLoadedSettingsAdapter
|
|
145
|
-
} from "./chunk-SQ5BK3GO.js";
|
|
149
|
+
MID_TURN_QUEUE_DRAIN_METHOD,
|
|
150
|
+
TODO_STOP_GUARD_QUEUE_RELEASE_METHOD
|
|
151
|
+
} from "./chunk-QR6U5QPP.js";
|
|
146
152
|
import {
|
|
147
153
|
ndJsonStream
|
|
148
|
-
} from "./chunk-
|
|
154
|
+
} from "./chunk-FEZXQXW2.js";
|
|
155
|
+
import {
|
|
156
|
+
NOT_CURRENTLY_GENERATING_CANCEL_MESSAGE
|
|
157
|
+
} from "./chunk-X6YQWCIJ.js";
|
|
149
158
|
import {
|
|
150
159
|
ACP_PREFLIGHT_KINDS,
|
|
151
160
|
IDLE_HOOK_EVENTS,
|
|
@@ -153,14 +162,23 @@ import {
|
|
|
153
162
|
SERVE_STATUS_EXT_METHODS,
|
|
154
163
|
STATUS_SCHEMA_VERSION,
|
|
155
164
|
mapDomainErrorToErrorKind
|
|
156
|
-
} from "./chunk-
|
|
165
|
+
} from "./chunk-TFV3XVAZ.js";
|
|
166
|
+
import "./chunk-HQ7MDVBO.js";
|
|
167
|
+
import "./chunk-HZXU6YZW.js";
|
|
168
|
+
import "./chunk-57OAHC2Y.js";
|
|
169
|
+
import "./chunk-NJQPQ4IO.js";
|
|
170
|
+
import "./chunk-E655RDRL.js";
|
|
171
|
+
import "./chunk-V6WHFGST.js";
|
|
172
|
+
import {
|
|
173
|
+
createLoadedSettingsAdapter
|
|
174
|
+
} from "./chunk-DYUPBU7H.js";
|
|
157
175
|
import "./chunk-W7FJ3N32.js";
|
|
158
|
-
import "./chunk-
|
|
176
|
+
import "./chunk-HVWPSGDY.js";
|
|
159
177
|
import "./chunk-TJTKSVIV.js";
|
|
160
178
|
import "./chunk-M5GB774H.js";
|
|
161
|
-
import "./chunk-
|
|
162
|
-
import "./chunk-
|
|
163
|
-
import "./chunk-
|
|
179
|
+
import "./chunk-HCCR43AY.js";
|
|
180
|
+
import "./chunk-53UMEONK.js";
|
|
181
|
+
import "./chunk-MHEZV3OY.js";
|
|
164
182
|
import {
|
|
165
183
|
AgentSideConnection,
|
|
166
184
|
PROTOCOL_VERSION,
|
|
@@ -169,48 +187,47 @@ import {
|
|
|
169
187
|
import {
|
|
170
188
|
assembleMcpServers,
|
|
171
189
|
loadMcpApprovals
|
|
172
|
-
} from "./chunk-
|
|
190
|
+
} from "./chunk-PTXVHS2O.js";
|
|
173
191
|
import {
|
|
174
|
-
OUTPUT_LANGUAGE_AUTO,
|
|
175
192
|
getOutputLanguageFilePath,
|
|
176
193
|
getPersistScopeForModelSelection,
|
|
177
194
|
getUserSettingsPath,
|
|
178
|
-
isAutoLanguage,
|
|
179
195
|
loadSettings,
|
|
180
|
-
|
|
196
|
+
resolveOutputLanguageOrPreserveAuto,
|
|
181
197
|
updateOutputLanguageFile,
|
|
182
198
|
writeOutputLanguageAndRegisterPath
|
|
183
|
-
} from "./chunk-
|
|
199
|
+
} from "./chunk-ILQ42UG6.js";
|
|
184
200
|
import "./chunk-RKUWKYED.js";
|
|
201
|
+
import "./chunk-GOXKNSDZ.js";
|
|
202
|
+
import {
|
|
203
|
+
getSystemDefaultsPath,
|
|
204
|
+
getSystemSettingsPath
|
|
205
|
+
} from "./chunk-IDS7MSUP.js";
|
|
185
206
|
import {
|
|
186
207
|
SUPPORTED_LANGUAGES,
|
|
187
208
|
getCurrentLanguage,
|
|
188
209
|
setLanguageAsync
|
|
189
|
-
} from "./chunk-
|
|
210
|
+
} from "./chunk-3PE7OY2G.js";
|
|
190
211
|
import {
|
|
191
212
|
findEnvFiles,
|
|
192
213
|
preResolveHomeEnvOverrides,
|
|
193
214
|
reloadEnvironment
|
|
194
|
-
} from "./chunk-
|
|
195
|
-
import "./chunk-GOXKNSDZ.js";
|
|
196
|
-
import {
|
|
197
|
-
getSystemDefaultsPath,
|
|
198
|
-
getSystemSettingsPath
|
|
199
|
-
} from "./chunk-IDS7MSUP.js";
|
|
215
|
+
} from "./chunk-NGTQA57Y.js";
|
|
200
216
|
import "./chunk-QRUIS3DN.js";
|
|
217
|
+
import "./chunk-W4DFAUAO.js";
|
|
218
|
+
import "./chunk-VJNBRRZG.js";
|
|
201
219
|
import {
|
|
202
220
|
isFolderTrustEnabled,
|
|
203
221
|
isWorkspaceTrusted,
|
|
204
222
|
loadTrustedFolders
|
|
205
|
-
} from "./chunk-
|
|
223
|
+
} from "./chunk-XFJU7SVP.js";
|
|
206
224
|
import "./chunk-ALGGS7UH.js";
|
|
207
225
|
import "./chunk-MR3PXB6E.js";
|
|
208
226
|
import {
|
|
209
|
-
writeStderrLine
|
|
210
|
-
|
|
227
|
+
writeStderrLine,
|
|
228
|
+
writeStderrLineSafe
|
|
229
|
+
} from "./chunk-OWAK7LMW.js";
|
|
211
230
|
import "./chunk-XFSFZCM5.js";
|
|
212
|
-
import "./chunk-GLNHPRZT.js";
|
|
213
|
-
import "./chunk-VJNBRRZG.js";
|
|
214
231
|
import {
|
|
215
232
|
ALL_PROVIDERS,
|
|
216
233
|
APPROVAL_MODE_INFO,
|
|
@@ -233,7 +250,9 @@ import {
|
|
|
233
250
|
SESSION_ARTIFACT_PERSISTENCE_VERSION,
|
|
234
251
|
SESSION_TITLE_MAX_LENGTH,
|
|
235
252
|
SESSION_TRANSCRIPT_MAX_LIMIT,
|
|
253
|
+
SESSION_TRANSCRIPT_MAX_PAGE_BYTES,
|
|
236
254
|
SessionService,
|
|
255
|
+
SessionTranscriptPageTooLargeError,
|
|
237
256
|
SessionTranscriptReader,
|
|
238
257
|
SessionTranscriptSnapshotUnavailableError,
|
|
239
258
|
SessionTranscriptTooLargeError,
|
|
@@ -275,6 +294,7 @@ import {
|
|
|
275
294
|
generatePromptSuggestion,
|
|
276
295
|
generateSessionRecap,
|
|
277
296
|
generateToolUseId,
|
|
297
|
+
getActiveGoal,
|
|
278
298
|
getArenaSystemReminder,
|
|
279
299
|
getAutoModePermissionDeniedReason,
|
|
280
300
|
getDefaultBaseUrlForProtocol,
|
|
@@ -321,35 +341,42 @@ import {
|
|
|
321
341
|
subagentGenerator,
|
|
322
342
|
unregisterGoalHook,
|
|
323
343
|
updateSetting
|
|
324
|
-
} from "./chunk-
|
|
344
|
+
} from "./chunk-6TDA4EVC.js";
|
|
345
|
+
import "./chunk-5M6IDOMF.js";
|
|
325
346
|
import "./chunk-T4TZQJ7W.js";
|
|
326
347
|
import {
|
|
327
348
|
external_exports
|
|
328
349
|
} from "./chunk-H6XPXXMH.js";
|
|
329
|
-
import "./chunk-
|
|
330
|
-
import "./chunk-
|
|
331
|
-
import "./chunk-
|
|
332
|
-
import "./chunk-
|
|
333
|
-
import "./chunk-TV6K2FB4.js";
|
|
350
|
+
import "./chunk-LKR7QQ63.js";
|
|
351
|
+
import "./chunk-4XCVGEEX.js";
|
|
352
|
+
import "./chunk-XSPFQQRE.js";
|
|
353
|
+
import "./chunk-4RPARQ5D.js";
|
|
334
354
|
import "./chunk-E2UVIFI2.js";
|
|
335
355
|
import "./chunk-XU457J4V.js";
|
|
336
356
|
import "./chunk-VDDGDZMA.js";
|
|
337
|
-
import "./chunk-
|
|
357
|
+
import "./chunk-J2MKYJKZ.js";
|
|
338
358
|
import "./chunk-SZRN75WQ.js";
|
|
339
359
|
import "./chunk-HTO4JFDZ.js";
|
|
340
360
|
import "./chunk-CPBF7KYF.js";
|
|
341
361
|
import {
|
|
342
362
|
APPROVAL_MODES,
|
|
343
|
-
FORK_SUBAGENT_TYPE
|
|
344
|
-
|
|
363
|
+
FORK_SUBAGENT_TYPE,
|
|
364
|
+
runWithRuntimeContentGenerator
|
|
365
|
+
} from "./chunk-UOA2IHRI.js";
|
|
345
366
|
import "./chunk-6AM5D4ME.js";
|
|
346
|
-
import "./chunk-
|
|
367
|
+
import "./chunk-OSSDHJDU.js";
|
|
347
368
|
import {
|
|
348
369
|
HookEventName,
|
|
349
370
|
createHookOutput
|
|
350
|
-
} from "./chunk-
|
|
351
|
-
import "./chunk-
|
|
352
|
-
import "./chunk-
|
|
371
|
+
} from "./chunk-SGPFJMRP.js";
|
|
372
|
+
import "./chunk-335ECZTA.js";
|
|
373
|
+
import "./chunk-JCJPZMJV.js";
|
|
374
|
+
import {
|
|
375
|
+
clearCachedCredentialFile,
|
|
376
|
+
qwenOAuth2Events
|
|
377
|
+
} from "./chunk-QGONRHUS.js";
|
|
378
|
+
import "./chunk-7KS72E2N.js";
|
|
379
|
+
import "./chunk-JESCGQM3.js";
|
|
353
380
|
import {
|
|
354
381
|
AuthType,
|
|
355
382
|
ConversationFinishedEvent,
|
|
@@ -360,9 +387,12 @@ import {
|
|
|
360
387
|
endToolExecutionSpan,
|
|
361
388
|
endToolSpan,
|
|
362
389
|
extractDaemonTraceContext,
|
|
390
|
+
formatFullTurnVisionNotice,
|
|
363
391
|
formatVisionBridgeNotice,
|
|
364
392
|
getAllGeminiMdFilenames,
|
|
393
|
+
getFullTurnVisionModelSelector,
|
|
365
394
|
getMCPServerStatus,
|
|
395
|
+
getSpecificMimeType,
|
|
366
396
|
hasImageParts,
|
|
367
397
|
logConversationFinishedEvent,
|
|
368
398
|
logLoopDetected,
|
|
@@ -372,6 +402,7 @@ import {
|
|
|
372
402
|
normalizeParts,
|
|
373
403
|
registerAcpEventLoopLagGauge,
|
|
374
404
|
runInToolSpanContext,
|
|
405
|
+
runSideQuery,
|
|
375
406
|
runVisionBridge,
|
|
376
407
|
shouldRunVisionBridge,
|
|
377
408
|
splitImageParts,
|
|
@@ -379,57 +410,49 @@ import {
|
|
|
379
410
|
startToolExecutionSpan,
|
|
380
411
|
startToolSpan,
|
|
381
412
|
uiTelemetryService,
|
|
413
|
+
withDaemonSpan,
|
|
382
414
|
withInteractionSpan
|
|
383
|
-
} from "./chunk-
|
|
415
|
+
} from "./chunk-YN2I5I42.js";
|
|
384
416
|
import "./chunk-4WKAA4KS.js";
|
|
385
417
|
import "./chunk-CR3C7WXL.js";
|
|
386
|
-
import {
|
|
387
|
-
runSideQuery
|
|
388
|
-
} from "./chunk-RTV5TUYB.js";
|
|
389
418
|
import "./chunk-VGC4I5JJ.js";
|
|
390
419
|
import {
|
|
391
420
|
getAutoMemoryRoot,
|
|
392
421
|
getUserAutoMemoryRoot
|
|
393
|
-
} from "./chunk-
|
|
394
|
-
import "./chunk-
|
|
395
|
-
import "./chunk-
|
|
422
|
+
} from "./chunk-LPHGXXZX.js";
|
|
423
|
+
import "./chunk-4CA4WUMS.js";
|
|
424
|
+
import "./chunk-VAJS2E2D.js";
|
|
425
|
+
import "./chunk-WEPXQKGP.js";
|
|
396
426
|
import {
|
|
397
427
|
ToolConfirmationOutcome,
|
|
398
428
|
ToolNames,
|
|
399
429
|
isShellProgressData
|
|
400
|
-
} from "./chunk-
|
|
401
|
-
import {
|
|
402
|
-
clearCachedCredentialFile,
|
|
403
|
-
qwenOAuth2Events
|
|
404
|
-
} from "./chunk-OKAIGAYW.js";
|
|
405
|
-
import "./chunk-ZPAHLFZU.js";
|
|
406
|
-
import "./chunk-JESCGQM3.js";
|
|
407
|
-
import "./chunk-WIEO4CWB.js";
|
|
430
|
+
} from "./chunk-ANRANWVE.js";
|
|
408
431
|
import "./chunk-XVNQMZ2I.js";
|
|
409
432
|
import "./chunk-FEOZBUMT.js";
|
|
433
|
+
import "./chunk-DJ2GSRLV.js";
|
|
434
|
+
import "./chunk-4CHDYDG3.js";
|
|
410
435
|
import {
|
|
411
436
|
DEFAULT_TOKEN_LIMIT,
|
|
412
437
|
getToolCallPreparations,
|
|
413
438
|
tokenLimit
|
|
414
|
-
} from "./chunk-
|
|
439
|
+
} from "./chunk-V4PCIS25.js";
|
|
415
440
|
import "./chunk-A4UCTEB5.js";
|
|
416
441
|
import "./chunk-XWRJCPHC.js";
|
|
417
|
-
import "./chunk-
|
|
442
|
+
import "./chunk-TYQMGACW.js";
|
|
418
443
|
import "./chunk-TYAMGABM.js";
|
|
419
444
|
import "./chunk-FCMNKVXT.js";
|
|
420
|
-
import "./chunk-DJ2GSRLV.js";
|
|
421
|
-
import "./chunk-LQIDP6K5.js";
|
|
422
445
|
import {
|
|
423
446
|
Storage,
|
|
424
447
|
createDebugLogger,
|
|
425
448
|
getErrorMessage,
|
|
426
449
|
getErrorStatus,
|
|
427
450
|
isSubpath
|
|
428
|
-
} from "./chunk-
|
|
429
|
-
import "./chunk-
|
|
451
|
+
} from "./chunk-UE5TZ55T.js";
|
|
452
|
+
import "./chunk-ZPVGEMVC.js";
|
|
430
453
|
import {
|
|
431
454
|
runExitCleanup
|
|
432
|
-
} from "./chunk-
|
|
455
|
+
} from "./chunk-DULSE2SH.js";
|
|
433
456
|
import "./chunk-75DOP5OR.js";
|
|
434
457
|
import "./chunk-DMTGGOSA.js";
|
|
435
458
|
import "./chunk-YQ3U5MUC.js";
|
|
@@ -444,6 +467,7 @@ import {
|
|
|
444
467
|
// packages/cli/src/acp-integration/acpAgent.ts
|
|
445
468
|
init_esbuild_shims();
|
|
446
469
|
import { randomUUID } from "node:crypto";
|
|
470
|
+
import { performance } from "node:perf_hooks";
|
|
447
471
|
|
|
448
472
|
// packages/cli/src/acp-integration/authMethods.ts
|
|
449
473
|
init_esbuild_shims();
|
|
@@ -820,9 +844,35 @@ __name(isInactiveExtensionSkill, "isInactiveExtensionSkill");
|
|
|
820
844
|
// packages/cli/src/acp-integration/session/Session.ts
|
|
821
845
|
init_esbuild_shims();
|
|
822
846
|
import { Buffer as Buffer2 } from "node:buffer";
|
|
847
|
+
import { existsSync as existsSync2, statSync as statSync2 } from "node:fs";
|
|
823
848
|
import * as os2 from "node:os";
|
|
824
849
|
import * as path3 from "node:path";
|
|
825
850
|
|
|
851
|
+
// packages/cli/src/utils/midTurnUserMessage.ts
|
|
852
|
+
init_esbuild_shims();
|
|
853
|
+
var MID_TURN_USER_MESSAGE_PREFIX = "\n[User message received during tool execution]: ";
|
|
854
|
+
function prefixMidTurnUserMessageParts(parts, displayText) {
|
|
855
|
+
const partArray = normalizePartList(parts);
|
|
856
|
+
if (partArray.length === 0) {
|
|
857
|
+
return [{ text: `${MID_TURN_USER_MESSAGE_PREFIX}${displayText}` }];
|
|
858
|
+
}
|
|
859
|
+
const [firstPart, ...rest] = partArray;
|
|
860
|
+
if ("text" in firstPart && typeof firstPart.text === "string") {
|
|
861
|
+
return [
|
|
862
|
+
{
|
|
863
|
+
...firstPart,
|
|
864
|
+
text: `${MID_TURN_USER_MESSAGE_PREFIX}${firstPart.text}`
|
|
865
|
+
},
|
|
866
|
+
...rest
|
|
867
|
+
];
|
|
868
|
+
}
|
|
869
|
+
return [
|
|
870
|
+
{ text: `${MID_TURN_USER_MESSAGE_PREFIX}${displayText}` },
|
|
871
|
+
...partArray
|
|
872
|
+
];
|
|
873
|
+
}
|
|
874
|
+
__name(prefixMidTurnUserMessageParts, "prefixMidTurnUserMessageParts");
|
|
875
|
+
|
|
826
876
|
// packages/cli/src/acp-integration/session/tool-call-preparation-tracker.ts
|
|
827
877
|
init_esbuild_shims();
|
|
828
878
|
var ToolCallPreparationTracker = class {
|
|
@@ -1601,11 +1651,196 @@ function loadRewriteConfig(settings) {
|
|
|
1601
1651
|
}
|
|
1602
1652
|
__name(loadRewriteConfig, "loadRewriteConfig");
|
|
1603
1653
|
|
|
1654
|
+
// packages/cli/src/acp-integration/session/daemon-todo-stop-guard.ts
|
|
1655
|
+
init_esbuild_shims();
|
|
1656
|
+
var TODO_STOP_GUARD_MAX_ATTEMPTS = 2;
|
|
1657
|
+
function parseStructuredTodos(value) {
|
|
1658
|
+
if (typeof value !== "object" || value === null) return null;
|
|
1659
|
+
const record = value;
|
|
1660
|
+
if (record["type"] !== "todo_list" || !Array.isArray(record["todos"])) {
|
|
1661
|
+
return null;
|
|
1662
|
+
}
|
|
1663
|
+
for (const item of record["todos"]) {
|
|
1664
|
+
if (typeof item !== "object" || item === null) return null;
|
|
1665
|
+
const todo = item;
|
|
1666
|
+
if (typeof todo["id"] !== "string" || typeof todo["content"] !== "string" || todo["status"] !== "pending" && todo["status"] !== "in_progress" && todo["status"] !== "completed") {
|
|
1667
|
+
return null;
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1670
|
+
return record["todos"];
|
|
1671
|
+
}
|
|
1672
|
+
__name(parseStructuredTodos, "parseStructuredTodos");
|
|
1673
|
+
var DaemonTodoStopGuard = class {
|
|
1674
|
+
constructor(enabled) {
|
|
1675
|
+
this.enabled = enabled;
|
|
1676
|
+
}
|
|
1677
|
+
static {
|
|
1678
|
+
__name(this, "DaemonTodoStopGuard");
|
|
1679
|
+
}
|
|
1680
|
+
#armed = false;
|
|
1681
|
+
#unfinishedCount = 0;
|
|
1682
|
+
#attempts = 0;
|
|
1683
|
+
#suspended = false;
|
|
1684
|
+
#retryPaused = false;
|
|
1685
|
+
#awaitingQueuedPrompt = false;
|
|
1686
|
+
#exhaustionReported = false;
|
|
1687
|
+
get hasTrustedUnfinishedState() {
|
|
1688
|
+
return this.enabled && this.#armed && !this.#suspended && this.#unfinishedCount > 0;
|
|
1689
|
+
}
|
|
1690
|
+
get isHardSuspended() {
|
|
1691
|
+
return this.enabled && this.#suspended;
|
|
1692
|
+
}
|
|
1693
|
+
get hasCommittedContinuation() {
|
|
1694
|
+
return this.enabled && this.#attempts > 0;
|
|
1695
|
+
}
|
|
1696
|
+
get blocksUnrelatedAutomaticTurns() {
|
|
1697
|
+
return this.enabled && this.#armed && !this.#suspended && this.#unfinishedCount > 0;
|
|
1698
|
+
}
|
|
1699
|
+
get needsStopInspection() {
|
|
1700
|
+
return this.enabled && this.#armed && !this.#suspended && !this.#retryPaused && !this.#awaitingQueuedPrompt && this.#unfinishedCount > 0;
|
|
1701
|
+
}
|
|
1702
|
+
clearTrust() {
|
|
1703
|
+
this.#armed = false;
|
|
1704
|
+
this.#unfinishedCount = 0;
|
|
1705
|
+
this.#attempts = 0;
|
|
1706
|
+
this.#suspended = false;
|
|
1707
|
+
this.#retryPaused = false;
|
|
1708
|
+
this.#awaitingQueuedPrompt = false;
|
|
1709
|
+
this.#exhaustionReported = false;
|
|
1710
|
+
}
|
|
1711
|
+
startOrdinaryPrompt() {
|
|
1712
|
+
this.clearTrust();
|
|
1713
|
+
}
|
|
1714
|
+
resumeTrustedPrompt() {
|
|
1715
|
+
this.#awaitingQueuedPrompt = false;
|
|
1716
|
+
this.#retryPaused = false;
|
|
1717
|
+
}
|
|
1718
|
+
blockUntilOrdinaryPromptStarts() {
|
|
1719
|
+
this.clearTrust();
|
|
1720
|
+
this.#suspended = true;
|
|
1721
|
+
}
|
|
1722
|
+
acceptMidTurnUserInput() {
|
|
1723
|
+
if (!this.enabled || this.#suspended) return;
|
|
1724
|
+
if (!this.#armed && this.#attempts === 0) return;
|
|
1725
|
+
this.#attempts = 0;
|
|
1726
|
+
this.#retryPaused = false;
|
|
1727
|
+
this.#awaitingQueuedPrompt = false;
|
|
1728
|
+
this.#exhaustionReported = false;
|
|
1729
|
+
}
|
|
1730
|
+
observeTodoWrite(resultDisplay, allowArm) {
|
|
1731
|
+
if (!this.enabled) return false;
|
|
1732
|
+
const todos = parseStructuredTodos(resultDisplay);
|
|
1733
|
+
if (todos === null) return false;
|
|
1734
|
+
if (!allowArm) {
|
|
1735
|
+
this.blockUntilOrdinaryPromptStarts();
|
|
1736
|
+
return true;
|
|
1737
|
+
}
|
|
1738
|
+
this.#unfinishedCount = todos.filter(
|
|
1739
|
+
(todo) => todo.status === "pending" || todo.status === "in_progress"
|
|
1740
|
+
).length;
|
|
1741
|
+
this.#exhaustionReported = false;
|
|
1742
|
+
if (this.#unfinishedCount === 0) {
|
|
1743
|
+
this.#armed = false;
|
|
1744
|
+
return true;
|
|
1745
|
+
}
|
|
1746
|
+
if (!this.#suspended) this.#armed = true;
|
|
1747
|
+
return true;
|
|
1748
|
+
}
|
|
1749
|
+
suspend() {
|
|
1750
|
+
if (!this.enabled) return;
|
|
1751
|
+
this.#suspended = true;
|
|
1752
|
+
this.#awaitingQueuedPrompt = false;
|
|
1753
|
+
}
|
|
1754
|
+
pauseForTrustedRetry() {
|
|
1755
|
+
if (!this.#armed) return;
|
|
1756
|
+
this.#retryPaused = true;
|
|
1757
|
+
this.#awaitingQueuedPrompt = false;
|
|
1758
|
+
}
|
|
1759
|
+
awaitQueuedPrompt() {
|
|
1760
|
+
if (!this.#armed && this.#attempts === 0 || this.#suspended) return false;
|
|
1761
|
+
this.#awaitingQueuedPrompt = true;
|
|
1762
|
+
return true;
|
|
1763
|
+
}
|
|
1764
|
+
decide(hasRelevantBackgroundInput) {
|
|
1765
|
+
if (!this.needsStopInspection) return { kind: "inactive" };
|
|
1766
|
+
if (hasRelevantBackgroundInput) return { kind: "deferred" };
|
|
1767
|
+
if (this.#attempts >= TODO_STOP_GUARD_MAX_ATTEMPTS) {
|
|
1768
|
+
return {
|
|
1769
|
+
kind: "exhausted",
|
|
1770
|
+
attempt: this.#attempts,
|
|
1771
|
+
maxAttempts: TODO_STOP_GUARD_MAX_ATTEMPTS,
|
|
1772
|
+
unfinishedCount: this.#unfinishedCount
|
|
1773
|
+
};
|
|
1774
|
+
}
|
|
1775
|
+
return {
|
|
1776
|
+
kind: "continue",
|
|
1777
|
+
attempt: this.#attempts + 1,
|
|
1778
|
+
maxAttempts: TODO_STOP_GUARD_MAX_ATTEMPTS,
|
|
1779
|
+
unfinishedCount: this.#unfinishedCount
|
|
1780
|
+
};
|
|
1781
|
+
}
|
|
1782
|
+
decideToolClosure(currentAttempt, hasRelevantBackgroundInput) {
|
|
1783
|
+
if (this.#unfinishedCount > 0) {
|
|
1784
|
+
return this.decide(hasRelevantBackgroundInput);
|
|
1785
|
+
}
|
|
1786
|
+
if (!this.enabled || this.#suspended || this.#retryPaused || this.#awaitingQueuedPrompt || this.#attempts !== currentAttempt) {
|
|
1787
|
+
return { kind: "inactive" };
|
|
1788
|
+
}
|
|
1789
|
+
if (hasRelevantBackgroundInput) return { kind: "deferred" };
|
|
1790
|
+
if (currentAttempt >= TODO_STOP_GUARD_MAX_ATTEMPTS) {
|
|
1791
|
+
return { kind: "inactive" };
|
|
1792
|
+
}
|
|
1793
|
+
return {
|
|
1794
|
+
kind: "continue",
|
|
1795
|
+
attempt: currentAttempt + 1,
|
|
1796
|
+
maxAttempts: TODO_STOP_GUARD_MAX_ATTEMPTS,
|
|
1797
|
+
unfinishedCount: 0,
|
|
1798
|
+
toolClosure: true
|
|
1799
|
+
};
|
|
1800
|
+
}
|
|
1801
|
+
commitContinuation(attempt) {
|
|
1802
|
+
const canCloseTools = this.enabled && this.#unfinishedCount === 0 && this.#attempts > 0 && !this.#suspended && !this.#retryPaused && !this.#awaitingQueuedPrompt;
|
|
1803
|
+
if (!this.needsStopInspection && !canCloseTools || attempt !== this.#attempts + 1 || attempt > TODO_STOP_GUARD_MAX_ATTEMPTS) {
|
|
1804
|
+
return false;
|
|
1805
|
+
}
|
|
1806
|
+
this.#attempts = attempt;
|
|
1807
|
+
return true;
|
|
1808
|
+
}
|
|
1809
|
+
markExhaustionReported() {
|
|
1810
|
+
if (this.#exhaustionReported) return false;
|
|
1811
|
+
this.#exhaustionReported = true;
|
|
1812
|
+
this.#suspended = true;
|
|
1813
|
+
return true;
|
|
1814
|
+
}
|
|
1815
|
+
};
|
|
1816
|
+
|
|
1604
1817
|
// packages/cli/src/acp-integration/session/Session.ts
|
|
1605
1818
|
var debugLogger6 = createDebugLogger("SESSION");
|
|
1606
1819
|
var USER_CANCEL_ABORT_REASON = "qwen:user-cancel";
|
|
1607
1820
|
var DAEMON_RETRY_META_KEY = "qwen.daemon.retry";
|
|
1608
1821
|
var DAEMON_CONTINUE_META_KEY = "qwen.daemon.continueLastTurn";
|
|
1822
|
+
var TODO_STOP_GUARD_PROMPT_PREFIX = "[Todo Stop Guard] ";
|
|
1823
|
+
var TODO_STOP_GUARD_PROMPT_BODY_SUFFIX = " todo item(s) are still pending or in progress. Continue executing the current task now. Do not ask the user whether to continue. If progress requires user input, use the structured question or permission flow. If progress depends on external state, report the blocker explicitly.";
|
|
1824
|
+
var TODO_STOP_GUARD_FINAL_PROMPT_SUFFIX = " This is the final automatic continuation. Before ending, either complete/update the todos or report the completed progress and the exact blocker.";
|
|
1825
|
+
function isTodoStopGuardPromptText(text) {
|
|
1826
|
+
if (typeof text !== "string") return false;
|
|
1827
|
+
if (!text.startsWith(TODO_STOP_GUARD_PROMPT_PREFIX)) return false;
|
|
1828
|
+
const remainder = text.slice(TODO_STOP_GUARD_PROMPT_PREFIX.length);
|
|
1829
|
+
const separator = remainder.indexOf(" ");
|
|
1830
|
+
if (separator <= 0) return false;
|
|
1831
|
+
const countText = remainder.slice(0, separator);
|
|
1832
|
+
const count = Number(countText);
|
|
1833
|
+
if (!Number.isSafeInteger(count) || count <= 0 || String(count) !== countText) {
|
|
1834
|
+
return false;
|
|
1835
|
+
}
|
|
1836
|
+
const body = `${countText}${TODO_STOP_GUARD_PROMPT_BODY_SUFFIX}`;
|
|
1837
|
+
return remainder === body || remainder === body + TODO_STOP_GUARD_FINAL_PROMPT_SUFFIX;
|
|
1838
|
+
}
|
|
1839
|
+
__name(isTodoStopGuardPromptText, "isTodoStopGuardPromptText");
|
|
1840
|
+
function isCompressionFailureStatus(status) {
|
|
1841
|
+
return status === 2 /* COMPRESSION_FAILED_INFLATED_TOKEN_COUNT */ || status === 3 /* COMPRESSION_FAILED_TOKEN_COUNT_ERROR */ || status === 4 /* COMPRESSION_FAILED_EMPTY_SUMMARY */ || status === 6 /* COMPRESSION_FAILED_OUTPUT_TRUNCATED */;
|
|
1842
|
+
}
|
|
1843
|
+
__name(isCompressionFailureStatus, "isCompressionFailureStatus");
|
|
1609
1844
|
async function finalizeToolCallPreparations(tracker, includeResolved, streamName) {
|
|
1610
1845
|
try {
|
|
1611
1846
|
await tracker.discard(includeResolved);
|
|
@@ -1860,6 +2095,15 @@ var MidTurnDrainTimeoutError = class extends Error {
|
|
|
1860
2095
|
}
|
|
1861
2096
|
};
|
|
1862
2097
|
var MAX_NOTIFICATION_QUEUE = 20;
|
|
2098
|
+
var MAX_DEFERRED_UNRELATED_CRON_QUEUE = 20;
|
|
2099
|
+
function isExistingFile(resolved, fileExists = existsSync2, statFile = statSync2) {
|
|
2100
|
+
try {
|
|
2101
|
+
return fileExists(resolved) && statFile(resolved).isFile();
|
|
2102
|
+
} catch {
|
|
2103
|
+
return false;
|
|
2104
|
+
}
|
|
2105
|
+
}
|
|
2106
|
+
__name(isExistingFile, "isExistingFile");
|
|
1863
2107
|
function resolveHomeLoopResolverRoots({
|
|
1864
2108
|
homeQwenDir = Storage.getGlobalQwenDir(),
|
|
1865
2109
|
homeDir = os2.homedir(),
|
|
@@ -2067,11 +2311,21 @@ var Session = class {
|
|
|
2067
2311
|
this.settings = settings;
|
|
2068
2312
|
this.sessionId = id;
|
|
2069
2313
|
this.runtimeBaseDir = Storage.getRuntimeBaseDir();
|
|
2314
|
+
const todoStopGuardEnabled = this.settings.merged.experimental?.todoStopGuard === true && !this.config.getBareMode() && !this.config.isSafeMode();
|
|
2315
|
+
this.todoStopGuard = new DaemonTodoStopGuard(todoStopGuardEnabled);
|
|
2316
|
+
this.todoStopGuardBackgroundBaseline = todoStopGuardEnabled ? this.#captureTodoStopGuardBackgroundBaseline() : {
|
|
2317
|
+
agents: /* @__PURE__ */ new Set(),
|
|
2318
|
+
shells: /* @__PURE__ */ new Set(),
|
|
2319
|
+
monitors: /* @__PURE__ */ new Set(),
|
|
2320
|
+
wakeups: /* @__PURE__ */ new Set()
|
|
2321
|
+
};
|
|
2070
2322
|
this.toolCallEmitter = new ToolCallEmitter(this);
|
|
2071
2323
|
this.planEmitter = new PlanEmitter(this);
|
|
2072
|
-
this.historyReplayer = new HistoryReplayer(this
|
|
2324
|
+
this.historyReplayer = new HistoryReplayer(this, {
|
|
2325
|
+
supersedeUnrestorableGoal: true
|
|
2326
|
+
});
|
|
2073
2327
|
this.messageEmitter = new MessageEmitter(this);
|
|
2074
|
-
this
|
|
2328
|
+
this.installGoalTerminalObserver();
|
|
2075
2329
|
this.#registerBackgroundNotificationCallbacks();
|
|
2076
2330
|
this.#registerSubSessionSpawner();
|
|
2077
2331
|
}
|
|
@@ -2133,6 +2387,10 @@ var Session = class {
|
|
|
2133
2387
|
// batch so a transient stall can't silently lose them. See
|
|
2134
2388
|
// `#drainMidTurnUserMessages`.
|
|
2135
2389
|
midTurnRecoveredMessages = [];
|
|
2390
|
+
todoStopGuard;
|
|
2391
|
+
todoStopGuardBackgroundBaseline;
|
|
2392
|
+
todoStopGuardQueuedPromptPriority = false;
|
|
2393
|
+
todoStopGuardDrainAutomaticQueuesWhenIdle = false;
|
|
2136
2394
|
// Background notification drain state. ACP does not have the TUI's idle
|
|
2137
2395
|
// hook, so the session serializes registry callbacks through this queue.
|
|
2138
2396
|
notificationQueue = [];
|
|
@@ -2169,6 +2427,169 @@ var Session = class {
|
|
|
2169
2427
|
pendingWorktreeNotice = null;
|
|
2170
2428
|
// Implement SessionContext interface
|
|
2171
2429
|
sessionId;
|
|
2430
|
+
#prepareTodoStopGuardForPrompt(params) {
|
|
2431
|
+
if (!this.todoStopGuard.enabled) {
|
|
2432
|
+
return {
|
|
2433
|
+
startsWorkChain: false,
|
|
2434
|
+
drainSupersededAutomaticQueues: false
|
|
2435
|
+
};
|
|
2436
|
+
}
|
|
2437
|
+
const drainSupersededAutomaticQueues = this.todoStopGuard.blocksUnrelatedAutomaticTurns || this.todoStopGuard.hasCommittedContinuation || this.todoStopGuardQueuedPromptPriority;
|
|
2438
|
+
if (this.config.getApprovalMode() === "plan" /* PLAN */) {
|
|
2439
|
+
this.todoStopGuardQueuedPromptPriority = false;
|
|
2440
|
+
this.todoStopGuard.blockUntilOrdinaryPromptStarts();
|
|
2441
|
+
return {
|
|
2442
|
+
startsWorkChain: false,
|
|
2443
|
+
drainSupersededAutomaticQueues
|
|
2444
|
+
};
|
|
2445
|
+
}
|
|
2446
|
+
const metadata = params._meta;
|
|
2447
|
+
const isRetry = params.retry === true || metadata?.[DAEMON_RETRY_META_KEY] === true;
|
|
2448
|
+
const isContinue = metadata?.[DAEMON_CONTINUE_META_KEY] === true;
|
|
2449
|
+
if (isRetry || isContinue) {
|
|
2450
|
+
this.todoStopGuardQueuedPromptPriority = false;
|
|
2451
|
+
if (this.todoStopGuard.hasTrustedUnfinishedState) {
|
|
2452
|
+
this.todoStopGuard.resumeTrustedPrompt();
|
|
2453
|
+
return {
|
|
2454
|
+
startsWorkChain: false,
|
|
2455
|
+
drainSupersededAutomaticQueues: false
|
|
2456
|
+
};
|
|
2457
|
+
}
|
|
2458
|
+
this.todoStopGuard.blockUntilOrdinaryPromptStarts();
|
|
2459
|
+
return {
|
|
2460
|
+
startsWorkChain: true,
|
|
2461
|
+
drainSupersededAutomaticQueues
|
|
2462
|
+
};
|
|
2463
|
+
}
|
|
2464
|
+
this.todoStopGuardQueuedPromptPriority = false;
|
|
2465
|
+
this.todoStopGuard.blockUntilOrdinaryPromptStarts();
|
|
2466
|
+
return {
|
|
2467
|
+
startsWorkChain: true,
|
|
2468
|
+
drainSupersededAutomaticQueues
|
|
2469
|
+
};
|
|
2470
|
+
}
|
|
2471
|
+
#prepareTodoStopGuardForAutomaticTurn(continuesCurrentWorkChain) {
|
|
2472
|
+
if (!this.todoStopGuard.enabled) return;
|
|
2473
|
+
if (this.config.getApprovalMode() === "plan" /* PLAN */) {
|
|
2474
|
+
this.todoStopGuard.blockUntilOrdinaryPromptStarts();
|
|
2475
|
+
return;
|
|
2476
|
+
}
|
|
2477
|
+
if (continuesCurrentWorkChain && this.todoStopGuard.isHardSuspended) {
|
|
2478
|
+
return;
|
|
2479
|
+
}
|
|
2480
|
+
if (continuesCurrentWorkChain && this.todoStopGuard.hasTrustedUnfinishedState) {
|
|
2481
|
+
this.todoStopGuard.resumeTrustedPrompt();
|
|
2482
|
+
return;
|
|
2483
|
+
}
|
|
2484
|
+
this.todoStopGuard.clearTrust();
|
|
2485
|
+
this.todoStopGuardBackgroundBaseline = this.#captureTodoStopGuardBackgroundBaseline();
|
|
2486
|
+
}
|
|
2487
|
+
#clearTodoStopGuardTrustAndDrainAutomaticQueues() {
|
|
2488
|
+
const preserveQueuedPromptPriority = this.todoStopGuardQueuedPromptPriority;
|
|
2489
|
+
const shouldDrain = (this.todoStopGuard.blocksUnrelatedAutomaticTurns || this.todoStopGuard.hasCommittedContinuation) && !preserveQueuedPromptPriority;
|
|
2490
|
+
this.todoStopGuard.blockUntilOrdinaryPromptStarts();
|
|
2491
|
+
if (preserveQueuedPromptPriority || !shouldDrain) return;
|
|
2492
|
+
if (this.pendingPrompt) {
|
|
2493
|
+
this.todoStopGuardDrainAutomaticQueuesWhenIdle = true;
|
|
2494
|
+
return;
|
|
2495
|
+
}
|
|
2496
|
+
void this.#drainCronQueue();
|
|
2497
|
+
void this.#drainNotificationQueue();
|
|
2498
|
+
}
|
|
2499
|
+
releaseTodoStopGuardQueuedPromptWait() {
|
|
2500
|
+
if (!this.todoStopGuardQueuedPromptPriority) return false;
|
|
2501
|
+
this.todoStopGuardQueuedPromptPriority = false;
|
|
2502
|
+
this.todoStopGuard.blockUntilOrdinaryPromptStarts();
|
|
2503
|
+
if (this.pendingPrompt) {
|
|
2504
|
+
this.todoStopGuardDrainAutomaticQueuesWhenIdle = true;
|
|
2505
|
+
return true;
|
|
2506
|
+
}
|
|
2507
|
+
void this.#drainCronQueue();
|
|
2508
|
+
void this.#drainNotificationQueue();
|
|
2509
|
+
return true;
|
|
2510
|
+
}
|
|
2511
|
+
clearTodoStopGuardTrust() {
|
|
2512
|
+
this.#clearTodoStopGuardTrustAndDrainAutomaticQueues();
|
|
2513
|
+
}
|
|
2514
|
+
#beginTodoStopGuardQueuedPromptCheck() {
|
|
2515
|
+
this.todoStopGuardQueuedPromptPriority = this.todoStopGuard.awaitQueuedPrompt();
|
|
2516
|
+
}
|
|
2517
|
+
#finishTodoStopGuardQueuedPromptCheck(hasQueuedPrompt) {
|
|
2518
|
+
const shouldWait = hasQueuedPrompt && this.todoStopGuardQueuedPromptPriority;
|
|
2519
|
+
this.todoStopGuardQueuedPromptPriority = shouldWait;
|
|
2520
|
+
if (!shouldWait) this.todoStopGuard.resumeTrustedPrompt();
|
|
2521
|
+
return shouldWait;
|
|
2522
|
+
}
|
|
2523
|
+
#notificationContinuesTodoStopGuardWorkChain(item) {
|
|
2524
|
+
const baseline = this.todoStopGuardBackgroundBaseline;
|
|
2525
|
+
if (item.kind === "agent") return !baseline.agents.has(item.taskId);
|
|
2526
|
+
if (item.kind === "shell") return !baseline.shells.has(item.taskId);
|
|
2527
|
+
return !baseline.monitors.has(item.taskId);
|
|
2528
|
+
}
|
|
2529
|
+
#cronContinuesTodoStopGuardWorkChain(item) {
|
|
2530
|
+
return item.source === "loop" && item.taskId !== void 0 && !this.todoStopGuardBackgroundBaseline.wakeups.has(item.taskId);
|
|
2531
|
+
}
|
|
2532
|
+
#captureTodoStopGuardBackgroundBaseline() {
|
|
2533
|
+
const agents = this.config.getBackgroundTaskRegistry?.()?.getAll?.() ?? [];
|
|
2534
|
+
const shells = this.config.getBackgroundShellRegistry?.()?.getAll?.() ?? [];
|
|
2535
|
+
const monitors = this.config.getMonitorRegistry?.()?.getAll?.() ?? [];
|
|
2536
|
+
const wakeups = this.config.isCronEnabled?.() ? (this.config.getCronScheduler?.()?.list?.() ?? []).filter(
|
|
2537
|
+
(job) => job.cronExpr === "@wakeup"
|
|
2538
|
+
) : [];
|
|
2539
|
+
return {
|
|
2540
|
+
agents: /* @__PURE__ */ new Set([
|
|
2541
|
+
...agents.map((task) => task.id),
|
|
2542
|
+
...this.notificationQueue.filter((item) => item.kind === "agent").map((item) => item.taskId)
|
|
2543
|
+
]),
|
|
2544
|
+
shells: /* @__PURE__ */ new Set([
|
|
2545
|
+
...shells.map((task) => task.id),
|
|
2546
|
+
...this.notificationQueue.filter((item) => item.kind === "shell").map((item) => item.taskId)
|
|
2547
|
+
]),
|
|
2548
|
+
monitors: /* @__PURE__ */ new Set([
|
|
2549
|
+
...monitors.map((task) => task.id),
|
|
2550
|
+
...this.notificationQueue.filter((item) => item.kind === "monitor").map((item) => item.taskId)
|
|
2551
|
+
]),
|
|
2552
|
+
wakeups: /* @__PURE__ */ new Set([
|
|
2553
|
+
...wakeups.map((job) => job.id),
|
|
2554
|
+
...this.cronQueue.flatMap(
|
|
2555
|
+
(item) => item.source === "loop" && item.taskId ? [item.taskId] : []
|
|
2556
|
+
)
|
|
2557
|
+
])
|
|
2558
|
+
};
|
|
2559
|
+
}
|
|
2560
|
+
#hasRelevantTodoStopGuardBackgroundInput() {
|
|
2561
|
+
if (this.notificationQueue.some(
|
|
2562
|
+
(item) => this.#notificationContinuesTodoStopGuardWorkChain(item)
|
|
2563
|
+
) || this.cronQueue.some(
|
|
2564
|
+
(item) => this.#cronContinuesTodoStopGuardWorkChain(item)
|
|
2565
|
+
)) {
|
|
2566
|
+
return true;
|
|
2567
|
+
}
|
|
2568
|
+
const baseline = this.todoStopGuardBackgroundBaseline;
|
|
2569
|
+
const agents = this.config.getBackgroundTaskRegistry?.()?.getAll?.() ?? [];
|
|
2570
|
+
if (agents.some(
|
|
2571
|
+
(task) => !baseline.agents.has(task.id) && task.isBackgrounded && (task.status === "running" || task.status === "paused" || task.status === "cancelled" && !task.notified)
|
|
2572
|
+
)) {
|
|
2573
|
+
return true;
|
|
2574
|
+
}
|
|
2575
|
+
const shells = this.config.getBackgroundShellRegistry?.()?.getAll?.() ?? [];
|
|
2576
|
+
if (shells.some(
|
|
2577
|
+
(task) => !baseline.shells.has(task.id) && task.status === "running"
|
|
2578
|
+
)) {
|
|
2579
|
+
return true;
|
|
2580
|
+
}
|
|
2581
|
+
const monitors = this.config.getMonitorRegistry?.()?.getAll?.() ?? [];
|
|
2582
|
+
if (monitors.some(
|
|
2583
|
+
(task) => !baseline.monitors.has(task.id) && task.status === "running"
|
|
2584
|
+
)) {
|
|
2585
|
+
return true;
|
|
2586
|
+
}
|
|
2587
|
+
if (!this.config.isCronEnabled?.()) return false;
|
|
2588
|
+
const wakeups = this.config.getCronScheduler?.()?.list?.() ?? [];
|
|
2589
|
+
return wakeups.some(
|
|
2590
|
+
(job) => job.cronExpr === "@wakeup" && !baseline.wakeups.has(job.id)
|
|
2591
|
+
);
|
|
2592
|
+
}
|
|
2172
2593
|
/**
|
|
2173
2594
|
* Wire the sub-session spawner to the daemon over the ACP `extMethod` request
|
|
2174
2595
|
* channel. The `create_sub_session` tool (model-initiated) is its caller. ONLY
|
|
@@ -2236,6 +2657,9 @@ var Session = class {
|
|
|
2236
2657
|
}
|
|
2237
2658
|
dispose() {
|
|
2238
2659
|
this.disposed = true;
|
|
2660
|
+
this.todoStopGuardQueuedPromptPriority = false;
|
|
2661
|
+
this.todoStopGuardDrainAutomaticQueuesWhenIdle = false;
|
|
2662
|
+
this.todoStopGuard.clearTrust();
|
|
2239
2663
|
this.notificationQueue = [];
|
|
2240
2664
|
this.cronQueue = [];
|
|
2241
2665
|
this.notificationAbortController?.abort();
|
|
@@ -2275,21 +2699,42 @@ var Session = class {
|
|
|
2275
2699
|
);
|
|
2276
2700
|
}
|
|
2277
2701
|
}
|
|
2278
|
-
|
|
2702
|
+
/**
|
|
2703
|
+
* Installs (or replaces) this session's goal-terminal observer.
|
|
2704
|
+
*
|
|
2705
|
+
* Public because it does not stay installed: `registerGoalHook` and
|
|
2706
|
+
* `unregisterGoalHook` both clear the observer table for the session, so any
|
|
2707
|
+
* caller that (re-)registers a goal outside `#processSlashCommandResult` —
|
|
2708
|
+
* notably goal restore on resume — has to put it back. Idempotent.
|
|
2709
|
+
*/
|
|
2710
|
+
installGoalTerminalObserver() {
|
|
2279
2711
|
setGoalTerminalObserver(this.sessionId, (event) => {
|
|
2280
2712
|
void this.messageEmitter.emitGoalTerminal(event).catch((error) => {
|
|
2281
2713
|
debugLogger6.warn(
|
|
2282
2714
|
`Failed to emit goal terminal update: ${this.#formatError(error)}`
|
|
2283
2715
|
);
|
|
2284
2716
|
});
|
|
2717
|
+
recordGoalStatusItem(this.config, goalTerminalEventToHistoryItem(event));
|
|
2285
2718
|
});
|
|
2286
2719
|
}
|
|
2720
|
+
/**
|
|
2721
|
+
* Emits a goal card and persists it to the transcript. Both `set` and
|
|
2722
|
+
* `cleared` reach the client this way — from `#emitGoalStatusItems` for a
|
|
2723
|
+
* `/goal` prompt, and from the `sessionGoalClear` ext method — so recording
|
|
2724
|
+
* here (rather than at each call site) keeps the transcript in step with the
|
|
2725
|
+
* hook. Replay goes through `messageEmitter.emitGoalStatus` directly and so
|
|
2726
|
+
* does not re-record.
|
|
2727
|
+
*/
|
|
2287
2728
|
emitGoalStatus(status) {
|
|
2288
2729
|
void this.messageEmitter.emitGoalStatus(status).catch((error) => {
|
|
2289
2730
|
debugLogger6.warn(
|
|
2290
2731
|
`Failed to emit goal status update: ${this.#formatError(error)}`
|
|
2291
2732
|
);
|
|
2292
2733
|
});
|
|
2734
|
+
recordGoalStatusItem(this.config, {
|
|
2735
|
+
type: "goal_status" /* GOAL_STATUS */,
|
|
2736
|
+
...status
|
|
2737
|
+
});
|
|
2293
2738
|
}
|
|
2294
2739
|
/**
|
|
2295
2740
|
* Replays conversation history to the client using modular components.
|
|
@@ -2332,6 +2777,9 @@ var Session = class {
|
|
|
2332
2777
|
}
|
|
2333
2778
|
chat.truncateHistory(apiTruncateIndex);
|
|
2334
2779
|
chat.stripThoughtsFromHistory();
|
|
2780
|
+
const preserveQueuedPromptPriority = this.todoStopGuardQueuedPromptPriority;
|
|
2781
|
+
const shouldDrainAutomaticQueues = (this.todoStopGuard.blocksUnrelatedAutomaticTurns || this.todoStopGuard.hasCommittedContinuation) && !preserveQueuedPromptPriority;
|
|
2782
|
+
this.todoStopGuard.blockUntilOrdinaryPromptStarts();
|
|
2335
2783
|
const rewindFiles = opts?.rewindFiles !== false;
|
|
2336
2784
|
const fileHistoryService = this.config.getFileHistoryService();
|
|
2337
2785
|
const survivingSnapshots = rewindFiles ? fileHistoryService.getSnapshots().slice(0, targetTurnIndex + 1) : void 0;
|
|
@@ -2343,6 +2791,10 @@ var Session = class {
|
|
|
2343
2791
|
{ truncatedCount: Math.max(0, apiHistory.length - apiTruncateIndex) },
|
|
2344
2792
|
survivingSnapshots
|
|
2345
2793
|
);
|
|
2794
|
+
if (shouldDrainAutomaticQueues) {
|
|
2795
|
+
void this.#drainCronQueue();
|
|
2796
|
+
void this.#drainNotificationQueue();
|
|
2797
|
+
}
|
|
2346
2798
|
return { targetTurnIndex, apiTruncateIndex };
|
|
2347
2799
|
}
|
|
2348
2800
|
captureHistorySnapshot() {
|
|
@@ -2369,6 +2821,7 @@ var Session = class {
|
|
|
2369
2821
|
);
|
|
2370
2822
|
}
|
|
2371
2823
|
this.config.getGeminiClient().getChat().setHistory(structuredClone(history));
|
|
2824
|
+
this.#clearTodoStopGuardTrustAndDrainAutomaticQueues();
|
|
2372
2825
|
}
|
|
2373
2826
|
#computeApiTruncationIndexForUserTurn(apiHistory, targetTurnIndex) {
|
|
2374
2827
|
const startIndex = getStartupContextLength(apiHistory, {
|
|
@@ -2397,6 +2850,11 @@ var Session = class {
|
|
|
2397
2850
|
);
|
|
2398
2851
|
if (hasFunctionResponse) return false;
|
|
2399
2852
|
if (isSystemReminderContent(content)) return false;
|
|
2853
|
+
if (content.parts.some(
|
|
2854
|
+
(part) => "text" in part && isTodoStopGuardPromptText(part.text)
|
|
2855
|
+
)) {
|
|
2856
|
+
return false;
|
|
2857
|
+
}
|
|
2400
2858
|
return content.parts.some((part) => "text" in part && part.text);
|
|
2401
2859
|
}
|
|
2402
2860
|
async cancelPendingPrompt() {
|
|
@@ -2410,6 +2868,7 @@ var Session = class {
|
|
|
2410
2868
|
if (!hadPrompt && !hadCron && !hadNotification) {
|
|
2411
2869
|
throw new Error(NOT_CURRENTLY_GENERATING_CANCEL_MESSAGE);
|
|
2412
2870
|
}
|
|
2871
|
+
this.todoStopGuard.suspend();
|
|
2413
2872
|
if (this.pendingPrompt) {
|
|
2414
2873
|
this.pendingPrompt.abort(USER_CANCEL_ABORT_REASON);
|
|
2415
2874
|
this.pendingPrompt = null;
|
|
@@ -2436,6 +2895,7 @@ var Session = class {
|
|
|
2436
2895
|
}
|
|
2437
2896
|
}
|
|
2438
2897
|
async prompt(params) {
|
|
2898
|
+
const todoStopGuardPreparation = this.#prepareTodoStopGuardForPrompt(params);
|
|
2439
2899
|
this.pendingPrompt?.abort();
|
|
2440
2900
|
const pendingSend = new AbortController();
|
|
2441
2901
|
this.pendingPrompt = pendingSend;
|
|
@@ -2477,10 +2937,15 @@ var Session = class {
|
|
|
2477
2937
|
if (pendingSend.signal.aborted) {
|
|
2478
2938
|
return { stopReason: "cancelled" };
|
|
2479
2939
|
}
|
|
2940
|
+
if (todoStopGuardPreparation.startsWorkChain) {
|
|
2941
|
+
this.todoStopGuardQueuedPromptPriority = false;
|
|
2942
|
+
this.todoStopGuard.startOrdinaryPrompt();
|
|
2943
|
+
this.todoStopGuardBackgroundBaseline = this.#captureTodoStopGuardBackgroundBaseline();
|
|
2944
|
+
}
|
|
2480
2945
|
this.duplicateProviderToolCallResponseIds.clear();
|
|
2481
2946
|
let resolveCompletion;
|
|
2482
|
-
this.pendingPromptCompletion = new Promise((
|
|
2483
|
-
resolveCompletion =
|
|
2947
|
+
this.pendingPromptCompletion = new Promise((resolve5) => {
|
|
2948
|
+
resolveCompletion = resolve5;
|
|
2484
2949
|
});
|
|
2485
2950
|
try {
|
|
2486
2951
|
const result = await this.#executePrompt(params, pendingSend);
|
|
@@ -2491,6 +2956,12 @@ var Session = class {
|
|
|
2491
2956
|
return result;
|
|
2492
2957
|
} finally {
|
|
2493
2958
|
this.pendingPrompt = null;
|
|
2959
|
+
const shouldDrainAutomaticQueues = todoStopGuardPreparation.drainSupersededAutomaticQueues || this.todoStopGuardDrainAutomaticQueuesWhenIdle || this.todoStopGuard.blocksUnrelatedAutomaticTurns || this.todoStopGuard.hasCommittedContinuation || this.todoStopGuardQueuedPromptPriority;
|
|
2960
|
+
this.todoStopGuardDrainAutomaticQueuesWhenIdle = false;
|
|
2961
|
+
if (shouldDrainAutomaticQueues) {
|
|
2962
|
+
void this.#drainCronQueue();
|
|
2963
|
+
void this.#drainNotificationQueue();
|
|
2964
|
+
}
|
|
2494
2965
|
void this.#startCronSchedulerIfNeeded();
|
|
2495
2966
|
resolveCompletion();
|
|
2496
2967
|
this.pendingPromptCompletion = null;
|
|
@@ -2552,6 +3023,9 @@ var Session = class {
|
|
|
2552
3023
|
*/
|
|
2553
3024
|
#maybeEmitFollowupSuggestion(result) {
|
|
2554
3025
|
if (result.stopReason !== "end_turn") return;
|
|
3026
|
+
if (this.todoStopGuard.blocksUnrelatedAutomaticTurns || this.todoStopGuardQueuedPromptPriority) {
|
|
3027
|
+
return;
|
|
3028
|
+
}
|
|
2555
3029
|
if (this.settings.merged.ui?.enableFollowupSuggestions === false) return;
|
|
2556
3030
|
if (this.config.getApprovalMode() === "plan" /* PLAN */) return;
|
|
2557
3031
|
const chat = this.config.getGeminiClient()?.getChat();
|
|
@@ -2686,6 +3160,14 @@ var Session = class {
|
|
|
2686
3160
|
);
|
|
2687
3161
|
const inputText = firstTextBlock?.text || "";
|
|
2688
3162
|
let parts;
|
|
3163
|
+
let fullTurnModelOverride;
|
|
3164
|
+
const onFullTurnModel = /* @__PURE__ */ __name((model) => {
|
|
3165
|
+
if (fullTurnModelOverride) {
|
|
3166
|
+
return false;
|
|
3167
|
+
}
|
|
3168
|
+
fullTurnModelOverride = model;
|
|
3169
|
+
return true;
|
|
3170
|
+
}, "onFullTurnModel");
|
|
2689
3171
|
if (isContinue) {
|
|
2690
3172
|
parts = continuationParts;
|
|
2691
3173
|
} else if (isSlashCommand(inputText)) {
|
|
@@ -2697,7 +3179,9 @@ var Session = class {
|
|
|
2697
3179
|
);
|
|
2698
3180
|
parts = await this.#processSlashCommandResult(
|
|
2699
3181
|
slashCommandResult,
|
|
2700
|
-
params.prompt
|
|
3182
|
+
params.prompt,
|
|
3183
|
+
pendingSend.signal,
|
|
3184
|
+
onFullTurnModel
|
|
2701
3185
|
);
|
|
2702
3186
|
if (parts === null) {
|
|
2703
3187
|
return { stopReason: "end_turn" };
|
|
@@ -2706,7 +3190,7 @@ var Session = class {
|
|
|
2706
3190
|
parts = await this.#resolvePrompt(
|
|
2707
3191
|
params.prompt,
|
|
2708
3192
|
pendingSend.signal,
|
|
2709
|
-
{ promptLast: true }
|
|
3193
|
+
{ promptLast: true, onFullTurnModel }
|
|
2710
3194
|
);
|
|
2711
3195
|
}
|
|
2712
3196
|
const hooksEnabled = !this.config.getDisableAllHooks?.();
|
|
@@ -2777,6 +3261,7 @@ ${this.pendingWorktreeNotice}
|
|
|
2777
3261
|
while (nextMessage !== null) {
|
|
2778
3262
|
turnCount++;
|
|
2779
3263
|
if (pendingSend.signal.aborted) {
|
|
3264
|
+
this.todoStopGuard.suspend();
|
|
2780
3265
|
this.#getCurrentChat().addHistory(nextMessage);
|
|
2781
3266
|
return { stopReason: "cancelled" };
|
|
2782
3267
|
}
|
|
@@ -2793,9 +3278,11 @@ ${this.pendingWorktreeNotice}
|
|
|
2793
3278
|
const sendResult = await this.#sendMessageStreamWithAutoCompression(
|
|
2794
3279
|
promptId,
|
|
2795
3280
|
nextMessage?.parts ?? [],
|
|
2796
|
-
pendingSend.signal
|
|
3281
|
+
pendingSend.signal,
|
|
3282
|
+
{ modelOverride: fullTurnModelOverride }
|
|
2797
3283
|
);
|
|
2798
3284
|
if (!sendResult.responseStream) {
|
|
3285
|
+
this.todoStopGuard.suspend();
|
|
2799
3286
|
this.#preserveUnsentMessageHistory(
|
|
2800
3287
|
nextMessage,
|
|
2801
3288
|
isContinue || sendResult.stopReason === "cancelled"
|
|
@@ -2808,6 +3295,7 @@ ${this.pendingWorktreeNotice}
|
|
|
2808
3295
|
try {
|
|
2809
3296
|
for await (const resp of responseStream) {
|
|
2810
3297
|
if (pendingSend.signal.aborted) {
|
|
3298
|
+
this.todoStopGuard.suspend();
|
|
2811
3299
|
return { stopReason: "cancelled" };
|
|
2812
3300
|
}
|
|
2813
3301
|
if (resp.type === "chunk" /* CHUNK */ && resp.value.candidates && resp.value.candidates.length > 0) {
|
|
@@ -2863,8 +3351,10 @@ ${this.pendingWorktreeNotice}
|
|
|
2863
3351
|
strippedOrphanEntries = null;
|
|
2864
3352
|
}
|
|
2865
3353
|
if (pendingSend.signal.aborted && pendingSend.signal.reason === USER_CANCEL_ABORT_REASON && this.#isAbortError(error)) {
|
|
3354
|
+
this.todoStopGuard.suspend();
|
|
2866
3355
|
return { stopReason: "cancelled" };
|
|
2867
3356
|
}
|
|
3357
|
+
this.todoStopGuard.pauseForTrustedRetry();
|
|
2868
3358
|
const errorStatus = getErrorStatus(error);
|
|
2869
3359
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2870
3360
|
const errorType = classifyApiError({
|
|
@@ -2901,24 +3391,31 @@ ${this.pendingWorktreeNotice}
|
|
|
2901
3391
|
);
|
|
2902
3392
|
}
|
|
2903
3393
|
if (functionCalls.length > 0) {
|
|
2904
|
-
const toolRun = await this
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
3394
|
+
const toolRun = await this.#runWithFullTurnModel(
|
|
3395
|
+
fullTurnModelOverride,
|
|
3396
|
+
() => this.runToolCalls(
|
|
3397
|
+
pendingSend.signal,
|
|
3398
|
+
promptId,
|
|
3399
|
+
functionCalls,
|
|
3400
|
+
toolLoopState
|
|
3401
|
+
)
|
|
2909
3402
|
);
|
|
2910
3403
|
if (toolRun.stopAfterPermissionCancel) {
|
|
3404
|
+
this.todoStopGuard.suspend();
|
|
2911
3405
|
await this.#preserveStoppedToolRun(
|
|
2912
3406
|
toolRun,
|
|
2913
3407
|
pendingSend.signal
|
|
2914
3408
|
);
|
|
2915
3409
|
return { stopReason: "end_turn" };
|
|
2916
3410
|
}
|
|
2917
|
-
|
|
3411
|
+
const nextAfterTools = await this.#buildNextMessageAfterToolRun(
|
|
2918
3412
|
toolRun,
|
|
2919
|
-
pendingSend.signal
|
|
3413
|
+
pendingSend.signal,
|
|
3414
|
+
onFullTurnModel
|
|
2920
3415
|
);
|
|
3416
|
+
nextMessage = nextAfterTools.message;
|
|
2921
3417
|
if (toolRun.loopDetected) {
|
|
3418
|
+
this.todoStopGuard.suspend();
|
|
2922
3419
|
await this.#preserveStoppedToolRun(
|
|
2923
3420
|
toolRun,
|
|
2924
3421
|
pendingSend.signal
|
|
@@ -2934,7 +3431,9 @@ ${this.pendingWorktreeNotice}
|
|
|
2934
3431
|
pendingSend,
|
|
2935
3432
|
promptId,
|
|
2936
3433
|
hooksEnabled,
|
|
2937
|
-
messageBus
|
|
3434
|
+
messageBus,
|
|
3435
|
+
true,
|
|
3436
|
+
fullTurnModelOverride
|
|
2938
3437
|
);
|
|
2939
3438
|
} finally {
|
|
2940
3439
|
logConversationFinishedEvent(
|
|
@@ -2951,220 +3450,558 @@ ${this.pendingWorktreeNotice}
|
|
|
2951
3450
|
}
|
|
2952
3451
|
);
|
|
2953
3452
|
}
|
|
2954
|
-
|
|
2955
|
-
* Handles the Stop hook iteration loop.
|
|
2956
|
-
* This method processes Stop hooks after a model response completes with no pending tool calls.
|
|
2957
|
-
* If a Stop hook requests continuation, it sends a follow-up message and loops back.
|
|
2958
|
-
* Maximum iterations (100) prevent infinite loops.
|
|
2959
|
-
*
|
|
2960
|
-
* @param pendingSend - The abort controller for the current prompt
|
|
2961
|
-
* @param promptId - The prompt ID for tracking
|
|
2962
|
-
* @param hooksEnabled - Whether hooks are enabled
|
|
2963
|
-
* @param messageBus - The MessageBus for hook communication (may be undefined)
|
|
2964
|
-
* @returns The ACP stop reason for the prompt.
|
|
2965
|
-
*/
|
|
2966
|
-
async #handleStopHookLoop(pendingSend, promptId, hooksEnabled, messageBus) {
|
|
3453
|
+
async #handleStopHookLoop(pendingSend, promptId, hooksEnabled, messageBus, allowExternalHooks = true, modelOverride) {
|
|
2967
3454
|
const stopHookBlockingCap = this.config.getStopHookBlockingCap();
|
|
2968
3455
|
let stopHookIterationCount = 0;
|
|
2969
3456
|
let stopHookReasons = [];
|
|
2970
|
-
|
|
2971
|
-
if (
|
|
3457
|
+
const onFullTurnModel = /* @__PURE__ */ __name((model) => {
|
|
3458
|
+
if (modelOverride) {
|
|
3459
|
+
return false;
|
|
3460
|
+
}
|
|
3461
|
+
modelOverride = model;
|
|
3462
|
+
return true;
|
|
3463
|
+
}, "onFullTurnModel");
|
|
3464
|
+
let midTurnContinuationCount = 0;
|
|
3465
|
+
while (true) {
|
|
3466
|
+
if (pendingSend.signal.aborted) {
|
|
3467
|
+
this.todoStopGuard.suspend();
|
|
2972
3468
|
return { stopReason: "end_turn" };
|
|
2973
3469
|
}
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
const continueReason = stopOutput.getEffectiveReason();
|
|
3002
|
-
stopHookIterationCount++;
|
|
3003
|
-
stopHookReasons = [...stopHookReasons, continueReason];
|
|
3004
|
-
if (stopHookIterationCount >= stopHookBlockingCap) {
|
|
3005
|
-
const warning = formatStopHookBlockingCapWarning(
|
|
3006
|
-
"Stop",
|
|
3007
|
-
stopHookBlockingCap
|
|
3008
|
-
);
|
|
3009
|
-
abortGoalForStopHookCap(
|
|
3010
|
-
this.config,
|
|
3011
|
-
this.config.getSessionId(),
|
|
3012
|
-
warning
|
|
3470
|
+
if (this.config.getApprovalMode() === "plan" /* PLAN */) {
|
|
3471
|
+
this.#clearTodoStopGuardTrustAndDrainAutomaticQueues();
|
|
3472
|
+
}
|
|
3473
|
+
if (this.todoStopGuardQueuedPromptPriority) {
|
|
3474
|
+
return { stopReason: "end_turn" };
|
|
3475
|
+
}
|
|
3476
|
+
if (this.todoStopGuard.needsStopInspection) {
|
|
3477
|
+
this.#beginTodoStopGuardQueuedPromptCheck();
|
|
3478
|
+
const drained = await this.#drainMidTurnInput(pendingSend.signal, {
|
|
3479
|
+
watchQueuedPromptForTodoStopGuard: true,
|
|
3480
|
+
onFullTurnModel
|
|
3481
|
+
});
|
|
3482
|
+
const waitsForQueuedPrompt = this.#finishTodoStopGuardQueuedPromptCheck(
|
|
3483
|
+
drained.hasQueuedPrompt
|
|
3484
|
+
);
|
|
3485
|
+
if (drained.parts.length > 0) {
|
|
3486
|
+
this.todoStopGuard.acceptMidTurnUserInput();
|
|
3487
|
+
const continuation2 = await this.#runStopContinuation(
|
|
3488
|
+
pendingSend,
|
|
3489
|
+
promptId + "_mid_turn_" + ++midTurnContinuationCount,
|
|
3490
|
+
promptId,
|
|
3491
|
+
drained.parts,
|
|
3492
|
+
false,
|
|
3493
|
+
{
|
|
3494
|
+
onFullTurnModel,
|
|
3495
|
+
getModelOverride: /* @__PURE__ */ __name(() => modelOverride, "getModelOverride")
|
|
3496
|
+
}
|
|
3013
3497
|
);
|
|
3014
|
-
|
|
3015
|
-
|
|
3498
|
+
if (continuation2.kind === "terminal") {
|
|
3499
|
+
return { stopReason: continuation2.stopReason };
|
|
3500
|
+
}
|
|
3501
|
+
continue;
|
|
3502
|
+
}
|
|
3503
|
+
if (waitsForQueuedPrompt) {
|
|
3016
3504
|
return { stopReason: "end_turn" };
|
|
3017
3505
|
}
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3506
|
+
}
|
|
3507
|
+
let externalReason = null;
|
|
3508
|
+
let stopHookCount = 1;
|
|
3509
|
+
let queuedPromptArrivedDuringStopHook = false;
|
|
3510
|
+
if (allowExternalHooks && hooksEnabled && messageBus && stopHookIterationCount < stopHookBlockingCap && this.config.hasHooksForEvent?.("Stop")) {
|
|
3511
|
+
const responseText = this.#getCurrentChat().getLastModelMessageText?.() || "[no response text]";
|
|
3512
|
+
const contextUsage = buildContextUsage(
|
|
3513
|
+
this.config.getContentGeneratorConfig()?.contextWindowSize ?? DEFAULT_TOKEN_LIMIT,
|
|
3514
|
+
this.lastPromptTokenCount
|
|
3515
|
+
);
|
|
3516
|
+
let response;
|
|
3517
|
+
try {
|
|
3518
|
+
response = await messageBus.request(
|
|
3519
|
+
{
|
|
3520
|
+
type: "hook-execution-request" /* HOOK_EXECUTION_REQUEST */,
|
|
3521
|
+
eventName: "Stop",
|
|
3522
|
+
input: {
|
|
3523
|
+
stop_hook_active: true,
|
|
3524
|
+
last_assistant_message: responseText,
|
|
3525
|
+
...contextUsage
|
|
3526
|
+
},
|
|
3527
|
+
signal: pendingSend.signal
|
|
3528
|
+
},
|
|
3529
|
+
"hook-execution-response" /* HOOK_EXECUTION_RESPONSE */
|
|
3023
3530
|
);
|
|
3531
|
+
} catch (error) {
|
|
3532
|
+
this.todoStopGuard.pauseForTrustedRetry();
|
|
3533
|
+
throw error;
|
|
3024
3534
|
}
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
}
|
|
3035
|
-
const
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
{ skipCompression: stopHookIterationCount > 1 }
|
|
3535
|
+
if (pendingSend.signal.aborted) {
|
|
3536
|
+
this.todoStopGuard.suspend();
|
|
3537
|
+
return { stopReason: "cancelled" };
|
|
3538
|
+
}
|
|
3539
|
+
if (this.todoStopGuard.needsStopInspection) {
|
|
3540
|
+
this.#beginTodoStopGuardQueuedPromptCheck();
|
|
3541
|
+
const drained = await this.#drainMidTurnInput(pendingSend.signal, {
|
|
3542
|
+
watchQueuedPromptForTodoStopGuard: true,
|
|
3543
|
+
onFullTurnModel
|
|
3544
|
+
});
|
|
3545
|
+
const waitsForQueuedPrompt = this.#finishTodoStopGuardQueuedPromptCheck(drained.hasQueuedPrompt);
|
|
3546
|
+
queuedPromptArrivedDuringStopHook = waitsForQueuedPrompt;
|
|
3547
|
+
if (drained.parts.length > 0) {
|
|
3548
|
+
this.todoStopGuard.acceptMidTurnUserInput();
|
|
3549
|
+
const continuation2 = await this.#runStopContinuation(
|
|
3550
|
+
pendingSend,
|
|
3551
|
+
promptId + "_mid_turn_" + ++midTurnContinuationCount,
|
|
3552
|
+
promptId,
|
|
3553
|
+
drained.parts,
|
|
3554
|
+
false,
|
|
3555
|
+
{
|
|
3556
|
+
onFullTurnModel,
|
|
3557
|
+
getModelOverride: /* @__PURE__ */ __name(() => modelOverride, "getModelOverride")
|
|
3558
|
+
}
|
|
3050
3559
|
);
|
|
3051
|
-
if (
|
|
3052
|
-
|
|
3053
|
-
nextMessage,
|
|
3054
|
-
continueSendResult.stopReason === "cancelled"
|
|
3055
|
-
);
|
|
3056
|
-
return { stopReason: continueSendResult.stopReason };
|
|
3560
|
+
if (continuation2.kind === "terminal") {
|
|
3561
|
+
return { stopReason: continuation2.stopReason };
|
|
3057
3562
|
}
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3563
|
+
}
|
|
3564
|
+
}
|
|
3565
|
+
const hookOutput = response.output ? createHookOutput("Stop", response.output) : void 0;
|
|
3566
|
+
const stopOutput = hookOutput;
|
|
3567
|
+
if (stopOutput?.systemMessage) {
|
|
3568
|
+
await this.messageEmitter.emitAgentMessage(stopOutput.systemMessage);
|
|
3569
|
+
}
|
|
3570
|
+
if (stopOutput?.isBlockingDecision() || stopOutput?.shouldStopExecution()) {
|
|
3571
|
+
externalReason = stopOutput.getEffectiveReason();
|
|
3572
|
+
stopHookIterationCount++;
|
|
3573
|
+
stopHookReasons = [...stopHookReasons, externalReason];
|
|
3574
|
+
stopHookCount = response.stopHookCount ?? 1;
|
|
3575
|
+
}
|
|
3576
|
+
}
|
|
3577
|
+
const guardDecision = queuedPromptArrivedDuringStopHook ? null : this.todoStopGuard.decide(
|
|
3578
|
+
this.todoStopGuard.needsStopInspection ? this.#hasRelevantTodoStopGuardBackgroundInput() : false
|
|
3579
|
+
);
|
|
3580
|
+
const guardContinuation = guardDecision?.kind === "continue" ? guardDecision : null;
|
|
3581
|
+
if (guardDecision?.kind === "exhausted") {
|
|
3582
|
+
await this.#emitTodoStopGuardExhausted(guardDecision);
|
|
3583
|
+
if (!externalReason) return { stopReason: "end_turn" };
|
|
3584
|
+
}
|
|
3585
|
+
if (externalReason && stopHookIterationCount >= stopHookBlockingCap) {
|
|
3586
|
+
const warning = formatStopHookBlockingCapWarning(
|
|
3587
|
+
"Stop",
|
|
3588
|
+
stopHookBlockingCap
|
|
3589
|
+
);
|
|
3590
|
+
abortGoalForStopHookCap(
|
|
3591
|
+
this.config,
|
|
3592
|
+
this.config.getSessionId(),
|
|
3593
|
+
warning
|
|
3594
|
+
);
|
|
3595
|
+
this.todoStopGuard.suspend();
|
|
3596
|
+
await this.messageEmitter.emitAgentMessage(warning);
|
|
3597
|
+
debugLogger6.warn(warning);
|
|
3598
|
+
return { stopReason: "end_turn" };
|
|
3599
|
+
}
|
|
3600
|
+
if (queuedPromptArrivedDuringStopHook) {
|
|
3601
|
+
return { stopReason: "end_turn" };
|
|
3602
|
+
}
|
|
3603
|
+
if (!externalReason && !guardContinuation) {
|
|
3604
|
+
return { stopReason: "end_turn" };
|
|
3605
|
+
}
|
|
3606
|
+
const continueParts = [];
|
|
3607
|
+
if (externalReason) continueParts.push({ text: externalReason });
|
|
3608
|
+
if (guardContinuation) {
|
|
3609
|
+
continueParts.push({
|
|
3610
|
+
text: this.#buildTodoStopGuardPrompt(guardContinuation)
|
|
3611
|
+
});
|
|
3612
|
+
}
|
|
3613
|
+
const continuationPromptId = externalReason ? promptId + "_stop_hook_" + stopHookIterationCount : promptId + "_todo_stop_guard_" + guardContinuation.attempt;
|
|
3614
|
+
if (externalReason && stopHookIterationCount > 1 && !guardContinuation) {
|
|
3615
|
+
await this.messageEmitter.emitStopHookLoop(
|
|
3616
|
+
stopHookIterationCount,
|
|
3617
|
+
stopHookReasons,
|
|
3618
|
+
stopHookCount
|
|
3619
|
+
);
|
|
3620
|
+
}
|
|
3621
|
+
const continuation = await this.#runStopContinuation(
|
|
3622
|
+
pendingSend,
|
|
3623
|
+
continuationPromptId,
|
|
3624
|
+
promptId,
|
|
3625
|
+
continueParts,
|
|
3626
|
+
stopHookIterationCount > 1 || (guardContinuation?.attempt ?? 0) > 1,
|
|
3627
|
+
{
|
|
3628
|
+
...guardContinuation ? { guardContinuation } : {},
|
|
3629
|
+
...externalReason ? { externalParts: [{ text: externalReason }] } : {},
|
|
3630
|
+
...externalReason && stopHookIterationCount > 1 && guardContinuation ? {
|
|
3631
|
+
onAutomaticContinuationValidated: /* @__PURE__ */ __name(() => this.messageEmitter.emitStopHookLoop(
|
|
3632
|
+
stopHookIterationCount,
|
|
3633
|
+
stopHookReasons,
|
|
3634
|
+
stopHookCount
|
|
3635
|
+
), "onAutomaticContinuationValidated")
|
|
3636
|
+
} : {},
|
|
3637
|
+
onFullTurnModel,
|
|
3638
|
+
getModelOverride: /* @__PURE__ */ __name(() => modelOverride, "getModelOverride")
|
|
3639
|
+
}
|
|
3640
|
+
);
|
|
3641
|
+
if (continuation.supersededAutomaticContinuation && externalReason) {
|
|
3642
|
+
stopHookIterationCount--;
|
|
3643
|
+
stopHookReasons = stopHookReasons.slice(0, -1);
|
|
3644
|
+
}
|
|
3645
|
+
if (continuation.kind === "terminal") {
|
|
3646
|
+
return { stopReason: continuation.stopReason };
|
|
3647
|
+
}
|
|
3648
|
+
}
|
|
3649
|
+
}
|
|
3650
|
+
async #runStopContinuation(pendingSend, streamPromptId, toolPromptId, parts, skipCompression, options = {}) {
|
|
3651
|
+
let nextMessage = { role: "user", parts };
|
|
3652
|
+
let nextGuardContinuation = options.guardContinuation;
|
|
3653
|
+
const toolLoopState = createDaemonToolLoopState();
|
|
3654
|
+
let initialSend = true;
|
|
3655
|
+
let automaticContinuationValidated = false;
|
|
3656
|
+
let supersededAutomaticContinuation = false;
|
|
3657
|
+
while (nextMessage !== null) {
|
|
3658
|
+
if (pendingSend.signal.aborted) {
|
|
3659
|
+
this.todoStopGuard.suspend();
|
|
3660
|
+
return {
|
|
3661
|
+
kind: "terminal",
|
|
3662
|
+
stopReason: "cancelled",
|
|
3663
|
+
...supersededAutomaticContinuation ? { supersededAutomaticContinuation: true } : {}
|
|
3664
|
+
};
|
|
3665
|
+
}
|
|
3666
|
+
const functionCalls = [];
|
|
3667
|
+
const preparationTracker = new ToolCallPreparationTracker(
|
|
3668
|
+
this.toolCallEmitter
|
|
3669
|
+
);
|
|
3670
|
+
let usageMetadata = null;
|
|
3671
|
+
const streamStartTime = Date.now();
|
|
3672
|
+
let streamFailed = false;
|
|
3673
|
+
let guardForThisSend = nextGuardContinuation;
|
|
3674
|
+
let preserveGuardOnSkippedSend = false;
|
|
3675
|
+
let messageForPreservation = nextMessage;
|
|
3676
|
+
const externalParts = initialSend ? options.externalParts : void 0;
|
|
3677
|
+
const promptIdForSend = guardForThisSend && guardForThisSend.attempt !== options.guardContinuation?.attempt ? toolPromptId + "_todo_stop_guard_" + guardForThisSend.attempt : streamPromptId;
|
|
3678
|
+
const messageDisplay = this.#createMessageDisplayDispatcher(
|
|
3679
|
+
pendingSend.signal
|
|
3680
|
+
);
|
|
3681
|
+
try {
|
|
3682
|
+
const sendResult = await this.#sendMessageStreamWithAutoCompression(
|
|
3683
|
+
promptIdForSend,
|
|
3684
|
+
nextMessage.parts ?? [],
|
|
3685
|
+
pendingSend.signal,
|
|
3686
|
+
{
|
|
3687
|
+
skipCompression: skipCompression || (guardForThisSend?.attempt ?? 0) > 1,
|
|
3688
|
+
getModelOverride: options.getModelOverride,
|
|
3689
|
+
beforeSend: guardForThisSend || !automaticContinuationValidated && options.onAutomaticContinuationValidated ? async ({ compressionFailed }) => {
|
|
3690
|
+
const inspectGuardPriority = guardForThisSend !== void 0;
|
|
3691
|
+
const guardCompressionFailed = inspectGuardPriority && compressionFailed;
|
|
3692
|
+
if (inspectGuardPriority) {
|
|
3693
|
+
this.#beginTodoStopGuardQueuedPromptCheck();
|
|
3694
|
+
const drained = await this.#drainMidTurnInput(
|
|
3695
|
+
pendingSend.signal,
|
|
3696
|
+
{
|
|
3697
|
+
watchQueuedPromptForTodoStopGuard: true,
|
|
3698
|
+
onFullTurnModel: options.onFullTurnModel
|
|
3699
|
+
}
|
|
3700
|
+
);
|
|
3701
|
+
const waitsForQueuedPrompt = this.#finishTodoStopGuardQueuedPromptCheck(
|
|
3702
|
+
drained.hasQueuedPrompt
|
|
3703
|
+
);
|
|
3704
|
+
if (drained.parts.length > 0) {
|
|
3705
|
+
this.todoStopGuard.acceptMidTurnUserInput();
|
|
3706
|
+
guardForThisSend = void 0;
|
|
3707
|
+
nextGuardContinuation = void 0;
|
|
3708
|
+
if (initialSend) {
|
|
3709
|
+
supersededAutomaticContinuation = true;
|
|
3078
3710
|
}
|
|
3711
|
+
const replacementMessage = initialSend ? drained.parts : [
|
|
3712
|
+
...(nextMessage?.parts ?? []).filter(
|
|
3713
|
+
(part) => !("text" in part && isTodoStopGuardPromptText(part.text))
|
|
3714
|
+
),
|
|
3715
|
+
...drained.parts
|
|
3716
|
+
];
|
|
3717
|
+
messageForPreservation = {
|
|
3718
|
+
role: "user",
|
|
3719
|
+
parts: replacementMessage
|
|
3720
|
+
};
|
|
3721
|
+
return {
|
|
3722
|
+
kind: "send",
|
|
3723
|
+
message: replacementMessage
|
|
3724
|
+
};
|
|
3079
3725
|
}
|
|
3080
|
-
if (
|
|
3081
|
-
|
|
3726
|
+
if (waitsForQueuedPrompt) {
|
|
3727
|
+
guardForThisSend = void 0;
|
|
3728
|
+
nextGuardContinuation = void 0;
|
|
3729
|
+
preserveGuardOnSkippedSend = true;
|
|
3730
|
+
if (initialSend) {
|
|
3731
|
+
supersededAutomaticContinuation = true;
|
|
3732
|
+
}
|
|
3733
|
+
return { kind: "stop", stopReason: "end_turn" };
|
|
3082
3734
|
}
|
|
3083
|
-
if (
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3735
|
+
if (guardCompressionFailed) {
|
|
3736
|
+
this.todoStopGuard.suspend();
|
|
3737
|
+
guardForThisSend = void 0;
|
|
3738
|
+
nextGuardContinuation = void 0;
|
|
3739
|
+
if (!externalParts || externalParts.length === 0) {
|
|
3740
|
+
preserveGuardOnSkippedSend = true;
|
|
3741
|
+
return { kind: "stop", stopReason: "end_turn" };
|
|
3088
3742
|
}
|
|
3089
3743
|
}
|
|
3090
|
-
if (
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3744
|
+
if (guardForThisSend && this.config.getApprovalMode() === "plan" /* PLAN */) {
|
|
3745
|
+
this.#clearTodoStopGuardTrustAndDrainAutomaticQueues();
|
|
3746
|
+
}
|
|
3747
|
+
if (guardForThisSend) {
|
|
3748
|
+
const hasRelevantBackgroundInput = this.#hasRelevantTodoStopGuardBackgroundInput();
|
|
3749
|
+
const refreshedDecision = guardForThisSend.toolClosure ? this.todoStopGuard.decideToolClosure(
|
|
3750
|
+
guardForThisSend.attempt - 1,
|
|
3751
|
+
hasRelevantBackgroundInput
|
|
3752
|
+
) : this.todoStopGuard.decide(
|
|
3753
|
+
hasRelevantBackgroundInput
|
|
3095
3754
|
);
|
|
3096
|
-
|
|
3755
|
+
if (refreshedDecision.kind !== "continue" || refreshedDecision.attempt !== guardForThisSend.attempt) {
|
|
3756
|
+
guardForThisSend = void 0;
|
|
3757
|
+
nextGuardContinuation = void 0;
|
|
3758
|
+
if (!options.externalParts) {
|
|
3759
|
+
preserveGuardOnSkippedSend = true;
|
|
3760
|
+
return { kind: "stop", stopReason: "end_turn" };
|
|
3761
|
+
}
|
|
3762
|
+
if (!initialSend && nextMessage) {
|
|
3763
|
+
nextMessage = {
|
|
3764
|
+
...nextMessage,
|
|
3765
|
+
parts: (nextMessage.parts ?? []).filter(
|
|
3766
|
+
(part) => !("text" in part && isTodoStopGuardPromptText(part.text))
|
|
3767
|
+
)
|
|
3768
|
+
};
|
|
3769
|
+
}
|
|
3770
|
+
}
|
|
3097
3771
|
}
|
|
3098
3772
|
}
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3773
|
+
if (!automaticContinuationValidated && options.onAutomaticContinuationValidated) {
|
|
3774
|
+
await options.onAutomaticContinuationValidated();
|
|
3775
|
+
automaticContinuationValidated = true;
|
|
3776
|
+
}
|
|
3777
|
+
const selectedMessage = guardForThisSend || !externalParts ? nextMessage?.parts ?? [] : externalParts;
|
|
3778
|
+
messageForPreservation = {
|
|
3779
|
+
role: "user",
|
|
3780
|
+
parts: selectedMessage
|
|
3781
|
+
};
|
|
3782
|
+
return {
|
|
3783
|
+
kind: "send",
|
|
3784
|
+
message: selectedMessage
|
|
3785
|
+
};
|
|
3786
|
+
} : void 0
|
|
3787
|
+
}
|
|
3788
|
+
);
|
|
3789
|
+
if (!sendResult.responseStream) {
|
|
3790
|
+
if (!automaticContinuationValidated && !supersededAutomaticContinuation && options.onAutomaticContinuationValidated) {
|
|
3791
|
+
await options.onAutomaticContinuationValidated();
|
|
3792
|
+
automaticContinuationValidated = true;
|
|
3793
|
+
}
|
|
3794
|
+
if (!preserveGuardOnSkippedSend) {
|
|
3795
|
+
this.todoStopGuard.suspend();
|
|
3796
|
+
}
|
|
3797
|
+
const preservedParts = (messageForPreservation.parts ?? []).filter(
|
|
3798
|
+
(part) => !("text" in part && isTodoStopGuardPromptText(part.text))
|
|
3799
|
+
);
|
|
3800
|
+
this.#preserveUnsentMessageHistory(
|
|
3801
|
+
preservedParts.length > 0 ? { ...messageForPreservation, parts: preservedParts } : null,
|
|
3802
|
+
sendResult.stopReason === "cancelled"
|
|
3803
|
+
);
|
|
3804
|
+
return {
|
|
3805
|
+
kind: "terminal",
|
|
3806
|
+
stopReason: sendResult.stopReason,
|
|
3807
|
+
...supersededAutomaticContinuation ? { supersededAutomaticContinuation: true } : {}
|
|
3808
|
+
};
|
|
3809
|
+
}
|
|
3810
|
+
const responseStream = sendResult.responseStream;
|
|
3811
|
+
nextMessage = null;
|
|
3812
|
+
initialSend = false;
|
|
3813
|
+
if (guardForThisSend) {
|
|
3814
|
+
const guardCommitted = this.todoStopGuard.commitContinuation(
|
|
3815
|
+
guardForThisSend.attempt
|
|
3816
|
+
);
|
|
3817
|
+
if (guardCommitted) {
|
|
3818
|
+
await this.#emitTodoStopGuardContinuation(guardForThisSend);
|
|
3819
|
+
}
|
|
3820
|
+
if (!guardCommitted && externalParts) {
|
|
3821
|
+
guardForThisSend = void 0;
|
|
3822
|
+
}
|
|
3823
|
+
}
|
|
3824
|
+
for await (const response of responseStream) {
|
|
3825
|
+
if (pendingSend.signal.aborted) {
|
|
3826
|
+
this.todoStopGuard.suspend();
|
|
3827
|
+
return {
|
|
3828
|
+
kind: "terminal",
|
|
3829
|
+
stopReason: "cancelled",
|
|
3830
|
+
...supersededAutomaticContinuation ? { supersededAutomaticContinuation: true } : {}
|
|
3831
|
+
};
|
|
3832
|
+
}
|
|
3833
|
+
if (response.type === "chunk" /* CHUNK */ && response.value.candidates && response.value.candidates.length > 0) {
|
|
3834
|
+
const candidate = response.value.candidates[0];
|
|
3835
|
+
for (const part of candidate.content?.parts ?? []) {
|
|
3836
|
+
if (!part.text) continue;
|
|
3837
|
+
this.messageEmitter.emitMessage(
|
|
3838
|
+
part.text,
|
|
3839
|
+
"assistant",
|
|
3840
|
+
part.thought
|
|
3127
3841
|
);
|
|
3842
|
+
if (!part.thought) messageDisplay?.addChunk(part.text);
|
|
3128
3843
|
}
|
|
3129
|
-
throw error;
|
|
3130
|
-
} finally {
|
|
3131
|
-
await messageDisplay?.finish();
|
|
3132
3844
|
}
|
|
3133
|
-
if (usageMetadata) {
|
|
3134
|
-
|
|
3135
|
-
const durationMs = Date.now() - streamStartTime;
|
|
3136
|
-
await this.messageEmitter.emitUsageMetadata(
|
|
3137
|
-
usageMetadata,
|
|
3138
|
-
"",
|
|
3139
|
-
durationMs
|
|
3140
|
-
);
|
|
3845
|
+
if (response.type === "chunk" /* CHUNK */ && response.value.usageMetadata) {
|
|
3846
|
+
usageMetadata = response.value.usageMetadata;
|
|
3141
3847
|
}
|
|
3142
|
-
if (
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
functionCalls
|
|
3147
|
-
toolLoopState
|
|
3148
|
-
);
|
|
3149
|
-
if (toolRun.stopAfterPermissionCancel) {
|
|
3150
|
-
await this.#preserveStoppedToolRun(toolRun, pendingSend.signal);
|
|
3151
|
-
return { stopReason: "end_turn" };
|
|
3848
|
+
if (response.type === "chunk" /* CHUNK */) {
|
|
3849
|
+
await preparationTracker.observe(response.value);
|
|
3850
|
+
if (response.value.functionCalls) {
|
|
3851
|
+
preparationTracker.resolve(response.value.functionCalls);
|
|
3852
|
+
functionCalls.push(...response.value.functionCalls);
|
|
3152
3853
|
}
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3854
|
+
}
|
|
3855
|
+
if (response.type === "retry" /* RETRY */ || response.type === "model_fallback" /* MODEL_FALLBACK */) {
|
|
3856
|
+
await finalizeToolCallPreparations(
|
|
3857
|
+
preparationTracker,
|
|
3858
|
+
true,
|
|
3859
|
+
`daemon continuation ${response.type}`
|
|
3156
3860
|
);
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3861
|
+
functionCalls.length = 0;
|
|
3862
|
+
}
|
|
3863
|
+
}
|
|
3864
|
+
} catch (error) {
|
|
3865
|
+
streamFailed = true;
|
|
3866
|
+
this.todoStopGuard.pauseForTrustedRetry();
|
|
3867
|
+
const errorStatus = getErrorStatus(error);
|
|
3868
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
3869
|
+
const errorType = classifyApiError({
|
|
3870
|
+
message: errorMessage,
|
|
3871
|
+
status: errorStatus
|
|
3872
|
+
});
|
|
3873
|
+
const hookSystem = this.config.getHookSystem?.();
|
|
3874
|
+
if (!this.config.getDisableAllHooks?.() && hookSystem && this.config.hasHooksForEvent?.("StopFailure")) {
|
|
3875
|
+
hookSystem.fireStopFailureEvent(errorType, errorMessage).catch((err) => {
|
|
3876
|
+
debugLogger6.warn(`StopFailure hook failed: ${err}`);
|
|
3877
|
+
});
|
|
3878
|
+
}
|
|
3879
|
+
if (errorStatus === 429) {
|
|
3880
|
+
throw new RequestError(429, "Rate limit exceeded. Try again later.");
|
|
3881
|
+
}
|
|
3882
|
+
throw error;
|
|
3883
|
+
} finally {
|
|
3884
|
+
try {
|
|
3885
|
+
await finalizeToolCallPreparations(
|
|
3886
|
+
preparationTracker,
|
|
3887
|
+
streamFailed || pendingSend.signal.aborted,
|
|
3888
|
+
"daemon continuation"
|
|
3889
|
+
);
|
|
3890
|
+
} finally {
|
|
3891
|
+
await messageDisplay?.finish();
|
|
3892
|
+
}
|
|
3893
|
+
}
|
|
3894
|
+
if (usageMetadata) {
|
|
3895
|
+
this.#recordPromptTokenCount(usageMetadata);
|
|
3896
|
+
const durationMs = Date.now() - streamStartTime;
|
|
3897
|
+
await this.messageEmitter.emitUsageMetadata(
|
|
3898
|
+
usageMetadata,
|
|
3899
|
+
"",
|
|
3900
|
+
durationMs
|
|
3901
|
+
);
|
|
3902
|
+
}
|
|
3903
|
+
if (functionCalls.length > 0) {
|
|
3904
|
+
const toolRun = await this.#runWithFullTurnModel(
|
|
3905
|
+
options.getModelOverride?.(),
|
|
3906
|
+
() => this.runToolCalls(
|
|
3907
|
+
pendingSend.signal,
|
|
3908
|
+
toolPromptId,
|
|
3909
|
+
functionCalls,
|
|
3910
|
+
toolLoopState
|
|
3911
|
+
)
|
|
3912
|
+
);
|
|
3913
|
+
if (toolRun.stopAfterPermissionCancel || toolRun.loopDetected) {
|
|
3914
|
+
this.todoStopGuard.suspend();
|
|
3915
|
+
await this.#preserveStoppedToolRun(toolRun, pendingSend.signal);
|
|
3916
|
+
return {
|
|
3917
|
+
kind: "terminal",
|
|
3918
|
+
stopReason: "end_turn",
|
|
3919
|
+
...supersededAutomaticContinuation ? { supersededAutomaticContinuation: true } : {}
|
|
3920
|
+
};
|
|
3921
|
+
}
|
|
3922
|
+
const nextAfterTools = await this.#buildNextMessageAfterToolRun(
|
|
3923
|
+
toolRun,
|
|
3924
|
+
pendingSend.signal,
|
|
3925
|
+
options.onFullTurnModel
|
|
3926
|
+
);
|
|
3927
|
+
nextMessage = nextAfterTools.message;
|
|
3928
|
+
if (nextAfterTools.hadMidTurnUserInput) {
|
|
3929
|
+
nextGuardContinuation = void 0;
|
|
3930
|
+
continue;
|
|
3931
|
+
}
|
|
3932
|
+
if (guardForThisSend && nextMessage) {
|
|
3933
|
+
const nextDecision = this.todoStopGuard.decideToolClosure(
|
|
3934
|
+
guardForThisSend.attempt,
|
|
3935
|
+
this.#hasRelevantTodoStopGuardBackgroundInput()
|
|
3936
|
+
);
|
|
3937
|
+
if (nextDecision.kind === "continue" && nextDecision.attempt > guardForThisSend.attempt) {
|
|
3938
|
+
nextGuardContinuation = nextDecision;
|
|
3939
|
+
if (!nextDecision.toolClosure) {
|
|
3940
|
+
nextMessage = {
|
|
3941
|
+
...nextMessage,
|
|
3942
|
+
parts: [
|
|
3943
|
+
...nextMessage.parts ?? [],
|
|
3944
|
+
{ text: this.#buildTodoStopGuardPrompt(nextDecision) }
|
|
3945
|
+
]
|
|
3946
|
+
};
|
|
3160
3947
|
}
|
|
3948
|
+
} else if (nextDecision.kind === "continue" && nextDecision.attempt <= guardForThisSend.attempt) {
|
|
3949
|
+
nextGuardContinuation = void 0;
|
|
3950
|
+
} else if (options.externalParts) {
|
|
3951
|
+
nextGuardContinuation = void 0;
|
|
3952
|
+
} else {
|
|
3953
|
+
this.#preserveUnsentMessageHistory(nextMessage, true);
|
|
3954
|
+
return {
|
|
3955
|
+
kind: "natural_stop",
|
|
3956
|
+
...supersededAutomaticContinuation ? { supersededAutomaticContinuation: true } : {}
|
|
3957
|
+
};
|
|
3161
3958
|
}
|
|
3959
|
+
} else {
|
|
3960
|
+
nextGuardContinuation = void 0;
|
|
3162
3961
|
}
|
|
3163
|
-
continue;
|
|
3164
3962
|
}
|
|
3165
|
-
break;
|
|
3166
3963
|
}
|
|
3167
|
-
return {
|
|
3964
|
+
return {
|
|
3965
|
+
kind: "natural_stop",
|
|
3966
|
+
...supersededAutomaticContinuation ? { supersededAutomaticContinuation: true } : {}
|
|
3967
|
+
};
|
|
3968
|
+
}
|
|
3969
|
+
#buildTodoStopGuardPrompt(state) {
|
|
3970
|
+
const prompt = `${TODO_STOP_GUARD_PROMPT_PREFIX}${state.unfinishedCount}${TODO_STOP_GUARD_PROMPT_BODY_SUFFIX}`;
|
|
3971
|
+
if (state.attempt < state.maxAttempts) return prompt;
|
|
3972
|
+
return prompt + TODO_STOP_GUARD_FINAL_PROMPT_SUFFIX;
|
|
3973
|
+
}
|
|
3974
|
+
async #emitTodoStopGuardContinuation(state) {
|
|
3975
|
+
await this.#emitTodoStopGuardMessageSafely(
|
|
3976
|
+
`[Todo Stop Guard] Automatic continuation ${state.attempt}/${state.maxAttempts} started; ${state.unfinishedCount} todo item(s) remain unfinished.`,
|
|
3977
|
+
state
|
|
3978
|
+
);
|
|
3979
|
+
}
|
|
3980
|
+
async #emitTodoStopGuardExhausted(state) {
|
|
3981
|
+
if (!this.todoStopGuard.markExhaustionReported()) return;
|
|
3982
|
+
await this.#emitTodoStopGuardMessageSafely(
|
|
3983
|
+
`[Todo Stop Guard] Automatic continuation stopped after ${state.maxAttempts} attempts; ${state.unfinishedCount} todo item(s) remain unfinished.`,
|
|
3984
|
+
state
|
|
3985
|
+
);
|
|
3986
|
+
}
|
|
3987
|
+
async #emitTodoStopGuardMessageSafely(text, state) {
|
|
3988
|
+
try {
|
|
3989
|
+
await this.sendUpdate({
|
|
3990
|
+
sessionUpdate: "agent_message_chunk",
|
|
3991
|
+
content: { type: "text", text },
|
|
3992
|
+
_meta: {
|
|
3993
|
+
source: "todo_stop_guard",
|
|
3994
|
+
qwenDiscreteMessage: true,
|
|
3995
|
+
attempt: state.attempt,
|
|
3996
|
+
maxAttempts: state.maxAttempts,
|
|
3997
|
+
unfinishedCount: state.unfinishedCount
|
|
3998
|
+
}
|
|
3999
|
+
});
|
|
4000
|
+
} catch (error) {
|
|
4001
|
+
debugLogger6.warn(
|
|
4002
|
+
`Failed to emit Todo Stop Guard status: ${this.#formatError(error)}`
|
|
4003
|
+
);
|
|
4004
|
+
}
|
|
3168
4005
|
}
|
|
3169
4006
|
async sendUpdate(update) {
|
|
3170
4007
|
const params = {
|
|
@@ -3176,14 +4013,13 @@ ${this.pendingWorktreeNotice}
|
|
|
3176
4013
|
#getCurrentChat() {
|
|
3177
4014
|
return this.config.getGeminiClient().getChat();
|
|
3178
4015
|
}
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
*/
|
|
4016
|
+
async #runWithFullTurnModel(modelOverride, fn) {
|
|
4017
|
+
if (!modelOverride?.endsWith("\0")) {
|
|
4018
|
+
return fn();
|
|
4019
|
+
}
|
|
4020
|
+
const runtimeView = await this.config.getBaseLlmClient().resolveForModel(modelOverride.slice(0, -1), { failClosed: true });
|
|
4021
|
+
return runWithRuntimeContentGenerator(runtimeView, fn);
|
|
4022
|
+
}
|
|
3187
4023
|
/**
|
|
3188
4024
|
* Create the MessageDisplay hook dispatcher for one model call's streamed
|
|
3189
4025
|
* reply, or null when the hook isn't registered (the common case — keeps
|
|
@@ -3206,11 +4042,20 @@ ${this.pendingWorktreeNotice}
|
|
|
3206
4042
|
(message) => debugLogger6.warn(message)
|
|
3207
4043
|
);
|
|
3208
4044
|
}
|
|
4045
|
+
/**
|
|
4046
|
+
* Mirrors the core send path for ACP model sends.
|
|
4047
|
+
*
|
|
4048
|
+
* Attempts automatic chat compression first, checks the session token limit,
|
|
4049
|
+
* emits an ACP-visible notice when compression succeeds, and returns the ACP
|
|
4050
|
+
* stop reason when the provider send should be skipped because the request
|
|
4051
|
+
* was cancelled or the session token limit was exceeded.
|
|
4052
|
+
*/
|
|
3209
4053
|
async #sendMessageStreamWithAutoCompression(promptId, message, abortSignal, options = {}) {
|
|
3210
4054
|
const geminiClient = this.config.getGeminiClient();
|
|
3211
4055
|
let compressionDiagnostic = null;
|
|
3212
4056
|
let compressionInfo = null;
|
|
3213
|
-
|
|
4057
|
+
let compressionFailed = false;
|
|
4058
|
+
if (!options.skipCompression && !(options.getModelOverride?.() ?? options.modelOverride)) {
|
|
3214
4059
|
try {
|
|
3215
4060
|
const compressed = await geminiClient.tryCompressChat(
|
|
3216
4061
|
promptId,
|
|
@@ -3219,6 +4064,9 @@ ${this.pendingWorktreeNotice}
|
|
|
3219
4064
|
);
|
|
3220
4065
|
compressionInfo = compressed;
|
|
3221
4066
|
this.#recordCompressionTokenCount(compressed);
|
|
4067
|
+
compressionFailed = isCompressionFailureStatus(
|
|
4068
|
+
compressed.compressionStatus
|
|
4069
|
+
);
|
|
3222
4070
|
if (compressed.compressionStatus === 1 /* COMPRESSED */) {
|
|
3223
4071
|
this.loopTickResolver?.resetCache();
|
|
3224
4072
|
const reasonClause = compressed.triggerReason === "image_overflow" ? `accumulated enough tool screenshots to trigger compaction for ${this.config.getModel()}` : `approached the input token limit for ${this.config.getModel()}`;
|
|
@@ -3232,6 +4080,7 @@ ${this.pendingWorktreeNotice}
|
|
|
3232
4080
|
debugLogger6.warn(
|
|
3233
4081
|
`Auto-compression failed for prompt ${promptId}; proceeding without compression: ` + this.#formatError(compressionError)
|
|
3234
4082
|
);
|
|
4083
|
+
compressionFailed = true;
|
|
3235
4084
|
}
|
|
3236
4085
|
}
|
|
3237
4086
|
if (abortSignal.aborted) {
|
|
@@ -3267,8 +4116,21 @@ ${this.pendingWorktreeNotice}
|
|
|
3267
4116
|
);
|
|
3268
4117
|
return { responseStream: null, stopReason: "cancelled" };
|
|
3269
4118
|
}
|
|
4119
|
+
if (options.beforeSend) {
|
|
4120
|
+
const decision = await options.beforeSend({ compressionFailed });
|
|
4121
|
+
if (decision.kind === "stop") {
|
|
4122
|
+
return { responseStream: null, stopReason: decision.stopReason };
|
|
4123
|
+
}
|
|
4124
|
+
message = decision.message;
|
|
4125
|
+
}
|
|
4126
|
+
if (abortSignal.aborted) {
|
|
4127
|
+
debugLogger6.debug(
|
|
4128
|
+
`Send aborted after pre-send validation for prompt ${promptId}`
|
|
4129
|
+
);
|
|
4130
|
+
return { responseStream: null, stopReason: "cancelled" };
|
|
4131
|
+
}
|
|
3270
4132
|
const responseStream = await this.#getCurrentChat().sendMessageStream(
|
|
3271
|
-
this.config.getModel(),
|
|
4133
|
+
options.getModelOverride?.() ?? options.modelOverride ?? this.config.getModel(),
|
|
3272
4134
|
{
|
|
3273
4135
|
message,
|
|
3274
4136
|
config: {
|
|
@@ -3315,22 +4177,30 @@ ${this.pendingWorktreeNotice}
|
|
|
3315
4177
|
);
|
|
3316
4178
|
await this.messageRewriter?.waitForPendingRewrites();
|
|
3317
4179
|
}
|
|
3318
|
-
async #buildNextMessageAfterToolRun(toolRun, abortSignal) {
|
|
4180
|
+
async #buildNextMessageAfterToolRun(toolRun, abortSignal, onFullTurnModel) {
|
|
3319
4181
|
if (toolRun.loopDetected) {
|
|
3320
4182
|
debugLogger6.debug("Stopping ACP turn after daemon loop detection.");
|
|
3321
|
-
return null;
|
|
4183
|
+
return { message: null, hadMidTurnUserInput: false };
|
|
3322
4184
|
}
|
|
3323
4185
|
if (toolRun.repeatedDuplicateProviderToolCall) {
|
|
4186
|
+
this.todoStopGuard.suspend();
|
|
3324
4187
|
debugLogger6.debug(
|
|
3325
4188
|
"Stopping ACP turn after dropping repeated duplicate provider tool-call response."
|
|
3326
4189
|
);
|
|
3327
|
-
return null;
|
|
4190
|
+
return { message: null, hadMidTurnUserInput: false };
|
|
3328
4191
|
}
|
|
3329
|
-
const
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
4192
|
+
const drained = await this.#drainMidTurnInput(abortSignal, {
|
|
4193
|
+
onFullTurnModel
|
|
4194
|
+
});
|
|
4195
|
+
const hadMidTurnUserInput = drained.parts.length > 0;
|
|
4196
|
+
if (hadMidTurnUserInput) {
|
|
4197
|
+
this.todoStopGuard.acceptMidTurnUserInput();
|
|
4198
|
+
}
|
|
4199
|
+
const parts = [...toolRun.parts, ...drained.parts];
|
|
4200
|
+
return {
|
|
4201
|
+
message: { role: "user", parts },
|
|
4202
|
+
hadMidTurnUserInput
|
|
4203
|
+
};
|
|
3334
4204
|
}
|
|
3335
4205
|
#recordCompressionTokenCount(info) {
|
|
3336
4206
|
this.#syncPromptTokenCountWithCurrentChat();
|
|
@@ -3408,15 +4278,26 @@ ${this.pendingWorktreeNotice}
|
|
|
3408
4278
|
content: { type: "text", text }
|
|
3409
4279
|
});
|
|
3410
4280
|
}
|
|
3411
|
-
async #drainMidTurnUserMessages(abortSignal) {
|
|
4281
|
+
async #drainMidTurnUserMessages(abortSignal, onFullTurnModel) {
|
|
4282
|
+
return (await this.#drainMidTurnInput(abortSignal, { onFullTurnModel })).parts;
|
|
4283
|
+
}
|
|
4284
|
+
async #drainMidTurnInput(abortSignal, options = {}) {
|
|
3412
4285
|
const recovered = this.#takeRecoveredMidTurnMessages();
|
|
3413
4286
|
if (this.midTurnDrainUnavailable) {
|
|
3414
|
-
return
|
|
4287
|
+
return {
|
|
4288
|
+
parts: await this.#buildMidTurnParts(
|
|
4289
|
+
recovered,
|
|
4290
|
+
abortSignal,
|
|
4291
|
+
options.onFullTurnModel
|
|
4292
|
+
),
|
|
4293
|
+
hasQueuedPrompt: false
|
|
4294
|
+
};
|
|
3415
4295
|
}
|
|
3416
4296
|
let drainPromise;
|
|
3417
4297
|
try {
|
|
3418
4298
|
drainPromise = this.client.extMethod(MID_TURN_QUEUE_DRAIN_METHOD, {
|
|
3419
|
-
sessionId: this.sessionId
|
|
4299
|
+
sessionId: this.sessionId,
|
|
4300
|
+
...options.watchQueuedPromptForTodoStopGuard ? { todoStopGuardWatchQueuedPrompt: true } : {}
|
|
3420
4301
|
});
|
|
3421
4302
|
let timeoutHandle;
|
|
3422
4303
|
const timeoutPromise = new Promise((_, reject) => {
|
|
@@ -3432,10 +4313,14 @@ ${this.pendingWorktreeNotice}
|
|
|
3432
4313
|
clearTimeout(timeoutHandle);
|
|
3433
4314
|
}
|
|
3434
4315
|
this.midTurnDrainTimeoutStrikes = 0;
|
|
3435
|
-
return
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
4316
|
+
return {
|
|
4317
|
+
parts: await this.#buildMidTurnParts(
|
|
4318
|
+
[...recovered, ...parseMidTurnDrainResponse(response)],
|
|
4319
|
+
abortSignal,
|
|
4320
|
+
options.onFullTurnModel
|
|
4321
|
+
),
|
|
4322
|
+
hasQueuedPrompt: isRecord2(response) && response["hasQueuedPrompt"] === true
|
|
4323
|
+
};
|
|
3439
4324
|
} catch (error) {
|
|
3440
4325
|
const errorMessage = error instanceof Error ? error.message : error && typeof error === "object" && "message" in error ? String(error.message) : String(error);
|
|
3441
4326
|
const errorCode = error && typeof error === "object" && "code" in error ? error.code : void 0;
|
|
@@ -3451,7 +4336,14 @@ ${this.pendingWorktreeNotice}
|
|
|
3451
4336
|
debugLogger6.warn(
|
|
3452
4337
|
`Mid-turn queue drain ${isPermanentError ? "permanently " : ""}unavailable [session ${this.sessionId}]: ${errorMessage}`
|
|
3453
4338
|
);
|
|
3454
|
-
return
|
|
4339
|
+
return {
|
|
4340
|
+
parts: await this.#buildMidTurnParts(
|
|
4341
|
+
recovered,
|
|
4342
|
+
abortSignal,
|
|
4343
|
+
options.onFullTurnModel
|
|
4344
|
+
),
|
|
4345
|
+
hasQueuedPrompt: false
|
|
4346
|
+
};
|
|
3455
4347
|
}
|
|
3456
4348
|
}
|
|
3457
4349
|
/** Read and clear the buffer of messages recovered from a timed-out drain. */
|
|
@@ -3474,9 +4366,9 @@ ${this.pendingWorktreeNotice}
|
|
|
3474
4366
|
});
|
|
3475
4367
|
const expired = Symbol("mid-turn-recovery-expired");
|
|
3476
4368
|
let timer;
|
|
3477
|
-
const deadline = new Promise((
|
|
4369
|
+
const deadline = new Promise((resolve5) => {
|
|
3478
4370
|
timer = setTimeout(
|
|
3479
|
-
() =>
|
|
4371
|
+
() => resolve5(expired),
|
|
3480
4372
|
MID_TURN_QUEUE_RECOVERY_TIMEOUT_MS
|
|
3481
4373
|
);
|
|
3482
4374
|
timer.unref?.();
|
|
@@ -3509,7 +4401,7 @@ ${this.pendingWorktreeNotice}
|
|
|
3509
4401
|
* happens on injection (here), so a message recovered from an earlier
|
|
3510
4402
|
* timed-out drain is still recorded exactly once.
|
|
3511
4403
|
*/
|
|
3512
|
-
async #buildMidTurnParts(messages, abortSignal) {
|
|
4404
|
+
async #buildMidTurnParts(messages, abortSignal, onFullTurnModel) {
|
|
3513
4405
|
const parts = [];
|
|
3514
4406
|
for (const message of messages) {
|
|
3515
4407
|
const displayText = message.kind === "text" ? message.message : message.displayText;
|
|
@@ -3518,7 +4410,9 @@ ${this.pendingWorktreeNotice}
|
|
|
3518
4410
|
rawParts = message.kind === "text" ? [{ text: message.message }] : await withTimeoutSignal(
|
|
3519
4411
|
abortSignal,
|
|
3520
4412
|
MID_TURN_QUEUE_RESOLVE_TIMEOUT_MS,
|
|
3521
|
-
(signal) => this.#resolvePrompt(message.content, signal
|
|
4413
|
+
(signal) => this.#resolvePrompt(message.content, signal, {
|
|
4414
|
+
onFullTurnModel
|
|
4415
|
+
})
|
|
3522
4416
|
);
|
|
3523
4417
|
} catch (messageError) {
|
|
3524
4418
|
if (abortSignal.aborted) return parts;
|
|
@@ -3557,13 +4451,38 @@ ${this.pendingWorktreeNotice}
|
|
|
3557
4451
|
scheduler.start((job) => {
|
|
3558
4452
|
if (this.cronDisabledByTokenLimit) return;
|
|
3559
4453
|
if (job.missed && detectAutonomousSentinel(job.prompt)) return;
|
|
3560
|
-
this
|
|
4454
|
+
this.#enqueueCronPrompt({
|
|
3561
4455
|
prompt: job.prompt,
|
|
3562
|
-
source: job.cronExpr === "@wakeup" ? "loop" : "cron"
|
|
4456
|
+
source: job.cronExpr === "@wakeup" ? "loop" : "cron",
|
|
4457
|
+
...job.id ? { taskId: job.id } : {}
|
|
3563
4458
|
});
|
|
3564
4459
|
void this.#drainCronQueue();
|
|
3565
4460
|
});
|
|
3566
4461
|
}
|
|
4462
|
+
#enqueueCronPrompt(item) {
|
|
4463
|
+
if ((this.todoStopGuard.blocksUnrelatedAutomaticTurns || this.todoStopGuardQueuedPromptPriority) && !this.#cronContinuesTodoStopGuardWorkChain(item)) {
|
|
4464
|
+
if (item.taskId) {
|
|
4465
|
+
const duplicateIndex = this.cronQueue.findIndex(
|
|
4466
|
+
(queued) => queued.taskId === item.taskId && !this.#cronContinuesTodoStopGuardWorkChain(queued)
|
|
4467
|
+
);
|
|
4468
|
+
if (duplicateIndex >= 0) {
|
|
4469
|
+
this.cronQueue[duplicateIndex] = item;
|
|
4470
|
+
return;
|
|
4471
|
+
}
|
|
4472
|
+
}
|
|
4473
|
+
const unrelatedIndices = this.cronQueue.map(
|
|
4474
|
+
(queued, index) => this.#cronContinuesTodoStopGuardWorkChain(queued) ? -1 : index
|
|
4475
|
+
).filter((index) => index >= 0);
|
|
4476
|
+
if (unrelatedIndices.length >= MAX_DEFERRED_UNRELATED_CRON_QUEUE) {
|
|
4477
|
+
const evictedIndex = unrelatedIndices[0];
|
|
4478
|
+
const [evicted] = this.cronQueue.splice(evictedIndex, 1);
|
|
4479
|
+
debugLogger6.warn(
|
|
4480
|
+
`Cron queue overflow while automatic work is deferred: evicting task=${evicted?.taskId ?? "unknown"}`
|
|
4481
|
+
);
|
|
4482
|
+
}
|
|
4483
|
+
}
|
|
4484
|
+
this.cronQueue.push(item);
|
|
4485
|
+
}
|
|
3567
4486
|
/**
|
|
3568
4487
|
* Processes queued cron prompts one at a time. Uses `cronProcessing`
|
|
3569
4488
|
* as a mutex to prevent concurrent access to the chat.
|
|
@@ -3573,14 +4492,18 @@ ${this.pendingWorktreeNotice}
|
|
|
3573
4492
|
if (this.cronProcessing) return;
|
|
3574
4493
|
if (this.pendingPrompt) return;
|
|
3575
4494
|
if (this.notificationProcessing) return;
|
|
4495
|
+
if (this.#nextCronQueueIndex() < 0) return;
|
|
3576
4496
|
this.cronProcessing = true;
|
|
3577
4497
|
let resolveCompletion;
|
|
3578
|
-
this.cronCompletion = new Promise((
|
|
3579
|
-
resolveCompletion =
|
|
4498
|
+
this.cronCompletion = new Promise((resolve5) => {
|
|
4499
|
+
resolveCompletion = resolve5;
|
|
3580
4500
|
});
|
|
3581
4501
|
try {
|
|
3582
4502
|
while (this.cronQueue.length > 0) {
|
|
3583
|
-
const
|
|
4503
|
+
const nextIndex = this.#nextCronQueueIndex();
|
|
4504
|
+
if (nextIndex < 0) break;
|
|
4505
|
+
const [item] = this.cronQueue.splice(nextIndex, 1);
|
|
4506
|
+
if (!item) break;
|
|
3584
4507
|
await this.#executeCronPrompt(item);
|
|
3585
4508
|
}
|
|
3586
4509
|
} finally {
|
|
@@ -3596,6 +4519,14 @@ ${this.pendingWorktreeNotice}
|
|
|
3596
4519
|
}
|
|
3597
4520
|
}
|
|
3598
4521
|
}
|
|
4522
|
+
#nextCronQueueIndex() {
|
|
4523
|
+
if (this.cronQueue.length === 0) return -1;
|
|
4524
|
+
if (this.todoStopGuardQueuedPromptPriority) return -1;
|
|
4525
|
+
if (!this.todoStopGuard.blocksUnrelatedAutomaticTurns) return 0;
|
|
4526
|
+
return this.cronQueue.findIndex(
|
|
4527
|
+
(item) => this.#cronContinuesTodoStopGuardWorkChain(item)
|
|
4528
|
+
);
|
|
4529
|
+
}
|
|
3599
4530
|
#getLoopTickResolver() {
|
|
3600
4531
|
const root = this.config.getWorkingDir();
|
|
3601
4532
|
if (!this.loopTickResolver || this.loopTickResolverRoot !== root) {
|
|
@@ -3635,6 +4566,9 @@ ${this.pendingWorktreeNotice}
|
|
|
3635
4566
|
async () => {
|
|
3636
4567
|
const ac = new AbortController();
|
|
3637
4568
|
this.cronAbortController = ac;
|
|
4569
|
+
this.#prepareTodoStopGuardForAutomaticTurn(
|
|
4570
|
+
this.#cronContinuesTodoStopGuardWorkChain(item)
|
|
4571
|
+
);
|
|
3638
4572
|
const promptId = this.config.getSessionId() + "########cron" + Date.now();
|
|
3639
4573
|
let cronHadError = false;
|
|
3640
4574
|
await withInteractionSpan(
|
|
@@ -3708,7 +4642,10 @@ ${this.pendingWorktreeNotice}
|
|
|
3708
4642
|
const toolLoopState = createDaemonToolLoopState();
|
|
3709
4643
|
while (nextMessage !== null) {
|
|
3710
4644
|
turnCount++;
|
|
3711
|
-
if (ac.signal.aborted)
|
|
4645
|
+
if (ac.signal.aborted) {
|
|
4646
|
+
this.todoStopGuard.suspend();
|
|
4647
|
+
return;
|
|
4648
|
+
}
|
|
3712
4649
|
const functionCalls = [];
|
|
3713
4650
|
const preparationTracker = new ToolCallPreparationTracker(
|
|
3714
4651
|
this.toolCallEmitter
|
|
@@ -3721,6 +4658,7 @@ ${this.pendingWorktreeNotice}
|
|
|
3721
4658
|
ac.signal
|
|
3722
4659
|
);
|
|
3723
4660
|
if (!sendResult.responseStream) {
|
|
4661
|
+
this.todoStopGuard.suspend();
|
|
3724
4662
|
this.#preserveUnsentMessageHistory(
|
|
3725
4663
|
nextMessage,
|
|
3726
4664
|
sendResult.stopReason === "cancelled"
|
|
@@ -3741,7 +4679,10 @@ ${this.pendingWorktreeNotice}
|
|
|
3741
4679
|
let streamFailed = false;
|
|
3742
4680
|
try {
|
|
3743
4681
|
for await (const resp of responseStream) {
|
|
3744
|
-
if (ac.signal.aborted)
|
|
4682
|
+
if (ac.signal.aborted) {
|
|
4683
|
+
this.todoStopGuard.suspend();
|
|
4684
|
+
return;
|
|
4685
|
+
}
|
|
3745
4686
|
if (resp.type === "chunk" /* CHUNK */ && resp.value.candidates && resp.value.candidates.length > 0) {
|
|
3746
4687
|
const candidate = resp.value.candidates[0];
|
|
3747
4688
|
for (const part of candidate.content?.parts ?? []) {
|
|
@@ -3809,21 +4750,40 @@ ${this.pendingWorktreeNotice}
|
|
|
3809
4750
|
toolLoopState
|
|
3810
4751
|
);
|
|
3811
4752
|
if (toolRun.stopAfterPermissionCancel) {
|
|
4753
|
+
this.todoStopGuard.suspend();
|
|
3812
4754
|
await this.#preserveStoppedToolRun(toolRun, ac.signal);
|
|
3813
4755
|
return;
|
|
3814
4756
|
}
|
|
3815
|
-
|
|
4757
|
+
const nextAfterTools = await this.#buildNextMessageAfterToolRun(
|
|
3816
4758
|
toolRun,
|
|
3817
4759
|
ac.signal
|
|
3818
4760
|
);
|
|
4761
|
+
nextMessage = nextAfterTools.message;
|
|
3819
4762
|
if (toolRun.loopDetected) {
|
|
4763
|
+
this.todoStopGuard.suspend();
|
|
3820
4764
|
await this.#preserveStoppedToolRun(toolRun, ac.signal);
|
|
3821
4765
|
return;
|
|
3822
4766
|
}
|
|
3823
4767
|
}
|
|
3824
4768
|
}
|
|
4769
|
+
if (this.todoStopGuard.needsStopInspection) {
|
|
4770
|
+
const guardStop = await this.#handleStopHookLoop(
|
|
4771
|
+
ac,
|
|
4772
|
+
promptId,
|
|
4773
|
+
false,
|
|
4774
|
+
void 0,
|
|
4775
|
+
false
|
|
4776
|
+
);
|
|
4777
|
+
if (guardStop.stopReason === "max_tokens") {
|
|
4778
|
+
this.#stopCronAfterTokenLimit();
|
|
4779
|
+
}
|
|
4780
|
+
}
|
|
3825
4781
|
} catch (error) {
|
|
3826
|
-
if (ac.signal.aborted)
|
|
4782
|
+
if (ac.signal.aborted) {
|
|
4783
|
+
this.todoStopGuard.suspend();
|
|
4784
|
+
return;
|
|
4785
|
+
}
|
|
4786
|
+
this.todoStopGuard.pauseForTrustedRetry();
|
|
3827
4787
|
cronHadError = true;
|
|
3828
4788
|
debugLogger6.error("Error processing cron prompt:", error);
|
|
3829
4789
|
const msg = error instanceof Error ? error.message : String(error);
|
|
@@ -3849,6 +4809,7 @@ ${this.pendingWorktreeNotice}
|
|
|
3849
4809
|
);
|
|
3850
4810
|
}
|
|
3851
4811
|
#stopCronAfterTokenLimit() {
|
|
4812
|
+
this.todoStopGuard.suspend();
|
|
3852
4813
|
this.cronDisabledByTokenLimit = true;
|
|
3853
4814
|
this.cronQueue = [];
|
|
3854
4815
|
if (!this.config.isCronEnabled()) return;
|
|
@@ -3920,9 +4881,28 @@ ${this.pendingWorktreeNotice}
|
|
|
3920
4881
|
}
|
|
3921
4882
|
#enqueueBackgroundNotification(item) {
|
|
3922
4883
|
while (this.notificationQueue.length >= MAX_NOTIFICATION_QUEUE) {
|
|
3923
|
-
|
|
4884
|
+
let evictedIndex = 0;
|
|
4885
|
+
if (this.todoStopGuard.blocksUnrelatedAutomaticTurns || this.todoStopGuardQueuedPromptPriority) {
|
|
4886
|
+
const incomingIsRelated = this.#notificationContinuesTodoStopGuardWorkChain(item);
|
|
4887
|
+
evictedIndex = this.notificationQueue.findIndex(
|
|
4888
|
+
(queued) => !this.#notificationContinuesTodoStopGuardWorkChain(queued)
|
|
4889
|
+
);
|
|
4890
|
+
if (evictedIndex < 0 && !incomingIsRelated) {
|
|
4891
|
+
debugLogger6.warn(
|
|
4892
|
+
`Notification queue overflow: dropping unrelated task=${item.taskId} kind=${item.kind} while automatic work is deferred`
|
|
4893
|
+
);
|
|
4894
|
+
return;
|
|
4895
|
+
}
|
|
4896
|
+
if (evictedIndex < 0) {
|
|
4897
|
+
debugLogger6.warn(
|
|
4898
|
+
`Notification queue overflow: dropping related task=${item.taskId} kind=${item.kind} because all queued items are related`
|
|
4899
|
+
);
|
|
4900
|
+
return;
|
|
4901
|
+
}
|
|
4902
|
+
}
|
|
4903
|
+
const [evicted] = this.notificationQueue.splice(evictedIndex, 1);
|
|
3924
4904
|
debugLogger6.warn(
|
|
3925
|
-
`Notification queue overflow: evicting task=${evicted
|
|
4905
|
+
`Notification queue overflow: evicting task=${evicted?.taskId ?? "unknown"} kind=${evicted?.kind ?? "unknown"}`
|
|
3926
4906
|
);
|
|
3927
4907
|
}
|
|
3928
4908
|
this.notificationQueue.push(item);
|
|
@@ -3935,17 +4915,21 @@ ${this.pendingWorktreeNotice}
|
|
|
3935
4915
|
return;
|
|
3936
4916
|
}
|
|
3937
4917
|
if (this.notificationQueue.length === 0) return;
|
|
4918
|
+
if (this.#nextNotificationQueueIndex() < 0) return;
|
|
3938
4919
|
this.notificationProcessing = true;
|
|
3939
4920
|
let resolveCompletion;
|
|
3940
|
-
this.notificationCompletion = new Promise((
|
|
3941
|
-
resolveCompletion =
|
|
4921
|
+
this.notificationCompletion = new Promise((resolve5) => {
|
|
4922
|
+
resolveCompletion = resolve5;
|
|
3942
4923
|
});
|
|
3943
4924
|
try {
|
|
3944
4925
|
while (this.notificationQueue.length > 0) {
|
|
3945
4926
|
if (this.pendingPrompt || this.cronProcessing || this.cronAbortController) {
|
|
3946
4927
|
break;
|
|
3947
4928
|
}
|
|
3948
|
-
const
|
|
4929
|
+
const nextIndex = this.#nextNotificationQueueIndex();
|
|
4930
|
+
if (nextIndex < 0) break;
|
|
4931
|
+
const [item] = this.notificationQueue.splice(nextIndex, 1);
|
|
4932
|
+
if (!item) break;
|
|
3949
4933
|
await sessionIdContext.run(
|
|
3950
4934
|
this.config.getSessionId(),
|
|
3951
4935
|
() => this.#executeBackgroundNotificationPromptInner(item)
|
|
@@ -3961,6 +4945,14 @@ ${this.pendingWorktreeNotice}
|
|
|
3961
4945
|
}
|
|
3962
4946
|
}
|
|
3963
4947
|
}
|
|
4948
|
+
#nextNotificationQueueIndex() {
|
|
4949
|
+
if (this.notificationQueue.length === 0) return -1;
|
|
4950
|
+
if (this.todoStopGuardQueuedPromptPriority) return -1;
|
|
4951
|
+
if (!this.todoStopGuard.blocksUnrelatedAutomaticTurns) return 0;
|
|
4952
|
+
return this.notificationQueue.findIndex(
|
|
4953
|
+
(item) => this.#notificationContinuesTodoStopGuardWorkChain(item)
|
|
4954
|
+
);
|
|
4955
|
+
}
|
|
3964
4956
|
async #executeBackgroundNotificationPromptInner(item) {
|
|
3965
4957
|
return Storage.runWithRuntimeBaseDir(
|
|
3966
4958
|
this.runtimeBaseDir,
|
|
@@ -3968,6 +4960,9 @@ ${this.pendingWorktreeNotice}
|
|
|
3968
4960
|
async () => {
|
|
3969
4961
|
const ac = new AbortController();
|
|
3970
4962
|
this.notificationAbortController = ac;
|
|
4963
|
+
this.#prepareTodoStopGuardForAutomaticTurn(
|
|
4964
|
+
this.#notificationContinuesTodoStopGuardWorkChain(item)
|
|
4965
|
+
);
|
|
3971
4966
|
const promptId = this.config.getSessionId() + "########notification" + Date.now();
|
|
3972
4967
|
try {
|
|
3973
4968
|
await this.#emitBackgroundNotificationDisplay(item);
|
|
@@ -3981,6 +4976,7 @@ ${this.pendingWorktreeNotice}
|
|
|
3981
4976
|
const toolLoopState = createDaemonToolLoopState();
|
|
3982
4977
|
while (nextMessage !== null) {
|
|
3983
4978
|
if (ac.signal.aborted) {
|
|
4979
|
+
this.todoStopGuard.suspend();
|
|
3984
4980
|
await this.#emitBackgroundNotificationEndTurn("cancelled");
|
|
3985
4981
|
return;
|
|
3986
4982
|
}
|
|
@@ -3997,6 +4993,7 @@ ${this.pendingWorktreeNotice}
|
|
|
3997
4993
|
ac.signal
|
|
3998
4994
|
);
|
|
3999
4995
|
if (!sendResult.responseStream) {
|
|
4996
|
+
this.todoStopGuard.suspend();
|
|
4000
4997
|
this.#preserveUnsentMessageHistory(
|
|
4001
4998
|
nextMessage,
|
|
4002
4999
|
sendResult.stopReason === "cancelled"
|
|
@@ -4015,6 +5012,7 @@ ${this.pendingWorktreeNotice}
|
|
|
4015
5012
|
try {
|
|
4016
5013
|
for await (const resp of responseStream) {
|
|
4017
5014
|
if (ac.signal.aborted) {
|
|
5015
|
+
this.todoStopGuard.suspend();
|
|
4018
5016
|
await this.#emitBackgroundNotificationEndTurn("cancelled");
|
|
4019
5017
|
return;
|
|
4020
5018
|
}
|
|
@@ -4094,15 +5092,18 @@ ${this.pendingWorktreeNotice}
|
|
|
4094
5092
|
toolLoopState
|
|
4095
5093
|
);
|
|
4096
5094
|
if (toolRun.stopAfterPermissionCancel) {
|
|
5095
|
+
this.todoStopGuard.suspend();
|
|
4097
5096
|
await this.#preserveStoppedToolRun(toolRun, ac.signal);
|
|
4098
5097
|
await this.#emitBackgroundNotificationEndTurn("end_turn");
|
|
4099
5098
|
return;
|
|
4100
5099
|
}
|
|
4101
|
-
|
|
5100
|
+
const nextAfterTools = await this.#buildNextMessageAfterToolRun(
|
|
4102
5101
|
toolRun,
|
|
4103
5102
|
ac.signal
|
|
4104
5103
|
);
|
|
5104
|
+
nextMessage = nextAfterTools.message;
|
|
4105
5105
|
if (toolRun.loopDetected) {
|
|
5106
|
+
this.todoStopGuard.suspend();
|
|
4106
5107
|
await this.#preserveStoppedToolRun(toolRun, ac.signal);
|
|
4107
5108
|
await this.#emitBackgroundNotificationEndTurn("end_turn");
|
|
4108
5109
|
return;
|
|
@@ -4112,12 +5113,24 @@ ${this.pendingWorktreeNotice}
|
|
|
4112
5113
|
if (this.messageRewriter) {
|
|
4113
5114
|
await this.messageRewriter.waitForPendingRewrites();
|
|
4114
5115
|
}
|
|
4115
|
-
|
|
5116
|
+
let stopReason = "end_turn";
|
|
5117
|
+
if (this.todoStopGuard.needsStopInspection) {
|
|
5118
|
+
stopReason = (await this.#handleStopHookLoop(
|
|
5119
|
+
ac,
|
|
5120
|
+
promptId,
|
|
5121
|
+
false,
|
|
5122
|
+
void 0,
|
|
5123
|
+
false
|
|
5124
|
+
)).stopReason;
|
|
5125
|
+
}
|
|
5126
|
+
await this.#emitBackgroundNotificationEndTurn(stopReason);
|
|
4116
5127
|
} catch (error) {
|
|
4117
5128
|
if (ac.signal.aborted) {
|
|
5129
|
+
this.todoStopGuard.suspend();
|
|
4118
5130
|
await this.#emitBackgroundNotificationEndTurn("cancelled");
|
|
4119
5131
|
return;
|
|
4120
5132
|
}
|
|
5133
|
+
this.todoStopGuard.pauseForTrustedRetry();
|
|
4121
5134
|
debugLogger6.error("Error processing background notification:", error);
|
|
4122
5135
|
const msg = error instanceof Error ? error.message : String(error);
|
|
4123
5136
|
try {
|
|
@@ -4267,6 +5280,9 @@ ${this.pendingWorktreeNotice}
|
|
|
4267
5280
|
);
|
|
4268
5281
|
}
|
|
4269
5282
|
this.config.setApprovalMode(approvalMode);
|
|
5283
|
+
if (approvalMode === "plan" /* PLAN */) {
|
|
5284
|
+
this.clearTodoStopGuardTrust();
|
|
5285
|
+
}
|
|
4270
5286
|
void this.client.extNotification("qwen/notify/session/mode-update", {
|
|
4271
5287
|
v: 1,
|
|
4272
5288
|
sessionId: this.sessionId,
|
|
@@ -4284,7 +5300,17 @@ ${this.pendingWorktreeNotice}
|
|
|
4284
5300
|
if (!rawModelId) {
|
|
4285
5301
|
throw RequestError.invalidParams(void 0, "modelId cannot be empty");
|
|
4286
5302
|
}
|
|
4287
|
-
const
|
|
5303
|
+
const resolvedRoute = resolveAcpModelOption(
|
|
5304
|
+
rawModelId,
|
|
5305
|
+
this.config.getAllConfiguredModels()
|
|
5306
|
+
);
|
|
5307
|
+
if (!resolvedRoute && rawModelId.startsWith(ACP_ROUTE_ID_PREFIX)) {
|
|
5308
|
+
throw RequestError.invalidParams(
|
|
5309
|
+
void 0,
|
|
5310
|
+
`Unknown or stale model route: "${rawModelId}"`
|
|
5311
|
+
);
|
|
5312
|
+
}
|
|
5313
|
+
const parsed = resolvedRoute ?? parseAcpModelOption(rawModelId);
|
|
4288
5314
|
const previousAuthType = this.config.getAuthType?.();
|
|
4289
5315
|
const selectedAuthType = parsed.authType ?? previousAuthType;
|
|
4290
5316
|
if (!selectedAuthType) {
|
|
@@ -4293,29 +5319,49 @@ ${this.pendingWorktreeNotice}
|
|
|
4293
5319
|
`authType cannot be determined for modelId "${parsed.modelId}"`
|
|
4294
5320
|
);
|
|
4295
5321
|
}
|
|
5322
|
+
const requireCachedCredentials = selectedAuthType !== previousAuthType && selectedAuthType === "qwen-oauth" /* QWEN_OAUTH */;
|
|
5323
|
+
const switchOptions = resolvedRoute?.baseUrl !== void 0 || requireCachedCredentials ? {
|
|
5324
|
+
...resolvedRoute?.baseUrl !== void 0 ? { baseUrl: resolvedRoute.baseUrl } : {},
|
|
5325
|
+
...requireCachedCredentials ? { requireCachedCredentials: true } : {}
|
|
5326
|
+
} : void 0;
|
|
4296
5327
|
await this.config.switchModel(
|
|
4297
5328
|
selectedAuthType,
|
|
4298
5329
|
parsed.modelId,
|
|
4299
|
-
|
|
5330
|
+
switchOptions
|
|
4300
5331
|
);
|
|
4301
5332
|
const after = this.config.getContentGeneratorConfig?.();
|
|
4302
5333
|
const effectiveAuthType = after?.authType ?? selectedAuthType;
|
|
4303
5334
|
const effectiveModelId = after?.model ?? parsed.modelId;
|
|
5335
|
+
const activeRuntimeSnapshot = this.config.getActiveRuntimeModelSnapshot?.();
|
|
5336
|
+
const currentAcpModelId = getCurrentAcpModelId(
|
|
5337
|
+
buildAcpModelOptions(this.config.getAllConfiguredModels()),
|
|
5338
|
+
activeRuntimeSnapshot?.id ?? effectiveModelId,
|
|
5339
|
+
activeRuntimeSnapshot?.authType ?? effectiveAuthType,
|
|
5340
|
+
activeRuntimeSnapshot ? void 0 : resolvedRoute ? resolvedRoute.registryBaseUrl : this.config.getCurrentModelRegistryBaseUrl?.()
|
|
5341
|
+
);
|
|
4304
5342
|
void this.client.extNotification("qwen/notify/session/model-update", {
|
|
4305
5343
|
v: 1,
|
|
4306
5344
|
sessionId: this.sessionId,
|
|
4307
|
-
currentModelId:
|
|
5345
|
+
currentModelId: currentAcpModelId
|
|
4308
5346
|
}).catch((error) => {
|
|
4309
5347
|
debugLogger6.debug("model-update extNotification failed", error);
|
|
4310
5348
|
});
|
|
4311
5349
|
if (options.persistDefault ?? true) {
|
|
4312
5350
|
const persistScope = getPersistScopeForModelSelection(this.settings);
|
|
4313
|
-
this.settings.setValue(
|
|
4314
|
-
|
|
5351
|
+
this.settings.setValue(
|
|
5352
|
+
persistScope,
|
|
5353
|
+
"model.name",
|
|
5354
|
+
resolvedRoute?.isRuntime ? resolvedRoute.modelId : effectiveModelId
|
|
5355
|
+
);
|
|
5356
|
+
this.settings.setValue(
|
|
5357
|
+
persistScope,
|
|
5358
|
+
"model.baseUrl",
|
|
5359
|
+
resolvedRoute && !resolvedRoute.isRuntime ? resolvedRoute.baseUrl ?? "" : ""
|
|
5360
|
+
);
|
|
4315
5361
|
this.settings.setValue(
|
|
4316
5362
|
persistScope,
|
|
4317
5363
|
"security.auth.selectedType",
|
|
4318
|
-
|
|
5364
|
+
effectiveAuthType
|
|
4319
5365
|
);
|
|
4320
5366
|
}
|
|
4321
5367
|
return {
|
|
@@ -4325,7 +5371,7 @@ ${this.pendingWorktreeNotice}
|
|
|
4325
5371
|
modelId: effectiveModelId,
|
|
4326
5372
|
baseUrl: after?.baseUrl ?? "(default)",
|
|
4327
5373
|
apiKey: maskApiKeyForDisplay(after?.apiKey),
|
|
4328
|
-
isRuntime: rawModelId.startsWith("$runtime|")
|
|
5374
|
+
isRuntime: resolvedRoute?.isRuntime ?? rawModelId.startsWith("$runtime|")
|
|
4329
5375
|
}
|
|
4330
5376
|
}
|
|
4331
5377
|
};
|
|
@@ -4334,33 +5380,29 @@ ${this.pendingWorktreeNotice}
|
|
|
4334
5380
|
* Sends a current_mode_update notification to the client.
|
|
4335
5381
|
* Called after the agent switches modes (e.g., from exit_plan_mode tool).
|
|
4336
5382
|
*/
|
|
4337
|
-
async sendCurrentModeUpdateNotification(
|
|
4338
|
-
|
|
4339
|
-
switch (outcome) {
|
|
4340
|
-
case "proceed_always" /* ProceedAlways */:
|
|
4341
|
-
newModeId = "auto-edit";
|
|
4342
|
-
break;
|
|
4343
|
-
case "restore_previous" /* RestorePrevious */:
|
|
4344
|
-
newModeId = this.config.getApprovalMode();
|
|
4345
|
-
break;
|
|
4346
|
-
case "proceed_once" /* ProceedOnce */:
|
|
4347
|
-
default:
|
|
4348
|
-
newModeId = "default";
|
|
4349
|
-
break;
|
|
4350
|
-
}
|
|
5383
|
+
async sendCurrentModeUpdateNotification() {
|
|
5384
|
+
const newModeId = this.config.getApprovalMode();
|
|
4351
5385
|
const update = {
|
|
4352
5386
|
sessionUpdate: "current_mode_update",
|
|
4353
5387
|
currentModeId: newModeId
|
|
4354
5388
|
};
|
|
4355
|
-
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
}
|
|
5389
|
+
let legacyFrameSent = false;
|
|
5390
|
+
try {
|
|
5391
|
+
await this.sendUpdate(update);
|
|
5392
|
+
legacyFrameSent = true;
|
|
5393
|
+
} catch (error) {
|
|
5394
|
+
debugLogger6.debug("current_mode_update notification failed", error);
|
|
5395
|
+
}
|
|
5396
|
+
try {
|
|
5397
|
+
await this.client.extNotification("qwen/notify/session/mode-update", {
|
|
5398
|
+
v: 1,
|
|
5399
|
+
sessionId: this.sessionId,
|
|
5400
|
+
currentModeId: newModeId,
|
|
5401
|
+
legacyFrameSent
|
|
5402
|
+
});
|
|
5403
|
+
} catch (error) {
|
|
4362
5404
|
debugLogger6.debug("mode-update extNotification failed", error);
|
|
4363
|
-
}
|
|
5405
|
+
}
|
|
4364
5406
|
}
|
|
4365
5407
|
/**
|
|
4366
5408
|
* Execute a batch of model-returned tool calls, running Agent calls
|
|
@@ -4914,6 +5956,7 @@ ${this.pendingWorktreeNotice}
|
|
|
4914
5956
|
);
|
|
4915
5957
|
}
|
|
4916
5958
|
const isTodoWriteTool = tool.name === ToolNames.TODO_WRITE;
|
|
5959
|
+
const isTrustedTodoWriteTool = isTodoWriteTool && tool.kind === "think" /* Think */ && tool.constructor.name === "TodoWriteTool";
|
|
4917
5960
|
const isAgentTool = tool.name === ToolNames.AGENT;
|
|
4918
5961
|
const isExitPlanModeTool = tool.name === ToolNames.EXIT_PLAN_MODE;
|
|
4919
5962
|
const isEnterPlanModeTool = tool.name === ToolNames.ENTER_PLAN_MODE;
|
|
@@ -4968,7 +6011,13 @@ ${this.pendingWorktreeNotice}
|
|
|
4968
6011
|
toolName,
|
|
4969
6012
|
toolParams
|
|
4970
6013
|
);
|
|
4971
|
-
const {
|
|
6014
|
+
const {
|
|
6015
|
+
finalPermission,
|
|
6016
|
+
pmForcedAsk,
|
|
6017
|
+
pmCtx,
|
|
6018
|
+
denyMessage,
|
|
6019
|
+
requiresUserInteraction
|
|
6020
|
+
} = flowResult;
|
|
4972
6021
|
const isPlanMode = approvalMode === "plan" /* PLAN */;
|
|
4973
6022
|
if (finalPermission === "deny") {
|
|
4974
6023
|
return earlyErrorResponse(
|
|
@@ -4993,7 +6042,7 @@ ${this.pendingWorktreeNotice}
|
|
|
4993
6042
|
);
|
|
4994
6043
|
}
|
|
4995
6044
|
let wasAutoModeDenialFallback = false;
|
|
4996
|
-
if (!autoModeAllowed && shouldRunAutoModeForCall(approvalMode, toolName)) {
|
|
6045
|
+
if (!autoModeAllowed && !requiresUserInteraction && shouldRunAutoModeForCall(approvalMode, toolName)) {
|
|
4997
6046
|
const denialState = this.config.getAutoModeDenialState();
|
|
4998
6047
|
const fallback = shouldFallback(denialState);
|
|
4999
6048
|
const messages = this.config.getGeminiClient?.()?.getHistoryTail(MAX_TRANSCRIPT_MESSAGES, false) ?? [];
|
|
@@ -5066,7 +6115,12 @@ ${this.pendingWorktreeNotice}
|
|
|
5066
6115
|
this.config.setAutoModeDenialState(after);
|
|
5067
6116
|
}
|
|
5068
6117
|
}, "recordAutoModeFallbackResolution");
|
|
5069
|
-
if (!autoModeAllowed && needsConfirmation(
|
|
6118
|
+
if (!autoModeAllowed && needsConfirmation(
|
|
6119
|
+
confirmationPermission,
|
|
6120
|
+
approvalMode,
|
|
6121
|
+
toolName,
|
|
6122
|
+
requiresUserInteraction
|
|
6123
|
+
)) {
|
|
5070
6124
|
confirmationDetails = await invocation.getConfirmationDetails(abortSignal);
|
|
5071
6125
|
injectPermissionRulesIfMissing(confirmationDetails, pmCtx);
|
|
5072
6126
|
if (isPlanModeBlocked(
|
|
@@ -5093,7 +6147,7 @@ ${this.pendingWorktreeNotice}
|
|
|
5093
6147
|
args,
|
|
5094
6148
|
String(approvalMode)
|
|
5095
6149
|
);
|
|
5096
|
-
if (hookResult.hasDecision) {
|
|
6150
|
+
if (hookResult.hasDecision && (!hookResult.shouldAllow || !requiresUserInteraction)) {
|
|
5097
6151
|
hookHandled = true;
|
|
5098
6152
|
if (hookResult.shouldAllow) {
|
|
5099
6153
|
if (hookResult.updatedInput) {
|
|
@@ -5116,7 +6170,7 @@ ${this.pendingWorktreeNotice}
|
|
|
5116
6170
|
}
|
|
5117
6171
|
}
|
|
5118
6172
|
}
|
|
5119
|
-
if (approvalMode === "auto-edit" /* AUTO_EDIT */ && (confirmationDetails.type === "edit" || confirmationDetails.type === "info")) {
|
|
6173
|
+
if (!requiresUserInteraction && approvalMode === "auto-edit" /* AUTO_EDIT */ && (confirmationDetails.type === "edit" || confirmationDetails.type === "info")) {
|
|
5120
6174
|
} else if (!hookHandled) {
|
|
5121
6175
|
didRequestPermission = true;
|
|
5122
6176
|
const content = buildPermissionRequestContent(confirmationDetails);
|
|
@@ -5184,12 +6238,11 @@ ${this.pendingWorktreeNotice}
|
|
|
5184
6238
|
);
|
|
5185
6239
|
}
|
|
5186
6240
|
onStopAfterPermissionCancel?.();
|
|
6241
|
+
const permissionFailureMessage = isExitPlanModeTool ? "The host could not present plan-exit approval. Plan mode remains active; use the host mode selector or /plan exit to leave plan mode." : `Permission request failed for "${toolName}": ${this.#formatError(
|
|
6242
|
+
error
|
|
6243
|
+
)}`;
|
|
5187
6244
|
return earlyErrorResponse(
|
|
5188
|
-
new Error(
|
|
5189
|
-
`Permission request failed for "${toolName}": ${this.#formatError(
|
|
5190
|
-
error
|
|
5191
|
-
)}`
|
|
5192
|
-
),
|
|
6245
|
+
new Error(permissionFailureMessage),
|
|
5193
6246
|
toolName,
|
|
5194
6247
|
{ stopAfterPermissionCancel: true }
|
|
5195
6248
|
);
|
|
@@ -5218,11 +6271,8 @@ ${this.pendingWorktreeNotice}
|
|
|
5218
6271
|
{ answers: output.answers }
|
|
5219
6272
|
);
|
|
5220
6273
|
}
|
|
5221
|
-
if (isExitPlanModeTool && outcome !== "cancel" /* Cancel */) {
|
|
5222
|
-
await this.sendCurrentModeUpdateNotification(outcome);
|
|
5223
|
-
}
|
|
5224
6274
|
if (confirmationDetails.type === "edit" && outcome === "proceed_always" /* ProceedAlways */) {
|
|
5225
|
-
await this.sendCurrentModeUpdateNotification(
|
|
6275
|
+
await this.sendCurrentModeUpdateNotification();
|
|
5226
6276
|
}
|
|
5227
6277
|
switch (outcome) {
|
|
5228
6278
|
case "cancel" /* Cancel */:
|
|
@@ -5342,11 +6392,11 @@ ${this.pendingWorktreeNotice}
|
|
|
5342
6392
|
throw execError;
|
|
5343
6393
|
}
|
|
5344
6394
|
cleanupAgentToolResources();
|
|
5345
|
-
if ((isEnterPlanModeTool || isExitPlanModeTool) && !
|
|
5346
|
-
await this.
|
|
5347
|
-
|
|
5348
|
-
|
|
5349
|
-
}
|
|
6395
|
+
if ((isEnterPlanModeTool || isExitPlanModeTool) && !toolResult.error && this.config.getApprovalMode() !== approvalMode) {
|
|
6396
|
+
await this.sendCurrentModeUpdateNotification();
|
|
6397
|
+
if (this.config.getApprovalMode() === "plan" /* PLAN */) {
|
|
6398
|
+
this.#clearTodoStopGuardTrustAndDrainAutomaticQueues();
|
|
6399
|
+
}
|
|
5350
6400
|
}
|
|
5351
6401
|
const responseParts = toolResult.error ? convertToFunctionErrorResponse(
|
|
5352
6402
|
toolName,
|
|
@@ -5361,6 +6411,13 @@ ${this.pendingWorktreeNotice}
|
|
|
5361
6411
|
const status = aborted ? "cancelled" : toolResult.error ? "error" : "success";
|
|
5362
6412
|
const succeeded = status === "success";
|
|
5363
6413
|
const responseError = toolResult.error ? new Error(toolResult.error.message) : aborted ? new Error("Tool execution was cancelled") : void 0;
|
|
6414
|
+
if (isTrustedTodoWriteTool && !toolResult.error) {
|
|
6415
|
+
this.todoStopGuard.observeTodoWrite(
|
|
6416
|
+
toolResult.returnDisplay,
|
|
6417
|
+
this.config.getApprovalMode() !== "plan" /* PLAN */
|
|
6418
|
+
);
|
|
6419
|
+
if (aborted) this.todoStopGuard.suspend();
|
|
6420
|
+
}
|
|
5364
6421
|
if (hooksEnabledForTool && messageBusForTool && !toolResult.error && !aborted && !nestedPermissionCancelled) {
|
|
5365
6422
|
const toolResponse = {
|
|
5366
6423
|
llmContent: toolResult.llmContent,
|
|
@@ -5381,6 +6438,7 @@ ${this.pendingWorktreeNotice}
|
|
|
5381
6438
|
debugLogger6.info(
|
|
5382
6439
|
`PostToolUse hook requested stop for ${toolName}: ${stopMessage}`
|
|
5383
6440
|
);
|
|
6441
|
+
this.todoStopGuard.suspend();
|
|
5384
6442
|
return earlyErrorResponse(new Error(stopMessage), toolName);
|
|
5385
6443
|
}
|
|
5386
6444
|
if (postHookResult.additionalContext) {
|
|
@@ -5566,7 +6624,7 @@ ${this.pendingWorktreeNotice}
|
|
|
5566
6624
|
}
|
|
5567
6625
|
}
|
|
5568
6626
|
if (hasActiveGoalStatus) {
|
|
5569
|
-
this
|
|
6627
|
+
this.installGoalTerminalObserver();
|
|
5570
6628
|
}
|
|
5571
6629
|
}
|
|
5572
6630
|
/**
|
|
@@ -5585,11 +6643,15 @@ ${this.pendingWorktreeNotice}
|
|
|
5585
6643
|
* @param originalPrompt The original prompt blocks
|
|
5586
6644
|
* @returns Parts to use for the prompt, or null if command was handled without needing model interaction
|
|
5587
6645
|
*/
|
|
5588
|
-
async #processSlashCommandResult(result, originalPrompt) {
|
|
6646
|
+
async #processSlashCommandResult(result, originalPrompt, abortSignal, onFullTurnModel) {
|
|
5589
6647
|
this.#emitGoalStatusItems(result);
|
|
5590
6648
|
switch (result.type) {
|
|
5591
6649
|
case "submit_prompt":
|
|
5592
|
-
return
|
|
6650
|
+
return this.#applyBridgeConversionsIfNeeded(
|
|
6651
|
+
normalizePartList(result.content),
|
|
6652
|
+
abortSignal,
|
|
6653
|
+
onFullTurnModel
|
|
6654
|
+
);
|
|
5593
6655
|
case "message": {
|
|
5594
6656
|
if (result.messageType === "error") {
|
|
5595
6657
|
throw new Error(result.content || "Slash command failed.");
|
|
@@ -5632,11 +6694,10 @@ ${this.pendingWorktreeNotice}
|
|
|
5632
6694
|
throw new Error(unsupportedError);
|
|
5633
6695
|
}
|
|
5634
6696
|
case "no_command":
|
|
5635
|
-
return this.#resolvePrompt(
|
|
5636
|
-
|
|
5637
|
-
|
|
5638
|
-
|
|
5639
|
-
);
|
|
6697
|
+
return this.#resolvePrompt(originalPrompt, abortSignal, {
|
|
6698
|
+
promptLast: true,
|
|
6699
|
+
onFullTurnModel
|
|
6700
|
+
});
|
|
5640
6701
|
default: {
|
|
5641
6702
|
const _exhaustive = result;
|
|
5642
6703
|
const unknownError = `Unknown slash command result type: ${_exhaustive.type}`;
|
|
@@ -5649,6 +6710,7 @@ ${this.pendingWorktreeNotice}
|
|
|
5649
6710
|
const embeddedContext = [];
|
|
5650
6711
|
const extensionMentions = /* @__PURE__ */ new Map();
|
|
5651
6712
|
const mcpServerMentions = /* @__PURE__ */ new Map();
|
|
6713
|
+
const textPathSpecsToRead = /* @__PURE__ */ new Set();
|
|
5652
6714
|
const preserveUnsupportedImageForBridge = shouldRunVisionBridge(
|
|
5653
6715
|
this.config
|
|
5654
6716
|
);
|
|
@@ -5657,6 +6719,16 @@ ${this.pendingWorktreeNotice}
|
|
|
5657
6719
|
case "text":
|
|
5658
6720
|
collectExtensionMentionRefs(part.text, extensionMentions);
|
|
5659
6721
|
collectMcpServerMentionRefs(part.text, mcpServerMentions);
|
|
6722
|
+
for (const pathSpec of extractAtPathCommands(part.text)) {
|
|
6723
|
+
const resolved = path3.resolve(
|
|
6724
|
+
this.config.getProjectRoot(),
|
|
6725
|
+
pathSpec
|
|
6726
|
+
);
|
|
6727
|
+
const filteringOptions = this.config.getFileFilteringOptions();
|
|
6728
|
+
if (path3.isAbsolute(pathSpec) && getSpecificMimeType(resolved)?.startsWith("image/") && isExistingFile(resolved) && this.config.getWorkspaceContext().isPathWithinWorkspace(pathSpec) && !this.config.getFileService().shouldIgnoreFile(pathSpec, filteringOptions)) {
|
|
6729
|
+
textPathSpecsToRead.add(pathSpec);
|
|
6730
|
+
}
|
|
6731
|
+
}
|
|
5660
6732
|
return { text: part.text };
|
|
5661
6733
|
case "image":
|
|
5662
6734
|
if (preserveUnsupportedImageForBridge) {
|
|
@@ -5704,23 +6776,31 @@ ${this.pendingWorktreeNotice}
|
|
|
5704
6776
|
}
|
|
5705
6777
|
});
|
|
5706
6778
|
const atPathCommandParts = parts.filter((part) => "fileData" in part);
|
|
6779
|
+
const pathSpecsToRead = [
|
|
6780
|
+
.../* @__PURE__ */ new Set([
|
|
6781
|
+
...textPathSpecsToRead,
|
|
6782
|
+
...atPathCommandParts.map((part) => part.fileData.fileUri)
|
|
6783
|
+
])
|
|
6784
|
+
];
|
|
5707
6785
|
const extensionParts = await this.#resolveExtensionMentionParts(
|
|
5708
6786
|
extensionMentions,
|
|
5709
6787
|
abortSignal
|
|
5710
6788
|
);
|
|
5711
6789
|
const mcpServerParts = this.#resolveMcpServerMentionParts(mcpServerMentions);
|
|
5712
|
-
if (
|
|
5713
|
-
return this.#applyBridgeConversionsIfNeeded(
|
|
6790
|
+
if (pathSpecsToRead.length === 0 && embeddedContext.length === 0 && extensionParts.length === 0 && mcpServerParts.length === 0) {
|
|
6791
|
+
return this.#applyBridgeConversionsIfNeeded(
|
|
6792
|
+
parts,
|
|
6793
|
+
abortSignal,
|
|
6794
|
+
options.onFullTurnModel
|
|
6795
|
+
);
|
|
5714
6796
|
}
|
|
5715
|
-
if (
|
|
6797
|
+
if (pathSpecsToRead.length === 0 && embeddedContext.length === 0) {
|
|
5716
6798
|
return this.#applyBridgeConversionsIfNeeded(
|
|
5717
6799
|
[...parts, ...extensionParts, ...mcpServerParts],
|
|
5718
|
-
abortSignal
|
|
6800
|
+
abortSignal,
|
|
6801
|
+
options.onFullTurnModel
|
|
5719
6802
|
);
|
|
5720
6803
|
}
|
|
5721
|
-
const pathSpecsToRead = atPathCommandParts.map(
|
|
5722
|
-
(part) => part.fileData.fileUri
|
|
5723
|
-
);
|
|
5724
6804
|
let initialQueryText = "";
|
|
5725
6805
|
for (let i = 0; i < parts.length; i++) {
|
|
5726
6806
|
const chunk = parts[i];
|
|
@@ -5776,10 +6856,11 @@ ${contextPart.text}`
|
|
|
5776
6856
|
const processedQueryParts = options.promptLast ? [...referenceParts, promptPart] : [promptPart, ...referenceParts];
|
|
5777
6857
|
return this.#applyBridgeConversionsIfNeeded(
|
|
5778
6858
|
processedQueryParts,
|
|
5779
|
-
abortSignal
|
|
6859
|
+
abortSignal,
|
|
6860
|
+
options.onFullTurnModel
|
|
5780
6861
|
);
|
|
5781
6862
|
}
|
|
5782
|
-
async #applyBridgeConversionsIfNeeded(originalParts, abortSignal) {
|
|
6863
|
+
async #applyBridgeConversionsIfNeeded(originalParts, abortSignal, onFullTurnModel) {
|
|
5783
6864
|
const parts = await this.#applyVoiceBridgeIfNeeded(
|
|
5784
6865
|
originalParts,
|
|
5785
6866
|
abortSignal
|
|
@@ -5787,6 +6868,28 @@ ${contextPart.text}`
|
|
|
5787
6868
|
if (!hasImageParts(parts) || !shouldRunVisionBridge(this.config)) {
|
|
5788
6869
|
return parts;
|
|
5789
6870
|
}
|
|
6871
|
+
const fullTurnModel = this.config.getDefaultVisionBridgeModel();
|
|
6872
|
+
if (onFullTurnModel && fullTurnModel?.agentCapable) {
|
|
6873
|
+
const fullTurnParts = parts.map((part) => clampInlineMediaPart(part));
|
|
6874
|
+
if (!hasImageParts(fullTurnParts)) {
|
|
6875
|
+
return fullTurnParts;
|
|
6876
|
+
}
|
|
6877
|
+
const selected = onFullTurnModel(
|
|
6878
|
+
getFullTurnVisionModelSelector(fullTurnModel)
|
|
6879
|
+
);
|
|
6880
|
+
if (selected) {
|
|
6881
|
+
try {
|
|
6882
|
+
await this.messageEmitter.emitAgentMessage(
|
|
6883
|
+
formatFullTurnVisionNotice(fullTurnModel)
|
|
6884
|
+
);
|
|
6885
|
+
} catch (error) {
|
|
6886
|
+
debugLogger6.debug(
|
|
6887
|
+
`full-turn vision: failed to emit notice; continuing error=${error instanceof Error ? error.message : String(error)}`
|
|
6888
|
+
);
|
|
6889
|
+
}
|
|
6890
|
+
}
|
|
6891
|
+
return fullTurnParts;
|
|
6892
|
+
}
|
|
5790
6893
|
let bridgeResult;
|
|
5791
6894
|
try {
|
|
5792
6895
|
debugLogger6.debug("vision bridge: gate matched, running conversion");
|
|
@@ -6126,6 +7229,56 @@ var POSIX_TMP_LOCAL_READ_ROOT = "/tmp";
|
|
|
6126
7229
|
var BTW_CHILD_TIMEOUT_MS = 55e3;
|
|
6127
7230
|
var MCP_OAUTH_START_TIMEOUT_MS = 3e4;
|
|
6128
7231
|
var WORKSPACE_MEMORY_REMEMBER_CHILD_TIMEOUT_MS = 295e3;
|
|
7232
|
+
function createAcpSessionStartProfiler(span) {
|
|
7233
|
+
let failedStage;
|
|
7234
|
+
const setAttribute = /* @__PURE__ */ __name((name, value) => {
|
|
7235
|
+
try {
|
|
7236
|
+
span?.setAttribute(name, value);
|
|
7237
|
+
} catch {
|
|
7238
|
+
}
|
|
7239
|
+
}, "setAttribute");
|
|
7240
|
+
const recordStage = /* @__PURE__ */ __name((stage, start) => {
|
|
7241
|
+
const durationMs = Math.round((performance.now() - start) * 100) / 100;
|
|
7242
|
+
if (Number.isFinite(durationMs) && durationMs >= 0) {
|
|
7243
|
+
setAttribute(`qwen-code.daemon.session_start.${stage}_ms`, durationMs);
|
|
7244
|
+
}
|
|
7245
|
+
}, "recordStage");
|
|
7246
|
+
const recordFailure = /* @__PURE__ */ __name((stage) => {
|
|
7247
|
+
if (failedStage !== void 0) return;
|
|
7248
|
+
failedStage = stage;
|
|
7249
|
+
setAttribute("qwen-code.daemon.session_start.failed_stage", stage);
|
|
7250
|
+
}, "recordFailure");
|
|
7251
|
+
return {
|
|
7252
|
+
async time(stage, fn) {
|
|
7253
|
+
if (!span) return await fn();
|
|
7254
|
+
const start = performance.now();
|
|
7255
|
+
try {
|
|
7256
|
+
return await fn();
|
|
7257
|
+
} catch (error) {
|
|
7258
|
+
recordFailure(stage);
|
|
7259
|
+
throw error;
|
|
7260
|
+
} finally {
|
|
7261
|
+
recordStage(stage, start);
|
|
7262
|
+
}
|
|
7263
|
+
},
|
|
7264
|
+
timeSync(stage, fn) {
|
|
7265
|
+
if (!span) return fn();
|
|
7266
|
+
const start = performance.now();
|
|
7267
|
+
try {
|
|
7268
|
+
return fn();
|
|
7269
|
+
} catch (error) {
|
|
7270
|
+
recordFailure(stage);
|
|
7271
|
+
throw error;
|
|
7272
|
+
} finally {
|
|
7273
|
+
recordStage(stage, start);
|
|
7274
|
+
}
|
|
7275
|
+
},
|
|
7276
|
+
setSessionId(sessionId) {
|
|
7277
|
+
setAttribute("session.id", sessionId);
|
|
7278
|
+
}
|
|
7279
|
+
};
|
|
7280
|
+
}
|
|
7281
|
+
__name(createAcpSessionStartProfiler, "createAcpSessionStartProfiler");
|
|
6129
7282
|
function workspaceMemoryErrorData(code, diagnostics) {
|
|
6130
7283
|
return {
|
|
6131
7284
|
errorKind: code,
|
|
@@ -6206,6 +7359,40 @@ function isBulkLoadReplayRequest(params) {
|
|
|
6206
7359
|
return meta?.[LOAD_REPLAY_MODE_META_KEY] === LOAD_REPLAY_BULK_MODE;
|
|
6207
7360
|
}
|
|
6208
7361
|
__name(isBulkLoadReplayRequest, "isBulkLoadReplayRequest");
|
|
7362
|
+
function getLoadReplayPageSize(params) {
|
|
7363
|
+
const meta = isObjectRecord(params._meta) ? params._meta : void 0;
|
|
7364
|
+
const value = meta?.[LOAD_REPLAY_PAGE_SIZE_META_KEY];
|
|
7365
|
+
if (value === void 0) return void 0;
|
|
7366
|
+
if (!Number.isSafeInteger(value) || value < 1 || value > SESSION_TRANSCRIPT_MAX_LIMIT) {
|
|
7367
|
+
throw RequestError.invalidParams(
|
|
7368
|
+
void 0,
|
|
7369
|
+
`Invalid load replay page size; expected 1..${SESSION_TRANSCRIPT_MAX_LIMIT}`
|
|
7370
|
+
);
|
|
7371
|
+
}
|
|
7372
|
+
return value;
|
|
7373
|
+
}
|
|
7374
|
+
__name(getLoadReplayPageSize, "getLoadReplayPageSize");
|
|
7375
|
+
function isHistoryTurnStart(record) {
|
|
7376
|
+
return record.type === "user" && record.subtype !== "mid_turn_user_message";
|
|
7377
|
+
}
|
|
7378
|
+
__name(isHistoryTurnStart, "isHistoryTurnStart");
|
|
7379
|
+
function selectRecentHistoryRecords(records, pageSize) {
|
|
7380
|
+
if (pageSize === void 0 || records.length <= pageSize) {
|
|
7381
|
+
return { records, hasMore: false };
|
|
7382
|
+
}
|
|
7383
|
+
let start = records.length - pageSize;
|
|
7384
|
+
for (let i = start; i < records.length; i++) {
|
|
7385
|
+
if (isHistoryTurnStart(records[i])) {
|
|
7386
|
+
start = i;
|
|
7387
|
+
break;
|
|
7388
|
+
}
|
|
7389
|
+
}
|
|
7390
|
+
while (start > 0 && !isHistoryTurnStart(records[start])) {
|
|
7391
|
+
start--;
|
|
7392
|
+
}
|
|
7393
|
+
return { records: records.slice(start), hasMore: start > 0 };
|
|
7394
|
+
}
|
|
7395
|
+
__name(selectRecentHistoryRecords, "selectRecentHistoryRecords");
|
|
6209
7396
|
function createHiddenWorkspaceMemoryConfig(config) {
|
|
6210
7397
|
return new Proxy(config, {
|
|
6211
7398
|
get(target, prop) {
|
|
@@ -7604,16 +8791,21 @@ __name(deliverClientMcpMessage, "deliverClientMcpMessage");
|
|
|
7604
8791
|
async function runAcpAgent(config, settings, argv) {
|
|
7605
8792
|
let acpConnection;
|
|
7606
8793
|
const bootstrapClientMcpSender = /* @__PURE__ */ __name((serverName, message) => deliverClientMcpMessage(acpConnection, serverName, message), "bootstrapClientMcpSender");
|
|
7607
|
-
|
|
7608
|
-
|
|
7609
|
-
|
|
7610
|
-
|
|
7611
|
-
|
|
7612
|
-
|
|
7613
|
-
|
|
7614
|
-
|
|
7615
|
-
|
|
7616
|
-
|
|
8794
|
+
beginAcpBootstrapConfigProfiling();
|
|
8795
|
+
try {
|
|
8796
|
+
await config.initialize({
|
|
8797
|
+
skipGeminiInitialization: true,
|
|
8798
|
+
// Bootstrap skips MCP discovery — each session runs its own
|
|
8799
|
+
// pool-routed discovery, so bootstrap-level spawns would be
|
|
8800
|
+
// redundant subprocess leaks (W119).
|
|
8801
|
+
skipMcpDiscovery: true,
|
|
8802
|
+
// Bind the workspace-level manager's SDK callback so a runtime-added
|
|
8803
|
+
// client-hosted MCP server (#5626) round-trips over the parent WS.
|
|
8804
|
+
sendSdkMcpMessage: bootstrapClientMcpSender
|
|
8805
|
+
});
|
|
8806
|
+
} finally {
|
|
8807
|
+
endAcpBootstrapConfigProfiling();
|
|
8808
|
+
}
|
|
7617
8809
|
const eventLoopMonitor = startEventLoopLagMonitor({
|
|
7618
8810
|
onNewMaxStall: /* @__PURE__ */ __name((maxMs) => {
|
|
7619
8811
|
console.error(`[perf] acp agent event loop stall: max=${maxMs}ms`);
|
|
@@ -7621,6 +8813,7 @@ async function runAcpAgent(config, settings, argv) {
|
|
|
7621
8813
|
});
|
|
7622
8814
|
let agentInstance;
|
|
7623
8815
|
let connection;
|
|
8816
|
+
markAcpStartup("transportSetupStart");
|
|
7624
8817
|
try {
|
|
7625
8818
|
const stdout = Writable.toWeb(process.stdout);
|
|
7626
8819
|
const stdin = Readable.toWeb(process.stdin);
|
|
@@ -7633,6 +8826,7 @@ async function runAcpAgent(config, settings, argv) {
|
|
|
7633
8826
|
agentInstance = new QwenAgent(config, settings, argv, conn);
|
|
7634
8827
|
return agentInstance;
|
|
7635
8828
|
}, stream);
|
|
8829
|
+
markAcpStartup("transportSetupEnd");
|
|
7636
8830
|
} catch (err) {
|
|
7637
8831
|
eventLoopMonitor.dispose();
|
|
7638
8832
|
throw err;
|
|
@@ -8212,10 +9406,11 @@ var QwenAgent = class {
|
|
|
8212
9406
|
}
|
|
8213
9407
|
}
|
|
8214
9408
|
async initialize(args) {
|
|
9409
|
+
markAcpStartup("initializeHandlerStart");
|
|
8215
9410
|
this.clientCapabilities = args.clientCapabilities;
|
|
8216
9411
|
const authMethods = buildAuthMethods();
|
|
8217
|
-
const version = "0.19.
|
|
8218
|
-
|
|
9412
|
+
const version = "0.19.12-preview.0";
|
|
9413
|
+
const response = {
|
|
8219
9414
|
protocolVersion: PROTOCOL_VERSION,
|
|
8220
9415
|
agentInfo: {
|
|
8221
9416
|
name: "qwen-code",
|
|
@@ -8243,6 +9438,22 @@ var QwenAgent = class {
|
|
|
8243
9438
|
}
|
|
8244
9439
|
}
|
|
8245
9440
|
};
|
|
9441
|
+
markAcpStartup("initializeHandlerEnd");
|
|
9442
|
+
markAcpStartup("responseBuilt");
|
|
9443
|
+
let startupProfile;
|
|
9444
|
+
try {
|
|
9445
|
+
startupProfile = buildAndFreezeAcpStartupProfile();
|
|
9446
|
+
} catch {
|
|
9447
|
+
startupProfile = void 0;
|
|
9448
|
+
}
|
|
9449
|
+
const requestedProfile = args._meta?.[CHANNEL_STARTUP_PROFILE_META_KEY];
|
|
9450
|
+
const profileRequested = requestedProfile !== null && typeof requestedProfile === "object" && !Array.isArray(requestedProfile) && requestedProfile["v"] === CHANNEL_STARTUP_PROFILE_VERSION;
|
|
9451
|
+
return profileRequested && startupProfile ? {
|
|
9452
|
+
...response,
|
|
9453
|
+
_meta: {
|
|
9454
|
+
[CHANNEL_STARTUP_PROFILE_META_KEY]: startupProfile
|
|
9455
|
+
}
|
|
9456
|
+
} : response;
|
|
8246
9457
|
}
|
|
8247
9458
|
async authenticate({ methodId }) {
|
|
8248
9459
|
const method = external_exports.nativeEnum(AuthType).parse(methodId);
|
|
@@ -8270,25 +9481,42 @@ var QwenAgent = class {
|
|
|
8270
9481
|
}
|
|
8271
9482
|
}
|
|
8272
9483
|
}
|
|
8273
|
-
async newSession({
|
|
8274
|
-
cwd,
|
|
8275
|
-
|
|
8276
|
-
|
|
8277
|
-
|
|
8278
|
-
|
|
8279
|
-
|
|
8280
|
-
|
|
8281
|
-
|
|
8282
|
-
|
|
8283
|
-
|
|
8284
|
-
|
|
8285
|
-
|
|
8286
|
-
|
|
8287
|
-
|
|
8288
|
-
|
|
8289
|
-
|
|
8290
|
-
|
|
8291
|
-
|
|
9484
|
+
async newSession(params) {
|
|
9485
|
+
const { cwd, mcpServers } = params;
|
|
9486
|
+
const parentContext = extractDaemonTraceContext(params);
|
|
9487
|
+
return await withDaemonSpan(
|
|
9488
|
+
"qwen-code.daemon.session_start",
|
|
9489
|
+
{ "qwen-code.daemon.operation": "acp_session_new" },
|
|
9490
|
+
async (span) => {
|
|
9491
|
+
const profiler = createAcpSessionStartProfiler(span);
|
|
9492
|
+
const settings = profiler.timeSync(
|
|
9493
|
+
"settings_load",
|
|
9494
|
+
() => loadSettingsCached(cwd)
|
|
9495
|
+
);
|
|
9496
|
+
this.settings = settings;
|
|
9497
|
+
const config = await profiler.time(
|
|
9498
|
+
"config_setup",
|
|
9499
|
+
() => this.newSessionConfig(cwd, mcpServers, settings)
|
|
9500
|
+
);
|
|
9501
|
+
await profiler.time("auth", () => this.ensureAuthenticated(config));
|
|
9502
|
+
profiler.timeSync(
|
|
9503
|
+
"file_system_setup",
|
|
9504
|
+
() => this.setupFileSystem(config)
|
|
9505
|
+
);
|
|
9506
|
+
const session = await profiler.time(
|
|
9507
|
+
"session_register",
|
|
9508
|
+
() => this.createAndStoreSession(config, settings)
|
|
9509
|
+
);
|
|
9510
|
+
profiler.setSessionId(session.getId());
|
|
9511
|
+
return profiler.timeSync("response_build", () => ({
|
|
9512
|
+
sessionId: session.getId(),
|
|
9513
|
+
models: this.buildAvailableModels(config),
|
|
9514
|
+
modes: this.buildModesData(config),
|
|
9515
|
+
configOptions: this.buildConfigOptions(config)
|
|
9516
|
+
}));
|
|
9517
|
+
},
|
|
9518
|
+
parentContext ? { parentContext } : {}
|
|
9519
|
+
);
|
|
8292
9520
|
}
|
|
8293
9521
|
async loadSession(params) {
|
|
8294
9522
|
const settings = loadSettingsCached(params.cwd);
|
|
@@ -8319,6 +9547,7 @@ var QwenAgent = class {
|
|
|
8319
9547
|
this.setupFileSystem(config);
|
|
8320
9548
|
const sessionData = config.getResumedSessionData();
|
|
8321
9549
|
const bulkReplay = isBulkLoadReplayRequest(params);
|
|
9550
|
+
const replayPageSize = bulkReplay ? getLoadReplayPageSize(params) : void 0;
|
|
8322
9551
|
const session = await this.createAndStoreSession(
|
|
8323
9552
|
config,
|
|
8324
9553
|
settings,
|
|
@@ -8332,13 +9561,19 @@ var QwenAgent = class {
|
|
|
8332
9561
|
let replayUpdates = [];
|
|
8333
9562
|
if (records) {
|
|
8334
9563
|
session.primeTurnFromHistory(records);
|
|
9564
|
+
const replayPage = selectRecentHistoryRecords(
|
|
9565
|
+
records,
|
|
9566
|
+
replayPageSize
|
|
9567
|
+
);
|
|
8335
9568
|
const replayUsage = createReplayCumulativeUsage();
|
|
8336
9569
|
const replay = await collectHistoryReplayUpdates({
|
|
8337
9570
|
sessionId: params.sessionId,
|
|
8338
9571
|
config,
|
|
8339
|
-
records,
|
|
9572
|
+
records: replayPage.records,
|
|
8340
9573
|
gaps: sessionData?.historyGaps,
|
|
8341
9574
|
cumulativeUsage: replayUsage,
|
|
9575
|
+
// A resume: the goal restore runs right after this.
|
|
9576
|
+
supersedeUnrestorableGoal: true,
|
|
8342
9577
|
logger: debugLogger7
|
|
8343
9578
|
});
|
|
8344
9579
|
replayUpdates = replay.updates;
|
|
@@ -8348,9 +9583,15 @@ var QwenAgent = class {
|
|
|
8348
9583
|
v: LOAD_REPLAY_VERSION,
|
|
8349
9584
|
updates: replayUpdates,
|
|
8350
9585
|
partial: true,
|
|
8351
|
-
replayError: replay.replayError
|
|
9586
|
+
replayError: replay.replayError,
|
|
9587
|
+
...replayPage.hasMore ? { hasMore: true } : {}
|
|
8352
9588
|
};
|
|
8353
9589
|
}
|
|
9590
|
+
replayEnvelope ??= {
|
|
9591
|
+
v: LOAD_REPLAY_VERSION,
|
|
9592
|
+
updates: replayUpdates,
|
|
9593
|
+
...replayPage.hasMore ? { hasMore: true } : {}
|
|
9594
|
+
};
|
|
8354
9595
|
}
|
|
8355
9596
|
replayEnvelope ??= {
|
|
8356
9597
|
v: LOAD_REPLAY_VERSION,
|
|
@@ -8364,6 +9605,7 @@ var QwenAgent = class {
|
|
|
8364
9605
|
}
|
|
8365
9606
|
}
|
|
8366
9607
|
await this.#restoreWorktreeOnResume(config, session);
|
|
9608
|
+
this.#restoreGoalOnResume(config, session);
|
|
8367
9609
|
const modesData = this.buildModesData(config);
|
|
8368
9610
|
const availableModels = this.buildAvailableModels(config);
|
|
8369
9611
|
const configOptions = this.buildConfigOptions(config);
|
|
@@ -8413,6 +9655,7 @@ var QwenAgent = class {
|
|
|
8413
9655
|
{ replayHistory: false }
|
|
8414
9656
|
);
|
|
8415
9657
|
await this.#restoreWorktreeOnResume(config, session);
|
|
9658
|
+
this.#restoreGoalOnResume(config, session);
|
|
8416
9659
|
const modesData = this.buildModesData(config);
|
|
8417
9660
|
const availableModels = this.buildAvailableModels(config);
|
|
8418
9661
|
const configOptions = this.buildConfigOptions(config);
|
|
@@ -8441,6 +9684,48 @@ var QwenAgent = class {
|
|
|
8441
9684
|
debugLogger7.warn(`ACP worktree restore failed: ${error}`);
|
|
8442
9685
|
}
|
|
8443
9686
|
}
|
|
9687
|
+
/**
|
|
9688
|
+
* Re-registers the `/goal` Stop hook when a resumed transcript ends on an
|
|
9689
|
+
* unsatisfied goal — the daemon counterpart of the TUI's resume restore.
|
|
9690
|
+
* Without this the goal loop silently dies whenever a session is reloaded or
|
|
9691
|
+
* `qwen serve` restarts, even though the transcript still shows it as active.
|
|
9692
|
+
*
|
|
9693
|
+
* The `addItem` bridge that `restoreGoalFromHistory` takes in the TUI is not
|
|
9694
|
+
* used here — the daemon's terminal card goes out over the wire, not into an
|
|
9695
|
+
* Ink history. But restore reaches `unregisterGoalHook` on every path,
|
|
9696
|
+
* including the one where there was nothing to restore, and that clears the
|
|
9697
|
+
* observer the `Session` constructor installed. So it is put back afterwards,
|
|
9698
|
+
* unconditionally: without it a restored goal that later achieves or fails
|
|
9699
|
+
* emits no terminal update and persists no terminal card, and the next reload
|
|
9700
|
+
* revives a goal that already finished.
|
|
9701
|
+
*
|
|
9702
|
+
* Best-effort: a failed restore must not block session load.
|
|
9703
|
+
*/
|
|
9704
|
+
#restoreGoalOnResume(config, session) {
|
|
9705
|
+
try {
|
|
9706
|
+
const records = config.getResumedSessionData()?.conversation.messages;
|
|
9707
|
+
if (!records?.length) return;
|
|
9708
|
+
const restored = restoreGoalFromHistory(
|
|
9709
|
+
collectGoalStatusItemsFromRecords(records),
|
|
9710
|
+
config
|
|
9711
|
+
);
|
|
9712
|
+
if (restored.restored) {
|
|
9713
|
+
debugLogger7.info(
|
|
9714
|
+
`ACP goal restored sessionId=${config.getSessionId()} condition=${restored.condition}`
|
|
9715
|
+
);
|
|
9716
|
+
} else if (restored.blockedBy && restored.blockedBy !== "condition-invalid") {
|
|
9717
|
+
writeStderrLineSafe(
|
|
9718
|
+
`qwen: not restoring the active goal for session ${config.getSessionId()} (${restored.blockedBy}).`
|
|
9719
|
+
);
|
|
9720
|
+
}
|
|
9721
|
+
} catch (error) {
|
|
9722
|
+
writeStderrLineSafe(
|
|
9723
|
+
`qwen: goal restore failed for session ${config.getSessionId()}: ${error}`
|
|
9724
|
+
);
|
|
9725
|
+
} finally {
|
|
9726
|
+
session.installGoalTerminalObserver();
|
|
9727
|
+
}
|
|
9728
|
+
}
|
|
8444
9729
|
async unstable_listSessions(params) {
|
|
8445
9730
|
const cwd = params.cwd || process.cwd();
|
|
8446
9731
|
const numericCursor = parseAcpSessionListCursor(params.cursor);
|
|
@@ -9298,9 +10583,18 @@ var QwenAgent = class {
|
|
|
9298
10583
|
const currentModelId = activeRuntimeSnapshot ? activeRuntimeSnapshot.id : (config.getModel() || "").trim();
|
|
9299
10584
|
const hasCurrentModel = currentModelId.length > 0;
|
|
9300
10585
|
const currentAuth = activeRuntimeSnapshot?.authType ?? currentAuthType;
|
|
9301
|
-
const
|
|
10586
|
+
const modelOptions = buildAcpModelOptions(
|
|
10587
|
+
config.getAllConfiguredModels()
|
|
10588
|
+
);
|
|
10589
|
+
const currentAcpModelId = hasCurrentModel ? getCurrentAcpModelId(
|
|
10590
|
+
modelOptions,
|
|
10591
|
+
currentModelId,
|
|
10592
|
+
currentAuth,
|
|
10593
|
+
activeRuntimeSnapshot ? void 0 : config.getCurrentModelRegistryBaseUrl?.()
|
|
10594
|
+
) : void 0;
|
|
9302
10595
|
const providers = /* @__PURE__ */ new Map();
|
|
9303
|
-
for (const
|
|
10596
|
+
for (const option of modelOptions) {
|
|
10597
|
+
const { model, effectiveModelId, modelId } = option;
|
|
9304
10598
|
const authType = String(model.authType);
|
|
9305
10599
|
let provider = providers.get(authType);
|
|
9306
10600
|
if (!provider) {
|
|
@@ -9313,9 +10607,7 @@ var QwenAgent = class {
|
|
|
9313
10607
|
};
|
|
9314
10608
|
providers.set(authType, provider);
|
|
9315
10609
|
}
|
|
9316
|
-
const
|
|
9317
|
-
const modelId = formatAcpModelId(effectiveModelId, model.authType);
|
|
9318
|
-
const isCurrent = currentAuth === model.authType && hasCurrentModel && (currentModelId === effectiveModelId || currentModelId === model.id || currentAcpModelId === modelId);
|
|
10610
|
+
const isCurrent = currentAuth === model.authType && currentAcpModelId === modelId;
|
|
9319
10611
|
const providerModel = {
|
|
9320
10612
|
modelId,
|
|
9321
10613
|
baseModelId: parseAcpBaseModelId(effectiveModelId),
|
|
@@ -10279,6 +11571,25 @@ var QwenAgent = class {
|
|
|
10279
11571
|
const cwd = requestedCwd || process.cwd();
|
|
10280
11572
|
const SESSION_ID_RE = /^[0-9a-fA-F-]{32,36}$/;
|
|
10281
11573
|
switch (method) {
|
|
11574
|
+
case TODO_STOP_GUARD_QUEUE_RELEASE_METHOD: {
|
|
11575
|
+
const sessionId = params["sessionId"];
|
|
11576
|
+
if (typeof sessionId !== "string" || sessionId.length === 0) {
|
|
11577
|
+
throw RequestError.invalidParams(
|
|
11578
|
+
void 0,
|
|
11579
|
+
"Invalid or missing sessionId"
|
|
11580
|
+
);
|
|
11581
|
+
}
|
|
11582
|
+
const session = this.sessions.get(sessionId);
|
|
11583
|
+
if (!session) {
|
|
11584
|
+
throw RequestError.invalidParams(
|
|
11585
|
+
void 0,
|
|
11586
|
+
`Session not found for id: ${sessionId}`
|
|
11587
|
+
);
|
|
11588
|
+
}
|
|
11589
|
+
return {
|
|
11590
|
+
released: session.releaseTodoStopGuardQueuedPromptWait()
|
|
11591
|
+
};
|
|
11592
|
+
}
|
|
10282
11593
|
case "qwen/providers/list": {
|
|
10283
11594
|
return {
|
|
10284
11595
|
providers: ALL_PROVIDERS.map(
|
|
@@ -10516,6 +11827,19 @@ var QwenAgent = class {
|
|
|
10516
11827
|
"Invalid transcript cursor"
|
|
10517
11828
|
);
|
|
10518
11829
|
}
|
|
11830
|
+
const rawBeforeRecordId = params["beforeRecordId"];
|
|
11831
|
+
if (rawBeforeRecordId !== void 0 && (typeof rawBeforeRecordId !== "string" || rawBeforeRecordId.length === 0)) {
|
|
11832
|
+
throw RequestError.invalidParams(
|
|
11833
|
+
void 0,
|
|
11834
|
+
"Invalid transcript record boundary"
|
|
11835
|
+
);
|
|
11836
|
+
}
|
|
11837
|
+
if (rawCursor !== void 0 && rawBeforeRecordId !== void 0) {
|
|
11838
|
+
throw RequestError.invalidParams(
|
|
11839
|
+
void 0,
|
|
11840
|
+
"Transcript cursor and record boundary are mutually exclusive"
|
|
11841
|
+
);
|
|
11842
|
+
}
|
|
10519
11843
|
const rawLimit = params["limit"];
|
|
10520
11844
|
if (rawLimit !== void 0 && (!Number.isSafeInteger(rawLimit) || rawLimit < 1 || rawLimit > SESSION_TRANSCRIPT_MAX_LIMIT)) {
|
|
10521
11845
|
throw RequestError.invalidParams(
|
|
@@ -10529,7 +11853,9 @@ var QwenAgent = class {
|
|
|
10529
11853
|
const reader = new SessionTranscriptReader(cwd);
|
|
10530
11854
|
const page = await reader.readPage(sessionId, {
|
|
10531
11855
|
...typeof rawCursor === "string" ? { cursor: rawCursor } : {},
|
|
10532
|
-
...typeof
|
|
11856
|
+
...typeof rawBeforeRecordId === "string" ? { beforeRecordId: rawBeforeRecordId } : {},
|
|
11857
|
+
...typeof rawLimit === "number" ? { limit: rawLimit } : {},
|
|
11858
|
+
maxBytes: SESSION_TRANSCRIPT_MAX_PAGE_BYTES
|
|
10533
11859
|
});
|
|
10534
11860
|
const config = await this.getTranscriptReplayConfig(cwd, settings);
|
|
10535
11861
|
const replay = await replayTranscriptRecordPage({
|
|
@@ -10578,6 +11904,14 @@ var QwenAgent = class {
|
|
|
10578
11904
|
maxBytes: error.maxBytes
|
|
10579
11905
|
});
|
|
10580
11906
|
}
|
|
11907
|
+
if (error instanceof SessionTranscriptPageTooLargeError) {
|
|
11908
|
+
throw new RequestError(-32012, error.message, {
|
|
11909
|
+
errorKind: "transcript_page_too_large",
|
|
11910
|
+
sessionId,
|
|
11911
|
+
pageBytes: error.pageBytes,
|
|
11912
|
+
maxBytes: error.maxBytes
|
|
11913
|
+
});
|
|
11914
|
+
}
|
|
10581
11915
|
if (error.code === "ENOENT") {
|
|
10582
11916
|
if (typeof rawCursor === "string") {
|
|
10583
11917
|
throw new RequestError(
|
|
@@ -11222,10 +12556,10 @@ var QwenAgent = class {
|
|
|
11222
12556
|
let resolveStarted;
|
|
11223
12557
|
let rejectStarted;
|
|
11224
12558
|
let startedTimer;
|
|
11225
|
-
const started = new Promise((
|
|
12559
|
+
const started = new Promise((resolve5, reject) => {
|
|
11226
12560
|
resolveStarted = /* @__PURE__ */ __name((value) => {
|
|
11227
12561
|
clearTimeout(startedTimer);
|
|
11228
|
-
|
|
12562
|
+
resolve5(value);
|
|
11229
12563
|
}, "resolveStarted");
|
|
11230
12564
|
rejectStarted = /* @__PURE__ */ __name((reason) => {
|
|
11231
12565
|
clearTimeout(startedTimer);
|
|
@@ -11543,6 +12877,7 @@ var QwenAgent = class {
|
|
|
11543
12877
|
`Model context refresh failed: ${error instanceof Error ? error.message : String(error)}`
|
|
11544
12878
|
);
|
|
11545
12879
|
}
|
|
12880
|
+
session.clearTodoStopGuardTrust();
|
|
11546
12881
|
return { previousCwd, newCwd: canonicalPath, warnings };
|
|
11547
12882
|
}
|
|
11548
12883
|
case SERVE_CONTROL_EXT_METHODS.sessionApprovalMode: {
|
|
@@ -11574,6 +12909,9 @@ var QwenAgent = class {
|
|
|
11574
12909
|
throw err;
|
|
11575
12910
|
}
|
|
11576
12911
|
const current = config.getApprovalMode();
|
|
12912
|
+
if (current === "plan") {
|
|
12913
|
+
session.clearTodoStopGuardTrust();
|
|
12914
|
+
}
|
|
11577
12915
|
return { previous, current };
|
|
11578
12916
|
}
|
|
11579
12917
|
case SERVE_CONTROL_EXT_METHODS.sessionLanguage: {
|
|
@@ -11619,8 +12957,7 @@ var QwenAgent = class {
|
|
|
11619
12957
|
let outputLanguage = null;
|
|
11620
12958
|
let refreshed = false;
|
|
11621
12959
|
if (syncOutputLanguage) {
|
|
11622
|
-
const
|
|
11623
|
-
const settingValue = isAutoLanguage(language) ? OUTPUT_LANGUAGE_AUTO : resolved;
|
|
12960
|
+
const settingValue = resolveOutputLanguageOrPreserveAuto(language);
|
|
11624
12961
|
let fileWriteOk = false;
|
|
11625
12962
|
try {
|
|
11626
12963
|
writeOutputLanguageAndRegisterPath(
|
|
@@ -11678,7 +13015,7 @@ var QwenAgent = class {
|
|
|
11678
13015
|
}
|
|
11679
13016
|
refreshed = results.length === 0 || failedCount === 0;
|
|
11680
13017
|
}
|
|
11681
|
-
outputLanguage = fileWriteOk ?
|
|
13018
|
+
outputLanguage = fileWriteOk ? settingValue : null;
|
|
11682
13019
|
}
|
|
11683
13020
|
return { language: resolvedLanguage, outputLanguage, refreshed };
|
|
11684
13021
|
}
|
|
@@ -12020,6 +13357,27 @@ ${outputText}
|
|
|
12020
13357
|
condition: cleared?.condition
|
|
12021
13358
|
};
|
|
12022
13359
|
}
|
|
13360
|
+
case SERVE_CONTROL_EXT_METHODS.sessionGoalGet: {
|
|
13361
|
+
const sessionId = params["sessionId"];
|
|
13362
|
+
if (typeof sessionId !== "string" || sessionId.length === 0) {
|
|
13363
|
+
throw RequestError.invalidParams(
|
|
13364
|
+
void 0,
|
|
13365
|
+
"Invalid or missing sessionId"
|
|
13366
|
+
);
|
|
13367
|
+
}
|
|
13368
|
+
this.sessionOrThrow(sessionId);
|
|
13369
|
+
const active = getActiveGoal(sessionId);
|
|
13370
|
+
return {
|
|
13371
|
+
// Projected field by field: `ActiveGoal` also carries `hookId` and
|
|
13372
|
+
// `tokensAtStart`, which are this process's business.
|
|
13373
|
+
active: active ? {
|
|
13374
|
+
condition: active.condition,
|
|
13375
|
+
iterations: active.iterations,
|
|
13376
|
+
setAt: active.setAt,
|
|
13377
|
+
...active.lastReason !== void 0 ? { lastReason: active.lastReason } : {}
|
|
13378
|
+
} : null
|
|
13379
|
+
};
|
|
13380
|
+
}
|
|
12023
13381
|
case SERVE_CONTROL_EXT_METHODS.sessionContinue: {
|
|
12024
13382
|
const sessionId = params["sessionId"];
|
|
12025
13383
|
if (typeof sessionId !== "string" || sessionId.length === 0) {
|
|
@@ -12816,6 +14174,9 @@ ${outputText}
|
|
|
12816
14174
|
if (newMode && APPROVAL_MODES.includes(newMode) && newMode !== config.getApprovalMode()) {
|
|
12817
14175
|
try {
|
|
12818
14176
|
config.setApprovalMode(newMode);
|
|
14177
|
+
if (newMode === "plan") {
|
|
14178
|
+
session.clearTodoStopGuardTrust();
|
|
14179
|
+
}
|
|
12819
14180
|
} catch (err) {
|
|
12820
14181
|
debugLogger7.warn(
|
|
12821
14182
|
`reload: setApprovalMode failed for session ${id}: ${err}`
|
|
@@ -13179,23 +14540,22 @@ ${outputText}
|
|
|
13179
14540
|
buildAvailableModels(config) {
|
|
13180
14541
|
const rawCurrentModelId = (config.getModel() || this.config.getModel() || "").trim();
|
|
13181
14542
|
const currentAuthType = config.getAuthType();
|
|
13182
|
-
const
|
|
14543
|
+
const modelOptions = buildAcpModelOptions(config.getAllConfiguredModels());
|
|
13183
14544
|
const activeRuntimeSnapshot = config.getActiveRuntimeModelSnapshot?.();
|
|
13184
|
-
const currentModelId =
|
|
13185
|
-
|
|
13186
|
-
activeRuntimeSnapshot
|
|
13187
|
-
|
|
13188
|
-
|
|
13189
|
-
|
|
13190
|
-
|
|
13191
|
-
|
|
13192
|
-
|
|
13193
|
-
|
|
13194
|
-
|
|
13195
|
-
|
|
13196
|
-
|
|
13197
|
-
|
|
13198
|
-
});
|
|
14545
|
+
const currentModelId = getCurrentAcpModelId(
|
|
14546
|
+
modelOptions,
|
|
14547
|
+
activeRuntimeSnapshot?.id ?? rawCurrentModelId,
|
|
14548
|
+
activeRuntimeSnapshot?.authType ?? currentAuthType,
|
|
14549
|
+
activeRuntimeSnapshot ? void 0 : config.getCurrentModelRegistryBaseUrl?.()
|
|
14550
|
+
);
|
|
14551
|
+
const mappedAvailableModels = modelOptions.map(({ model, modelId }) => ({
|
|
14552
|
+
modelId,
|
|
14553
|
+
name: model.label,
|
|
14554
|
+
description: model.description ?? null,
|
|
14555
|
+
_meta: {
|
|
14556
|
+
contextLimit: model.contextWindowSize ?? tokenLimit(model.id)
|
|
14557
|
+
}
|
|
14558
|
+
}));
|
|
13199
14559
|
return {
|
|
13200
14560
|
currentModelId,
|
|
13201
14561
|
availableModels: mappedAvailableModels
|
|
@@ -13215,14 +14575,16 @@ ${outputText}
|
|
|
13215
14575
|
}
|
|
13216
14576
|
buildConfigOptions(config) {
|
|
13217
14577
|
const currentApprovalMode = config.getApprovalMode();
|
|
13218
|
-
const
|
|
14578
|
+
const modelOptions = buildAcpModelOptions(config.getAllConfiguredModels());
|
|
13219
14579
|
const rawCurrentModelId = (config.getModel() || "").trim();
|
|
13220
14580
|
const currentAuthType = config.getAuthType?.();
|
|
13221
14581
|
const activeRuntimeSnapshot = config.getActiveRuntimeModelSnapshot?.();
|
|
13222
|
-
const currentModelId =
|
|
13223
|
-
|
|
13224
|
-
activeRuntimeSnapshot
|
|
13225
|
-
|
|
14582
|
+
const currentModelId = getCurrentAcpModelId(
|
|
14583
|
+
modelOptions,
|
|
14584
|
+
activeRuntimeSnapshot?.id ?? rawCurrentModelId,
|
|
14585
|
+
activeRuntimeSnapshot?.authType ?? currentAuthType,
|
|
14586
|
+
activeRuntimeSnapshot ? void 0 : config.getCurrentModelRegistryBaseUrl?.()
|
|
14587
|
+
);
|
|
13226
14588
|
const modeOptions = APPROVAL_MODES.map((mode) => ({
|
|
13227
14589
|
value: mode,
|
|
13228
14590
|
name: APPROVAL_MODE_INFO[mode].name,
|
|
@@ -13237,14 +14599,11 @@ ${outputText}
|
|
|
13237
14599
|
currentValue: currentApprovalMode,
|
|
13238
14600
|
options: modeOptions
|
|
13239
14601
|
};
|
|
13240
|
-
const
|
|
13241
|
-
|
|
13242
|
-
|
|
13243
|
-
|
|
13244
|
-
|
|
13245
|
-
description: model.description ?? ""
|
|
13246
|
-
};
|
|
13247
|
-
});
|
|
14602
|
+
const configModelOptions = modelOptions.map(({ model, modelId }) => ({
|
|
14603
|
+
value: modelId,
|
|
14604
|
+
name: model.label,
|
|
14605
|
+
description: model.description ?? ""
|
|
14606
|
+
}));
|
|
13248
14607
|
const modelConfigOption = {
|
|
13249
14608
|
id: "model",
|
|
13250
14609
|
name: "Model",
|
|
@@ -13252,19 +14611,11 @@ ${outputText}
|
|
|
13252
14611
|
category: "model",
|
|
13253
14612
|
type: "select",
|
|
13254
14613
|
currentValue: currentModelId,
|
|
13255
|
-
options:
|
|
14614
|
+
options: configModelOptions
|
|
13256
14615
|
};
|
|
13257
14616
|
return [modeConfigOption, modelConfigOption];
|
|
13258
14617
|
}
|
|
13259
|
-
formatCurrentModelId(baseModelId, authType) {
|
|
13260
|
-
if (!baseModelId) return baseModelId;
|
|
13261
|
-
return authType ? formatAcpModelId(baseModelId, authType) : baseModelId;
|
|
13262
|
-
}
|
|
13263
14618
|
};
|
|
13264
|
-
function isMainSelectableModel(model) {
|
|
13265
|
-
return model.fastOnly !== true && model.voiceOnly !== true;
|
|
13266
|
-
}
|
|
13267
|
-
__name(isMainSelectableModel, "isMainSelectableModel");
|
|
13268
14619
|
function diffSettingsKeys(oldMerged, newMerged) {
|
|
13269
14620
|
const changed = /* @__PURE__ */ new Set();
|
|
13270
14621
|
const allKeys = /* @__PURE__ */ new Set([
|
|
@@ -13297,6 +14648,11 @@ export {
|
|
|
13297
14648
|
* Copyright 2025 Qwen Team
|
|
13298
14649
|
* SPDX-License-Identifier: Apache-2.0
|
|
13299
14650
|
*/
|
|
14651
|
+
/**
|
|
14652
|
+
* @license
|
|
14653
|
+
* Copyright 2026 Qwen
|
|
14654
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
14655
|
+
*/
|
|
13300
14656
|
/**
|
|
13301
14657
|
* @license
|
|
13302
14658
|
* Copyright 2025 Qwen
|