@qwen-code/qwen-code 0.23.1-preview.2 → 0.23.2-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/computer-use/SKILL.md +189 -116
- package/bundled/goal-draft/SKILL.md +23 -13
- package/bundled/qc-helper/docs/_meta.ts +1 -0
- package/bundled/qc-helper/docs/configuration/model-providers.md +47 -1
- package/bundled/qc-helper/docs/configuration/settings.md +50 -0
- package/bundled/qc-helper/docs/conversations-recovery.md +102 -0
- package/bundled/qc-helper/docs/features/channels/overview.md +1 -1
- package/bundled/qc-helper/docs/features/computer-use.md +9 -7
- package/bundled/qc-helper/docs/features/followup-suggestions.md +2 -2
- package/bundled/qc-helper/docs/features/goals.md +15 -3
- package/bundled/qc-helper/docs/qwen-serve.md +19 -1
- package/chunks/{MaxSizedBox-IYIQ43IZ.js → MaxSizedBox-ZZJT3PJF.js} +20 -20
- package/chunks/{StandaloneSessionPicker-AWB2OHX6.js → StandaloneSessionPicker-DIOSZTMX.js} +38 -38
- package/chunks/{acp-startup-profiler-BAL4LJTN.js → acp-startup-profiler-KEU6VAYR.js} +2 -2
- package/chunks/{acpAgent-ZC57OLS4.js → acpAgent-62JUP5A7.js} +118 -91
- package/chunks/{agent-GEBPAEJS.js → agent-NLPEQQDZ.js} +13 -13
- package/chunks/{agent-headless-63ZEYAJK.js → agent-headless-Y2GR5F2Q.js} +13 -13
- package/chunks/{anthropicContentGenerator-6XDHXIII.js → anthropicContentGenerator-I7LQZH26.js} +30 -7
- package/chunks/{askUserQuestion-3KAYLLMM.js → askUserQuestion-I5W5S3D6.js} +1 -1
- package/chunks/{bridge-MHWO5I5T.js → bridge-Q66BD62H.js} +23 -23
- package/chunks/{channel-management-service-NFRZXQFO.js → channel-management-service-TRTLQTSV.js} +4 -4
- package/chunks/{channel-settings-store-T7PMIHKC.js → channel-settings-store-R5STFWUW.js} +31 -31
- package/chunks/{channel-worker-group-O2BWK5F7.js → channel-worker-group-PIYPVCTF.js} +6 -6
- package/chunks/{channel-worker-manager-4WP7VJOD.js → channel-worker-manager-FQHEDTD2.js} +6 -6
- package/chunks/{channel-worker-supervisor-CCUXD6J5.js → channel-worker-supervisor-XJPZZ3VK.js} +3 -3
- package/chunks/{chunk-ZJ2LM2SI.js → chunk-2OR32P5M.js} +104 -33
- package/chunks/chunk-2Z3T52OC.js +82 -0
- package/chunks/{chunk-5FYGZ7E3.js → chunk-33MLFMCL.js} +2 -2
- package/chunks/{chunk-RH344FKI.js → chunk-3BTHHXXE.js} +1 -1
- package/chunks/{chunk-OFB36ZBA.js → chunk-3LPJ776W.js} +1 -1
- package/chunks/{chunk-TSLRORQR.js → chunk-43CI6YWJ.js} +1467 -1323
- package/chunks/{chunk-LTCI6ZOJ.js → chunk-45ROPFQY.js} +1 -1
- package/chunks/{chunk-W4LL5RZO.js → chunk-4ALNJDHL.js} +52 -13
- package/chunks/{chunk-RRCNEW2A.js → chunk-4BLTSTF6.js} +58 -4
- package/chunks/{chunk-3RMVM33U.js → chunk-4JKLPTV6.js} +5 -5
- package/chunks/{chunk-ZRVFHLLK.js → chunk-5DQ4YTIZ.js} +1 -1
- package/chunks/{chunk-AWDF462I.js → chunk-5GD7LYOH.js} +2 -2
- package/chunks/{chunk-HZS3JRQW.js → chunk-5VZFJTL2.js} +40 -2
- package/chunks/{chunk-537SQ2AI.js → chunk-5WC2ECUK.js} +104 -16
- package/chunks/{chunk-ZT3XUGSU.js → chunk-63ACHB2H.js} +86 -9
- package/chunks/{chunk-3K65MUKD.js → chunk-65I7S4Z3.js} +2 -1
- package/chunks/{chunk-REDVV5NC.js → chunk-6GRDHIVI.js} +7 -7
- package/chunks/{chunk-2LD5U7Q3.js → chunk-6YEOCHSE.js} +29 -1
- package/chunks/{chunk-C4NXRR7T.js → chunk-743XE7N7.js} +2 -2
- package/chunks/{chunk-I7UNCY24.js → chunk-7GZCCHJL.js} +3 -3
- package/chunks/{chunk-XX4MBBFW.js → chunk-7L35FKPF.js} +3 -3
- package/chunks/{chunk-GEV66YGE.js → chunk-7RXOEUFF.js} +1 -1
- package/chunks/{chunk-TXAEXF2B.js → chunk-BL6B2QS2.js} +21 -8
- package/chunks/{chunk-KAZWXVI3.js → chunk-CABDNUJ4.js} +2 -2
- package/chunks/{chunk-R7TKFIQO.js → chunk-CALNF3Z3.js} +1 -1
- package/chunks/{chunk-22QOQKG4.js → chunk-CG2PDIGD.js} +1 -1
- package/chunks/{chunk-MFCWL4LI.js → chunk-CPJRFFPH.js} +451 -396
- package/chunks/{chunk-LD53HMPV.js → chunk-CRZBDVP2.js} +1 -0
- package/chunks/{chunk-RSU3I6UL.js → chunk-DCPRCDSR.js} +1 -1
- package/chunks/{chunk-PLUAIHZO.js → chunk-DTB5BXRG.js} +6 -6
- package/chunks/{chunk-FWH4736Q.js → chunk-EA4NFWVG.js} +3 -3
- package/chunks/{chunk-AX23QSX3.js → chunk-EHTKOO6W.js} +4 -4
- package/chunks/{chunk-37SOBIA3.js → chunk-ERXNTINK.js} +1 -1
- package/chunks/{chunk-EGRFCIXD.js → chunk-EUXF6URV.js} +79 -18
- package/chunks/{chunk-F47DITLZ.js → chunk-FAWTMDX7.js} +14 -0
- package/chunks/{chunk-5JLQWQK6.js → chunk-FV4DM2M4.js} +2 -2
- package/chunks/{chunk-C7M445SS.js → chunk-G5QLLD53.js} +1 -1
- package/chunks/{chunk-5V4B3EWA.js → chunk-GM44O6F7.js} +1 -1
- package/chunks/{chunk-Z6DDPSGJ.js → chunk-GNY7B3CA.js} +1 -1
- package/chunks/{chunk-7PMKXGRP.js → chunk-GXIHBIHC.js} +66 -9
- package/chunks/{chunk-ERMAXPXA.js → chunk-HIXUUCGY.js} +187 -12
- package/chunks/{chunk-EJNYBDYC.js → chunk-HNLMYDQE.js} +1 -1
- package/chunks/{chunk-RCUWMVN3.js → chunk-HZ2HUXX7.js} +1 -1
- package/chunks/{chunk-SHX2HIE7.js → chunk-ISPBBKJN.js} +1 -1
- package/chunks/{chunk-QQGAR64U.js → chunk-IUJLW6ZI.js} +4 -4
- package/chunks/{chunk-IMWCUWQT.js → chunk-J3TJH52D.js} +1 -1
- package/chunks/{chunk-AIMZIXZM.js → chunk-J4ECGDA3.js} +5 -7
- package/chunks/{chunk-HPE4LEWX.js → chunk-JDPBJIKI.js} +1 -1
- package/chunks/{chunk-Y3C5COGI.js → chunk-L6ZME3W7.js} +1 -1
- package/chunks/{chunk-EPZWBYQI.js → chunk-LBKYQ33T.js} +8 -6
- package/chunks/{chunk-KTLT7VCX.js → chunk-LN3WBOKU.js} +2 -2
- package/chunks/{chunk-FXYNIZPW.js → chunk-LUVXLLMS.js} +51 -10
- package/chunks/{chunk-RQNAO42A.js → chunk-M6YLOETP.js} +1 -1
- package/chunks/{chunk-6KYWU726.js → chunk-M73KHGNR.js} +13 -66
- package/chunks/{chunk-ADJD4LZF.js → chunk-MA5OUNN6.js} +1 -1
- package/chunks/{chunk-SI6Q52UI.js → chunk-MMMA36MN.js} +3 -3
- package/chunks/{chunk-QW7BUOSI.js → chunk-MWEF5MUK.js} +20 -3
- package/chunks/{chunk-JOV46WGX.js → chunk-NB3NDQQK.js} +1 -1
- package/chunks/chunk-NOO4QFXM.js +171 -0
- package/chunks/{chunk-UTVIIA7N.js → chunk-NVS4Z6GT.js} +1 -1
- package/chunks/{chunk-VMFPZXRT.js → chunk-ODBNTMZW.js} +43 -31
- package/chunks/{chunk-UKADFFL2.js → chunk-OFVAS4AR.js} +1 -1
- package/chunks/{chunk-WQBR7LN5.js → chunk-OIPUQE3S.js} +1 -1
- package/chunks/{chunk-2C3XDBGL.js → chunk-ORREXWOM.js} +4 -4
- package/chunks/{chunk-RD3VPM4E.js → chunk-PQWM4SX2.js} +2 -2
- package/chunks/{chunk-Z6KFLEG7.js → chunk-PSPAM24S.js} +1 -0
- package/chunks/{chunk-RUMSY4ES.js → chunk-Q2F43WTJ.js} +8 -7
- package/chunks/{chunk-VYCJITND.js → chunk-QJAFSFYA.js} +1 -1
- package/chunks/{chunk-L36LLVA5.js → chunk-QLM7D7W3.js} +3 -3
- package/chunks/{chunk-NUQFUXOG.js → chunk-QTNCGZHQ.js} +2 -0
- package/chunks/{chunk-XNC2TCUO.js → chunk-QXXBW2G4.js} +4 -4
- package/chunks/{chunk-TDHVOZ65.js → chunk-R2266LQ5.js} +2 -2
- package/chunks/{chunk-QJVZLILI.js → chunk-R7OO56VZ.js} +1 -1
- package/chunks/{chunk-LYHYXJJ3.js → chunk-RDV4NLI3.js} +3 -3
- package/chunks/{chunk-733KQL63.js → chunk-RN6V5HKE.js} +3 -3
- package/chunks/{chunk-WLZRMF3C.js → chunk-RX3FYFCN.js} +353 -11
- package/chunks/{chunk-NXWYCSPL.js → chunk-SOA4HKRJ.js} +1 -1
- package/chunks/{chunk-ZNI3V2XA.js → chunk-TK4XHPKW.js} +2 -2
- package/chunks/{chunk-RGAQDQ3Z.js → chunk-UHUT4IDM.js} +18 -9
- package/chunks/{chunk-T7TP5UQL.js → chunk-ULY4ISY2.js} +4 -4
- package/chunks/{chunk-PMGWY6ZP.js → chunk-UULHYZ4W.js} +13 -10
- package/chunks/{chunk-BNWIX6BM.js → chunk-UXDVUFKU.js} +3 -3
- package/chunks/{chunk-HY3DXYZK.js → chunk-UYDQYDW2.js} +1 -1
- package/chunks/{chunk-YLFICBYK.js → chunk-VEQBVJYH.js} +3 -3
- package/chunks/{chunk-3K456UJF.js → chunk-VF6D6EGV.js} +12 -4
- package/chunks/{chunk-KP5QK3FB.js → chunk-VH764G6B.js} +397 -54
- package/chunks/{chunk-IGOIYZBG.js → chunk-VHPG7BH6.js} +2 -2
- package/chunks/{chunk-I67KJGM6.js → chunk-W3ONSAYO.js} +3 -3
- package/chunks/{chunk-SHK2SIR5.js → chunk-W673V2H3.js} +4 -4
- package/chunks/{chunk-C55CR5I4.js → chunk-W7PXLIZJ.js} +6 -6
- package/chunks/{chunk-OHOO527W.js → chunk-WG7BL3FY.js} +52 -2
- package/chunks/{chunk-B5FF3LRF.js → chunk-WIRYFL2L.js} +22 -15
- package/chunks/{chunk-P5Z7VD23.js → chunk-WZ4YULVF.js} +106 -39
- package/chunks/{chunk-WFXD5OZH.js → chunk-WZS3X663.js} +1 -1
- package/chunks/{chunk-HWZOOSEB.js → chunk-XAXTQURR.js} +3 -3
- package/chunks/{chunk-ANVC5CSK.js → chunk-XBLG564H.js} +10 -10
- package/chunks/{chunk-VU7O7CGQ.js → chunk-XDNFODER.js} +1 -1
- package/chunks/{chunk-SD7Y2PMC.js → chunk-XI7RST4D.js} +2 -2
- package/chunks/{chunk-65GHQ4FX.js → chunk-XVTCSVBK.js} +514 -47
- package/chunks/{chunk-4OCYWXKF.js → chunk-Y6ZWXM44.js} +3 -3
- package/chunks/{chunk-7IKXTGZT.js → chunk-YI2YCNSP.js} +1 -1
- package/chunks/{chunk-E4VX6LXB.js → chunk-YZTGGCEE.js} +10 -2
- package/chunks/{chunk-75UQFGFE.js → chunk-ZIPYCXQP.js} +1 -1
- package/chunks/{chunk-AUJOWIT5.js → chunk-ZUNWKOAP.js} +3 -3
- package/chunks/{config-utils-F4CFJ4MW.js → config-utils-37FHWPTP.js} +24 -24
- package/chunks/{contextCommand-OIIGGOMU.js → contextCommand-R4JUBV5N.js} +22 -22
- package/chunks/{core-runtime-JEHLOGMB.js → core-runtime-6U4OXU5C.js} +20 -20
- package/chunks/{create-sub-session-MVFBE5RA.js → create-sub-session-LLUYAGZN.js} +21 -21
- package/chunks/{daemon-LCUELM6E.js → daemon-UI6SQSBV.js} +1 -1
- package/chunks/{daemon-git-worktree-guard-5FTKLJOU.js → daemon-git-worktree-guard-O2UTNFJC.js} +20 -20
- package/chunks/{daemon-status-provider-P6A5MPMW.js → daemon-status-provider-7GMAKSTX.js} +27 -27
- package/chunks/{daemon-trust-policy-ZJ3NFYUO.js → daemon-trust-policy-VNP76VMO.js} +27 -27
- package/chunks/{daemon-trust-policy-monitor-6SDLEW7S.js → daemon-trust-policy-monitor-TD5O3BZA.js} +27 -27
- package/chunks/{deferred-core-runtime-DWOXIU5S.js → deferred-core-runtime-NJM63YJS.js} +20 -20
- package/chunks/{discovery-TUM3ZQ6U.js → discovery-XP4RMDUM.js} +4 -2
- package/chunks/{dist-NXW4DUUX.js → dist-24TCWK5H.js} +1 -1
- package/chunks/{dist-I74QLLQS.js → dist-5I4HLUTO.js} +1 -1
- package/chunks/{dist-XINEKB5A.js → dist-FDISN4AK.js} +1 -1
- package/chunks/{dist-VCAS67N5.js → dist-M4CBX53H.js} +1 -1
- package/chunks/{dist-AI25RVRA.js → dist-NQ2636VT.js} +1 -1
- package/chunks/{dist-3H3WODVS.js → dist-OR2ZQTXZ.js} +1 -1
- package/chunks/{dist-P6YWBITG.js → dist-STAGIFNB.js} +430 -51
- package/chunks/{dist-YNQU4CKC.js → dist-WZTUKIDR.js} +2 -2
- package/chunks/{dist-T4PRA5EZ.js → dist-XJ25G6OH.js} +1 -1
- package/chunks/{edit-WPVXLL3T.js → edit-GL7OA6RV.js} +13 -13
- package/chunks/{enter-worktree-5A6VW6BN.js → enter-worktree-YFTKHXHZ.js} +2 -2
- package/chunks/{enterPlanMode-JSODW7E2.js → enterPlanMode-VC4BCSZE.js} +13 -13
- package/chunks/{environment-5LLJ3I3W.js → environment-BI6IBAZJ.js} +23 -23
- package/chunks/{errors-IQT3YZEP.js → errors-D6G2ZM2R.js} +22 -22
- package/chunks/{exit-worktree-QV7E7KP6.js → exit-worktree-NF2XEMES.js} +3 -3
- package/chunks/{exitPlanMode-DDVFYNW4.js → exitPlanMode-DX446CA6.js} +13 -13
- package/chunks/{fast-path-PAUQQEVU.js → fast-path-MAYDLJIP.js} +3 -3
- package/chunks/{fast-path-settings-ISEJPRYE.js → fast-path-settings-SATXY3PD.js} +3 -3
- package/chunks/{glob-SQ7CTZ7F.js → glob-TVKRFY36.js} +13 -13
- package/chunks/{goal-tools-UWZRCLQB.js → goal-tools-CA6YANRN.js} +13 -13
- package/chunks/{handleAutoUpdate-RUPZZTSG.js → handleAutoUpdate-AW4ZAHON.js} +23 -23
- package/chunks/{i18n-SF5MPWEB.js → i18n-IH5CRAY7.js} +23 -21
- package/chunks/{image-gen-Q3RUTVKR.js → image-gen-XP4NNIYG.js} +4 -4
- package/chunks/{initializer-CK4WPYZG.js → initializer-UBR37ZNM.js} +27 -27
- package/chunks/{installationInfo-IRPQEYRF.js → installationInfo-Y52756EC.js} +20 -20
- package/chunks/{list-E3PS3EBJ.js → list-7V5JDZPO.js} +30 -30
- package/chunks/{llm-JQKBOYAF.js → llm-QDB6JVF5.js} +62 -62
- package/chunks/{llm-content-generator-2QWGBW42.js → llm-content-generator-EO6MZCEO.js} +23 -8
- package/chunks/{loadedSettingsAdapter-DGXGVYZS.js → loadedSettingsAdapter-I3YQKMC4.js} +27 -27
- package/chunks/{loggingContentGenerator-ZYURLJKK.js → loggingContentGenerator-MNXYUGDG.js} +14 -14
- package/chunks/{managed-npm-update-HTHR63EA.js → managed-npm-update-EA3EXPTO.js} +20 -20
- package/chunks/{mcp-I7G2AEWS.js → mcp-QTAJ544Y.js} +27 -27
- package/chunks/{monitor-4R76BCRZ.js → monitor-6FQKQOTP.js} +13 -13
- package/chunks/{nonInteractiveCli-24OQ3VP2.js → nonInteractiveCli-MRCTZL5X.js} +64 -61
- package/chunks/{notebook-edit-PPSH7FEX.js → notebook-edit-BQQCKI7K.js} +13 -13
- package/chunks/{openaiContentGenerator-K7V5EO7F.js → openaiContentGenerator-TTSKXNVH.js} +8 -8
- package/chunks/{pidfile-TGIUY2GG.js → pidfile-KPIS6RIT.js} +20 -20
- package/chunks/{processUtils-3USXUQWX.js → processUtils-ZCASPKK4.js} +2 -2
- package/chunks/{prompt-terminal-ledger-XHVZRXJI.js → prompt-terminal-ledger-D6HM6TV7.js} +21 -21
- package/chunks/{qwenContentGenerator-MPBOQB64.js → qwenContentGenerator-GGZEFLBD.js} +16 -16
- package/chunks/{qwenOAuth2-BS5D2LYV.js → qwenOAuth2-KX6LVYQ3.js} +4 -4
- package/chunks/{read-file-R256LDWQ.js → read-file-VE5GDFLP.js} +2 -2
- package/chunks/{resumeHistoryUtils-S43LTFHD.js → resumeHistoryUtils-HSSGMYDC.js} +23 -23
- package/chunks/{ripGrep-L7HPZ75Y.js → ripGrep-SEJE7AA6.js} +3 -3
- package/chunks/{run-qwen-serve-CTFL5R6U.js → run-qwen-serve-OJYVH7N6.js} +58 -60
- package/chunks/{runtime-FS5TL6P7.js → runtime-KGMQQFJD.js} +32 -32
- package/chunks/{scheduled-tasks-QXPV3Q35.js → scheduled-tasks-7H5HWHYD.js} +25 -25
- package/chunks/{scheduler-EXU5HMVK.js → scheduler-BE42AKDG.js} +22 -22
- package/chunks/{send-message-GQKXGMPI.js → send-message-AWKUDJBH.js} +1 -1
- package/chunks/{serve-ITJC7WNN.js → serve-KZVKYMSL.js} +27 -27
- package/chunks/{server-6JQY3PTU.js → server-PJRALPJQ.js} +1296 -822
- package/chunks/{session-PJDEKXD4.js → session-IHITXU2S.js} +63 -62
- package/chunks/{session-attachments-root-L37ORSST.js → session-attachments-root-GQ2TUI3Y.js} +20 -20
- package/chunks/{session-pr-refresh-WIFD52YL.js → session-pr-refresh-H43LULTE.js} +24 -24
- package/chunks/{settings-LO6J5SAZ.js → settings-RKEQQDFC.js} +26 -26
- package/chunks/{shell-ANAFVYGR.js → shell-6PJ444U5.js} +13 -13
- package/chunks/{skill-SHJWKSPH.js → skill-Q3UP7B5V.js} +2 -2
- package/chunks/{skill-settings-GX3XHZ5Q.js → skill-settings-LZR5YRRW.js} +26 -26
- package/chunks/{spawnChannel-WE42VBKM.js → spawnChannel-WM3DT2BF.js} +20 -20
- package/chunks/{standalone-update-CWDIKJRP.js → standalone-update-E5474IBI.js} +22 -22
- package/chunks/{start-opentui-ui-BBHGFOTF.js → start-opentui-ui-WLWZNQ2I.js} +1991 -986
- package/chunks/{startInteractiveUI-FQX7LUYP.js → startInteractiveUI-FBQSGWGO.js} +1119 -1478
- package/chunks/{team-create-WKTPCH6D.js → team-create-VIGUFUT4.js} +13 -13
- package/chunks/{team-plan-approval-Y23DL7WR.js → team-plan-approval-HQVZA3MD.js} +13 -13
- package/chunks/{terminal-image-renderer-B646HBDW.js → terminal-image-renderer-LUKNCOVM.js} +20 -20
- package/chunks/{theme-manager-BNWESY26.js → theme-manager-LOENKYLY.js} +20 -20
- package/chunks/{tool-search-PVQ5O5Y2.js → tool-search-ZIFAQCE2.js} +2 -2
- package/chunks/{total-session-admission-P5Z43KNW.js → total-session-admission-FUUJH3QH.js} +24 -24
- package/chunks/{trustedFolders-FH2LT2MZ.js → trustedFolders-C76KYROP.js} +21 -21
- package/chunks/{update-relaunch-WOWTKJSN.js → update-relaunch-4G2SRXKX.js} +5 -5
- package/chunks/{updateCheck-3MYFMM35.js → updateCheck-EIZIO7HI.js} +22 -22
- package/chunks/{useAutoAcceptIndicator-Q7ZRRRKO.js → useAutoAcceptIndicator-EAA6KSY4.js} +29 -29
- package/chunks/{validateNonInterActiveAuth-MYEWJX3G.js → validateNonInterActiveAuth-BRX22QCN.js} +59 -58
- package/chunks/{version-RO2FPO76.js → version-E56RU7PR.js} +1 -1
- package/chunks/{web-fetch-QAKY2LUA.js → web-fetch-AAUCD7RM.js} +5 -5
- package/chunks/{web-search-XA5Z4ZCD.js → web-search-HFUQF44Q.js} +18 -7
- package/chunks/{workflow-QFIOCMDM.js → workflow-3MABM53N.js} +15 -15
- package/chunks/{workspace-providers-status-B2UD7RAG.js → workspace-providers-status-2FRLBZ5I.js} +29 -29
- package/chunks/{workspace-registration-store-VZLRTI3Q.js → workspace-registration-store-YL7HLYYI.js} +1 -1
- package/chunks/{workspace-registry-GYOGG6TM.js → workspace-registry-BNRP2ELW.js} +24 -24
- package/chunks/{workspace-runtime-coordinator-7KRXGQ4V.js → workspace-runtime-coordinator-WKGF7VHS.js} +24 -24
- package/chunks/{workspace-service-DJEYGJE4.js → workspace-service-4MYO72MM.js} +31 -31
- package/chunks/{workspace-skills-status-MOKNESUC.js → workspace-skills-status-SU66TJLZ.js} +27 -27
- package/chunks/{workspace-trust-reconciler-AXOSUTQW.js → workspace-trust-reconciler-D5QT7WQB.js} +31 -31
- package/chunks/{write-file-QOYVHAKK.js → write-file-NVPQE2AZ.js} +14 -14
- package/chunks/{zoom-image-UCCLGFNC.js → zoom-image-RJHC66WG.js} +2 -2
- package/cli.js +13 -13
- package/export-transcript-document.js +126 -122
- package/package.json +3 -3
- package/web-shell/assets/{abnfDiagram-VCTEODGH-CTstZpXw.js → abnfDiagram-VCTEODGH-DHc6plZn.js} +1 -1
- package/web-shell/assets/{arc-DKW0mbPo.js → arc-BQ9m8TDV.js} +1 -1
- package/web-shell/assets/{architectureDiagram-5GKGNRK7-DkMpJ42t.js → architectureDiagram-5GKGNRK7-D5ap3oVB.js} +1 -1
- package/web-shell/assets/{blockDiagram-NRAW4CY4-7Cp1_4i3.js → blockDiagram-NRAW4CY4-BIbnyNph.js} +1 -1
- package/web-shell/assets/{c4Diagram-UCG6FXSJ-BfaoSlBK.js → c4Diagram-UCG6FXSJ-BRsdx_iG.js} +1 -1
- package/web-shell/assets/channel-uMMdTrYk.js +1 -0
- package/web-shell/assets/{chunk-2Q5K7J3B-_n1qzAio.js → chunk-2Q5K7J3B-3lf1fNlx.js} +1 -1
- package/web-shell/assets/{chunk-5VM5RSS4-0cira5ZV.js → chunk-5VM5RSS4-DP8VNRc4.js} +1 -1
- package/web-shell/assets/{chunk-F27PBJKO-DseRXSHC.js → chunk-F27PBJKO-DrohDmZ6.js} +1 -1
- package/web-shell/assets/{chunk-G27WJ6UU-BehQWin0.js → chunk-G27WJ6UU-UZ2QhSx6.js} +1 -1
- package/web-shell/assets/{chunk-JWPE2WC7-B5ftg1Bb.js → chunk-JWPE2WC7-BIMHVcZK.js} +1 -1
- package/web-shell/assets/{chunk-LCL6LL3I-D7rnbVdk.js → chunk-LCL6LL3I-izRxdSDd.js} +1 -1
- package/web-shell/assets/{chunk-POPQ4Y6H-2Bp-Orju.js → chunk-POPQ4Y6H-CXADD4PP.js} +1 -1
- package/web-shell/assets/{chunk-SVP7TREG-CD2goGva.js → chunk-SVP7TREG-B96d8Y_1.js} +1 -1
- package/web-shell/assets/{chunk-XXDRQBXY-DzQt-Rji.js → chunk-XXDRQBXY-CF2sVQpv.js} +1 -1
- package/web-shell/assets/classDiagram-DTDB5LWJ-DcY-26Ig.js +1 -0
- package/web-shell/assets/classDiagram-v2-JRS7N3AN-DcY-26Ig.js +1 -0
- package/web-shell/assets/{cose-bilkent-JH36ORCC-C-BZXSUn.js → cose-bilkent-JH36ORCC-CT6tXVAS.js} +1 -1
- package/web-shell/assets/csv-CX7rUNeC.svg +1 -0
- package/web-shell/assets/{cynefin-OW5HDTMX-BTcvowe1.js → cynefin-OW5HDTMX-X1NS4vtV.js} +1 -1
- package/web-shell/assets/{cynefinDiagram-5FMLGOSQ-BoUE6K81.js → cynefinDiagram-5FMLGOSQ-DNsKNOT4.js} +1 -1
- package/web-shell/assets/{dagre-3AP2YEHR-BHxy9xeB.js → dagre-3AP2YEHR-9-AHKqsb.js} +1 -1
- package/web-shell/assets/{diagram-S7CK7UJ4-DMiJIvDT.js → diagram-S7CK7UJ4-Bjgms7j6.js} +1 -1
- package/web-shell/assets/{diagram-UQ7AKVKN-DXV09Aes.js → diagram-UQ7AKVKN-h6bCprbE.js} +1 -1
- package/web-shell/assets/{diagram-VSXAHHWV-CocpRomV.js → diagram-VSXAHHWV-4SbQXVLt.js} +1 -1
- package/web-shell/assets/{diagram-VX7I27RA-DL7nqtb4.js → diagram-VX7I27RA-B5gPCzzB.js} +1 -1
- package/web-shell/assets/{diagram-Z3DM3KII-CPZ2Jux_.js → diagram-Z3DM3KII-DFJXIA3A.js} +1 -1
- package/web-shell/assets/{ebnfDiagram-PWID7BFC-BX-eVNsX.js → ebnfDiagram-PWID7BFC-FwyaU7VY.js} +1 -1
- package/web-shell/assets/{erDiagram-SSCWMZ5O-CPy_Ir6y.js → erDiagram-SSCWMZ5O-8vJQh2te.js} +1 -1
- package/web-shell/assets/{flowDiagram-A5DVABFB-eknAOte9.js → flowDiagram-A5DVABFB-BzA_1gMN.js} +1 -1
- package/web-shell/assets/{ganttDiagram-EL5Y4UJY-crAxw_t7.js → ganttDiagram-EL5Y4UJY-Co-ABbVX.js} +1 -1
- package/web-shell/assets/{gitGraphDiagram-WWUBYQGX-M29pa3Tc.js → gitGraphDiagram-WWUBYQGX-DW_FcyrX.js} +1 -1
- package/web-shell/assets/{index-C9R-iojE.js → index-BbMXfhNG.js} +1 -1
- package/web-shell/assets/{index-B4TLaxWs.js → index-Bu-rZoJ-.js} +462 -454
- package/web-shell/assets/index-CsPwZ1ut.css +36 -0
- package/web-shell/assets/{infoDiagram-RXCK75RN-XqspXdOU.js → infoDiagram-RXCK75RN-BEgfhUFN.js} +1 -1
- package/web-shell/assets/{ishikawaDiagram-5VMMS53U-C5KFS-7j.js → ishikawaDiagram-5VMMS53U-DCsMxQmc.js} +1 -1
- package/web-shell/assets/{journeyDiagram-EYS64GPL-Cc57LVRo.js → journeyDiagram-EYS64GPL-DyIEYoHz.js} +1 -1
- package/web-shell/assets/{kanban-definition-3QL26DDD-C81OG-AI.js → kanban-definition-3QL26DDD-CkxjqCNr.js} +1 -1
- package/web-shell/assets/{layout-CFVu37BB.js → layout-BEWc0Al9.js} +1 -1
- package/web-shell/assets/{linear-ChBxdtWf.js → linear-CNuNxirL.js} +1 -1
- package/web-shell/assets/{mermaid.core-CMLfue0w.js → mermaid.core-DZBre674.js} +6 -6
- package/web-shell/assets/{mindmap-definition-FBJOCRG2-DFsvJThp.js → mindmap-definition-FBJOCRG2-CpafFz_F.js} +1 -1
- package/web-shell/assets/{pegDiagram-XKGWAZYB-BzpRzM4F.js → pegDiagram-XKGWAZYB-DfZqk_dq.js} +1 -1
- package/web-shell/assets/{pieDiagram-E7YTZNPT-Cv0Kankl.js → pieDiagram-E7YTZNPT-S0UWXlgC.js} +1 -1
- package/web-shell/assets/{quadrantDiagram-AXDQQJYC-Bh2BJ3Ay.js → quadrantDiagram-AXDQQJYC-dd37_Ohj.js} +1 -1
- package/web-shell/assets/{railroadDiagram-O6MQD6OU-y8rNDdDS.js → railroadDiagram-O6MQD6OU-CH8NJZ7u.js} +1 -1
- package/web-shell/assets/{requirementDiagram-EFPCY7ZU-C0m2DKJ_.js → requirementDiagram-EFPCY7ZU-CFdqWYih.js} +1 -1
- package/web-shell/assets/{sankeyDiagram-P5KCCOFB-BzdGnSF4.js → sankeyDiagram-P5KCCOFB-CsddcEGD.js} +1 -1
- package/web-shell/assets/{sequenceDiagram-WJ2MYXX4-DPzAVmzz.js → sequenceDiagram-WJ2MYXX4-BZ270mGw.js} +1 -1
- package/web-shell/assets/{sizeCapture-X5ZJPWSS-LcHG28Zh.js → sizeCapture-X5ZJPWSS-CGaS4DBV.js} +1 -1
- package/web-shell/assets/{stateDiagram-HBIQ2CUA-C1Bzy3IT.js → stateDiagram-HBIQ2CUA-COpIzMu6.js} +1 -1
- package/web-shell/assets/stateDiagram-v2-4QOOHH4V-D6qEVAji.js +1 -0
- package/web-shell/assets/{swimlanes-XN3QIQJK-Bftk8V64.js → swimlanes-XN3QIQJK-CMF889m3.js} +1 -1
- package/web-shell/assets/swimlanesDiagram-VK2B7HYN-mem5Jj4m.js +8 -0
- package/web-shell/assets/{timeline-definition-24CTP7MA-BfXHcN1A.js → timeline-definition-24CTP7MA-BelnxYz5.js} +1 -1
- package/web-shell/assets/{vennDiagram-4TSXK5OY-DRSlI9-V.js → vennDiagram-4TSXK5OY-CU-NRqIB.js} +1 -1
- package/web-shell/assets/{wardleyDiagram-VM6X3IG4-CaLmqGau.js → wardleyDiagram-VM6X3IG4-CDNKqWh-.js} +1 -1
- package/web-shell/assets/{xychartDiagram-S5SC5T6Z-8lgUT6e8.js → xychartDiagram-S5SC5T6Z-CLqguL5D.js} +1 -1
- package/web-shell/index.html +2 -2
- package/chunks/chunk-3UMWOKJC.js +0 -78
- package/chunks/chunk-IQAFKVXS.js +0 -22
- package/web-shell/assets/channel-CQx7VSAp.js +0 -1
- package/web-shell/assets/classDiagram-DTDB5LWJ-C-Uz8hHk.js +0 -1
- package/web-shell/assets/classDiagram-v2-JRS7N3AN-C-Uz8hHk.js +0 -1
- package/web-shell/assets/index-CCrkEbzz.css +0 -36
- package/web-shell/assets/stateDiagram-v2-4QOOHH4V-LuuL5byY.js +0 -1
- package/web-shell/assets/swimlanesDiagram-VK2B7HYN-COmnNq8s.js +0 -8
|
@@ -698,6 +698,7 @@ var AcpBridge = class extends EventEmitter {
|
|
|
698
698
|
channelLoopToolHandlers = [];
|
|
699
699
|
knownSessionIds = /* @__PURE__ */ new Set();
|
|
700
700
|
sessionBindingTokens = /* @__PURE__ */ new Map();
|
|
701
|
+
toolCallKindsBySession = /* @__PURE__ */ new Map();
|
|
701
702
|
channelLoopMcpRegistered = false;
|
|
702
703
|
channelLoopMcpRegistration = null;
|
|
703
704
|
pendingPermissions = /* @__PURE__ */ new Map();
|
|
@@ -743,6 +744,7 @@ var AcpBridge = class extends EventEmitter {
|
|
|
743
744
|
this.resolvePendingPermissions();
|
|
744
745
|
this.knownSessionIds.clear();
|
|
745
746
|
this.sessionBindingTokens.clear();
|
|
747
|
+
this.toolCallKindsBySession.clear();
|
|
746
748
|
this.connection = null;
|
|
747
749
|
this.child = null;
|
|
748
750
|
this.emit("disconnected", code, signal);
|
|
@@ -906,6 +908,7 @@ var AcpBridge = class extends EventEmitter {
|
|
|
906
908
|
if (!this.knownSessionIds.delete(sessionId))
|
|
907
909
|
return;
|
|
908
910
|
this.sessionBindingTokens.delete(sessionId);
|
|
911
|
+
this.toolCallKindsBySession.delete(sessionId);
|
|
909
912
|
this.resolvePendingPermissions(sessionId);
|
|
910
913
|
const conn = this.connection;
|
|
911
914
|
if (!conn || !this.isConnected)
|
|
@@ -930,6 +933,7 @@ var AcpBridge = class extends EventEmitter {
|
|
|
930
933
|
this.resolvePendingPermissions();
|
|
931
934
|
this.knownSessionIds.clear();
|
|
932
935
|
this.sessionBindingTokens.clear();
|
|
936
|
+
this.toolCallKindsBySession.clear();
|
|
933
937
|
if (this.child) {
|
|
934
938
|
this.child.kill();
|
|
935
939
|
this.child = null;
|
|
@@ -968,19 +972,44 @@ var AcpBridge = class extends EventEmitter {
|
|
|
968
972
|
}
|
|
969
973
|
break;
|
|
970
974
|
}
|
|
971
|
-
case "tool_call":
|
|
975
|
+
case "tool_call":
|
|
976
|
+
case "tool_call_update": {
|
|
977
|
+
const toolCallId = update["toolCallId"] || "";
|
|
978
|
+
if (!toolCallId)
|
|
979
|
+
break;
|
|
980
|
+
const explicitKind = typeof update["kind"] === "string" ? update["kind"] : "";
|
|
981
|
+
const meta = update["_meta"];
|
|
982
|
+
if (type === "tool_call_update" && !explicitKind && update["status"] === "in_progress" && (meta?.["shellProgress"] !== void 0 || meta?.["subagentProgress"] === true)) {
|
|
983
|
+
break;
|
|
984
|
+
}
|
|
985
|
+
let sessionKinds = this.toolCallKindsBySession.get(sessionId);
|
|
986
|
+
const kind = explicitKind || sessionKinds?.get(toolCallId);
|
|
987
|
+
if (!kind)
|
|
988
|
+
break;
|
|
989
|
+
if (type === "tool_call" || explicitKind) {
|
|
990
|
+
const kinds = sessionKinds ?? /* @__PURE__ */ new Map();
|
|
991
|
+
kinds.set(toolCallId, kind);
|
|
992
|
+
this.toolCallKindsBySession.set(sessionId, kinds);
|
|
993
|
+
sessionKinds = kinds;
|
|
994
|
+
}
|
|
972
995
|
const event = {
|
|
973
996
|
sessionId,
|
|
974
|
-
toolCallId
|
|
975
|
-
kind
|
|
997
|
+
toolCallId,
|
|
998
|
+
kind,
|
|
976
999
|
title: update["title"] || "",
|
|
977
1000
|
status: update["status"] || "pending",
|
|
978
1001
|
rawInput: update["rawInput"]
|
|
979
1002
|
};
|
|
980
|
-
if (event.status === "pending" || event.status === "in_progress") {
|
|
1003
|
+
if (type === "tool_call" && (event.status === "pending" || event.status === "in_progress")) {
|
|
981
1004
|
this.emitResponseBoundary(sessionId);
|
|
982
1005
|
}
|
|
983
1006
|
this.emit("toolCall", event);
|
|
1007
|
+
if (event.status === "completed" || event.status === "failed") {
|
|
1008
|
+
sessionKinds?.delete(toolCallId);
|
|
1009
|
+
if (sessionKinds?.size === 0) {
|
|
1010
|
+
this.toolCallKindsBySession.delete(sessionId);
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
984
1013
|
break;
|
|
985
1014
|
}
|
|
986
1015
|
case "plan": {
|
|
@@ -1763,6 +1792,49 @@ init_esbuild_shims();
|
|
|
1763
1792
|
import { chmodSync as chmodSync2, existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync3, renameSync as renameSync3, rmSync, unlinkSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
1764
1793
|
import { dirname as dirname3, isAbsolute, join as join4 } from "node:path";
|
|
1765
1794
|
import process2 from "node:process";
|
|
1795
|
+
function readDaemonHttpErrorCode(error) {
|
|
1796
|
+
let current = error;
|
|
1797
|
+
for (let depth = 0; depth < 5; depth++) {
|
|
1798
|
+
if (typeof current !== "object" && typeof current !== "function" || current === null) {
|
|
1799
|
+
return void 0;
|
|
1800
|
+
}
|
|
1801
|
+
const record = current;
|
|
1802
|
+
if (record["name"] === "DaemonHttpError" && record["status"] === 409) {
|
|
1803
|
+
const body = record["body"];
|
|
1804
|
+
if (typeof body === "object" && body !== null && !Array.isArray(body)) {
|
|
1805
|
+
const code = body["code"];
|
|
1806
|
+
if (typeof code === "string" && code.length > 0)
|
|
1807
|
+
return code;
|
|
1808
|
+
}
|
|
1809
|
+
}
|
|
1810
|
+
current = record["cause"];
|
|
1811
|
+
}
|
|
1812
|
+
return void 0;
|
|
1813
|
+
}
|
|
1814
|
+
__name(readDaemonHttpErrorCode, "readDaemonHttpErrorCode");
|
|
1815
|
+
function readSupersededReplacementId(error) {
|
|
1816
|
+
let current = error;
|
|
1817
|
+
for (let depth = 0; depth < 5; depth++) {
|
|
1818
|
+
if (typeof current !== "object" && typeof current !== "function" || current === null) {
|
|
1819
|
+
return void 0;
|
|
1820
|
+
}
|
|
1821
|
+
const record = current;
|
|
1822
|
+
if (record["name"] === "DaemonHttpError" && record["status"] === 409) {
|
|
1823
|
+
const body = record["body"];
|
|
1824
|
+
if (typeof body === "object" && body !== null && !Array.isArray(body)) {
|
|
1825
|
+
const typedBody = body;
|
|
1826
|
+
if (typedBody["code"] !== "worktree_session_superseded") {
|
|
1827
|
+
return void 0;
|
|
1828
|
+
}
|
|
1829
|
+
const replacement = typedBody["replacementSessionId"];
|
|
1830
|
+
return typeof replacement === "string" && replacement.length > 0 ? replacement : void 0;
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
current = record["cause"];
|
|
1834
|
+
}
|
|
1835
|
+
return void 0;
|
|
1836
|
+
}
|
|
1837
|
+
__name(readSupersededReplacementId, "readSupersededReplacementId");
|
|
1766
1838
|
var SessionRouter = class {
|
|
1767
1839
|
static {
|
|
1768
1840
|
__name(this, "SessionRouter");
|
|
@@ -1773,9 +1845,11 @@ var SessionRouter = class {
|
|
|
1773
1845
|
// session ID → target
|
|
1774
1846
|
toCwd = /* @__PURE__ */ new Map();
|
|
1775
1847
|
// session ID → cwd
|
|
1848
|
+
toManagedMeta = /* @__PURE__ */ new Map();
|
|
1776
1849
|
creatingSessions = /* @__PURE__ */ new Map();
|
|
1777
1850
|
sessionLoadWindows = /* @__PURE__ */ new Set();
|
|
1778
1851
|
liveSessionIds = /* @__PURE__ */ new Set();
|
|
1852
|
+
staleBridgeBindings = /* @__PURE__ */ new Set();
|
|
1779
1853
|
routeTokens = /* @__PURE__ */ new Map();
|
|
1780
1854
|
lifecycleGeneration = 0;
|
|
1781
1855
|
bridge;
|
|
@@ -1797,6 +1871,7 @@ var SessionRouter = class {
|
|
|
1797
1871
|
setBridge(bridge) {
|
|
1798
1872
|
this.bridge = bridge;
|
|
1799
1873
|
this.liveSessionIds.clear();
|
|
1874
|
+
this.staleBridgeBindings.clear();
|
|
1800
1875
|
}
|
|
1801
1876
|
/** Set scope override for a specific channel. */
|
|
1802
1877
|
setChannelScope(channelName, scope) {
|
|
@@ -2072,12 +2147,12 @@ var SessionRouter = class {
|
|
|
2072
2147
|
this.endSessionLoad(loadWindow);
|
|
2073
2148
|
}
|
|
2074
2149
|
}
|
|
2075
|
-
async loadManagedSession(sessionId, target, workspaceCwd, expectedCwd = workspaceCwd, isolation = "shared") {
|
|
2150
|
+
async loadManagedSession(sessionId, target, workspaceCwd, expectedCwd = workspaceCwd, isolation = "shared", allowSupersededRedirect = true) {
|
|
2076
2151
|
if (this.liveSessionIds.has(sessionId)) {
|
|
2077
2152
|
const actualCwd = this.validateManagedSessionIdentity(this.bridge, sessionId, workspaceCwd, expectedCwd, isolation);
|
|
2078
2153
|
this.toTarget.set(sessionId, target);
|
|
2079
2154
|
this.toCwd.set(sessionId, actualCwd);
|
|
2080
|
-
return { loaded: false };
|
|
2155
|
+
return { loaded: false, sessionId };
|
|
2081
2156
|
}
|
|
2082
2157
|
const loadWindow = this.beginSessionLoad();
|
|
2083
2158
|
const lifecycleGeneration = this.lifecycleGeneration;
|
|
@@ -2085,6 +2160,9 @@ var SessionRouter = class {
|
|
|
2085
2160
|
const bindingToken = {};
|
|
2086
2161
|
let loadedSessionId;
|
|
2087
2162
|
try {
|
|
2163
|
+
if (this.staleBridgeBindings.delete(sessionId)) {
|
|
2164
|
+
await bridge.discardSession?.(sessionId).catch(() => void 0);
|
|
2165
|
+
}
|
|
2088
2166
|
loadedSessionId = await bridge.loadSession(sessionId, workspaceCwd, this.sessionOptions(target.channelName), bindingToken);
|
|
2089
2167
|
if (lifecycleGeneration !== this.lifecycleGeneration || bridge !== this.bridge) {
|
|
2090
2168
|
this.scheduleManagedDiscard(bridge, loadedSessionId, bindingToken);
|
|
@@ -2104,16 +2182,105 @@ var SessionRouter = class {
|
|
|
2104
2182
|
this.toTarget.set(sessionId, target);
|
|
2105
2183
|
this.toCwd.set(sessionId, actualCwd);
|
|
2106
2184
|
this.liveSessionIds.add(sessionId);
|
|
2107
|
-
return { loaded: true };
|
|
2185
|
+
return { loaded: true, sessionId };
|
|
2108
2186
|
} catch (error) {
|
|
2109
2187
|
if (loadedSessionId) {
|
|
2110
2188
|
await bridge.discardSession?.(loadedSessionId, bindingToken).catch(() => void 0);
|
|
2189
|
+
throw error;
|
|
2190
|
+
}
|
|
2191
|
+
const replacementId = readSupersededReplacementId(error);
|
|
2192
|
+
if (allowSupersededRedirect && replacementId !== void 0 && replacementId !== sessionId) {
|
|
2193
|
+
const redirected = await this.loadManagedSession(replacementId, target, workspaceCwd, expectedCwd, isolation, false);
|
|
2194
|
+
this.healSupersededRoute(sessionId, redirected.sessionId);
|
|
2195
|
+
return {
|
|
2196
|
+
loaded: redirected.loaded,
|
|
2197
|
+
sessionId: redirected.sessionId,
|
|
2198
|
+
redirectedFrom: sessionId
|
|
2199
|
+
};
|
|
2111
2200
|
}
|
|
2112
2201
|
throw error;
|
|
2113
2202
|
} finally {
|
|
2114
2203
|
this.endSessionLoad(loadWindow);
|
|
2115
2204
|
}
|
|
2116
2205
|
}
|
|
2206
|
+
/**
|
|
2207
|
+
* Remap every route that still points at a superseded session to its
|
|
2208
|
+
* replacement, and drop the superseded id's bookkeeping. The manager's
|
|
2209
|
+
* own task registry heals separately (it owns the task-name mapping).
|
|
2210
|
+
*/
|
|
2211
|
+
healSupersededRoute(oldSessionId, newSessionId) {
|
|
2212
|
+
let changed = false;
|
|
2213
|
+
for (const [key, mappedSessionId] of this.toSession) {
|
|
2214
|
+
if (mappedSessionId !== oldSessionId)
|
|
2215
|
+
continue;
|
|
2216
|
+
this.invalidateRouteOperation(key);
|
|
2217
|
+
this.toSession.set(key, newSessionId);
|
|
2218
|
+
changed = true;
|
|
2219
|
+
}
|
|
2220
|
+
changed = this.toTarget.delete(oldSessionId) || changed;
|
|
2221
|
+
changed = this.toCwd.delete(oldSessionId) || changed;
|
|
2222
|
+
const managedMeta = this.toManagedMeta.get(oldSessionId);
|
|
2223
|
+
if (managedMeta !== void 0) {
|
|
2224
|
+
this.toManagedMeta.set(newSessionId, managedMeta);
|
|
2225
|
+
this.toManagedMeta.delete(oldSessionId);
|
|
2226
|
+
changed = true;
|
|
2227
|
+
}
|
|
2228
|
+
this.liveSessionIds.delete(oldSessionId);
|
|
2229
|
+
this.staleBridgeBindings.delete(oldSessionId);
|
|
2230
|
+
if (changed)
|
|
2231
|
+
this.persist();
|
|
2232
|
+
}
|
|
2233
|
+
/**
|
|
2234
|
+
* Worktree reset: transfer the task session's checkout ownership to a
|
|
2235
|
+
* fresh replacement session on the daemon, validate the replacement's
|
|
2236
|
+
* attestation, and route it. The task registry itself is swapped by the
|
|
2237
|
+
* named-session manager (it owns the task-name mapping); this call only
|
|
2238
|
+
* wires the router's session bookkeeping.
|
|
2239
|
+
*
|
|
2240
|
+
* A failure past the daemon's marker flip rolls nothing back: the
|
|
2241
|
+
* registry keeps pointing at the old id, and the next selection's load
|
|
2242
|
+
* heals it through the superseded redirect — the failed reset drops the
|
|
2243
|
+
* old id from the live set so that load consults the daemon again.
|
|
2244
|
+
*/
|
|
2245
|
+
async replaceManagedWorktreeSession(sessionId, target, workspaceCwd, expectedCwd) {
|
|
2246
|
+
const bridge = this.bridge;
|
|
2247
|
+
if (!bridge.resetWorktreeSession) {
|
|
2248
|
+
throw new Error("Worktree reset is not supported by this bridge");
|
|
2249
|
+
}
|
|
2250
|
+
const loadWindow = this.beginSessionLoad();
|
|
2251
|
+
const lifecycleGeneration = this.lifecycleGeneration;
|
|
2252
|
+
const bindingToken = {};
|
|
2253
|
+
let replacementId;
|
|
2254
|
+
try {
|
|
2255
|
+
replacementId = await bridge.resetWorktreeSession(sessionId, workspaceCwd, this.sessionOptions(target.channelName), bindingToken);
|
|
2256
|
+
if (lifecycleGeneration !== this.lifecycleGeneration || bridge !== this.bridge) {
|
|
2257
|
+
this.scheduleManagedDiscard(bridge, replacementId, bindingToken);
|
|
2258
|
+
throw new Error("Managed session reset was invalidated");
|
|
2259
|
+
}
|
|
2260
|
+
if (typeof replacementId !== "string" || replacementId.length === 0) {
|
|
2261
|
+
throw new Error("Invalid session ID from bridge");
|
|
2262
|
+
}
|
|
2263
|
+
if (loadWindow.delete(replacementId)) {
|
|
2264
|
+
await bridge.discardSession?.(replacementId, bindingToken);
|
|
2265
|
+
throw new Error(`Managed session ${replacementId} died before reset completed`);
|
|
2266
|
+
}
|
|
2267
|
+
const actualCwd = this.validateManagedSessionIdentity(bridge, replacementId, workspaceCwd, expectedCwd, "worktree");
|
|
2268
|
+
this.toTarget.set(replacementId, target);
|
|
2269
|
+
this.toCwd.set(replacementId, actualCwd);
|
|
2270
|
+
this.liveSessionIds.add(replacementId);
|
|
2271
|
+
this.forgetManagedSession(sessionId);
|
|
2272
|
+
return replacementId;
|
|
2273
|
+
} catch (error) {
|
|
2274
|
+
if (replacementId !== void 0) {
|
|
2275
|
+
await bridge.discardSession?.(replacementId, bindingToken).catch(() => void 0);
|
|
2276
|
+
}
|
|
2277
|
+
this.staleBridgeBindings.add(sessionId);
|
|
2278
|
+
this.liveSessionIds.delete(sessionId);
|
|
2279
|
+
throw error;
|
|
2280
|
+
} finally {
|
|
2281
|
+
this.endSessionLoad(loadWindow);
|
|
2282
|
+
}
|
|
2283
|
+
}
|
|
2117
2284
|
validateManagedSessionIdentity(bridge, sessionId, workspaceCwd, expectedCwd, isolation) {
|
|
2118
2285
|
if (isolation === "shared") {
|
|
2119
2286
|
return workspaceCwd;
|
|
@@ -2126,10 +2293,26 @@ var SessionRouter = class {
|
|
|
2126
2293
|
}
|
|
2127
2294
|
return canonicalWorktree;
|
|
2128
2295
|
}
|
|
2129
|
-
activateManagedSession(sessionId, target, cwd) {
|
|
2296
|
+
activateManagedSession(sessionId, target, cwd, managed) {
|
|
2297
|
+
if (managed?.isolation === "worktree" && !managed.workspaceCwd) {
|
|
2298
|
+
throw new Error("A worktree managed session requires its workspace cwd.");
|
|
2299
|
+
}
|
|
2300
|
+
const previousMeta = this.toManagedMeta.get(sessionId);
|
|
2301
|
+
if (managed?.isolation === "worktree") {
|
|
2302
|
+
this.toManagedMeta.set(sessionId, {
|
|
2303
|
+
isolation: "worktree",
|
|
2304
|
+
workspaceCwd: managed.workspaceCwd
|
|
2305
|
+
});
|
|
2306
|
+
} else {
|
|
2307
|
+
this.toManagedMeta.delete(sessionId);
|
|
2308
|
+
}
|
|
2309
|
+
const metaChanged = managed?.isolation === "worktree" ? previousMeta?.workspaceCwd !== managed.workspaceCwd : previousMeta !== void 0;
|
|
2130
2310
|
const key = this.routingKey(target.channelName, target.senderId, target.chatId, target.threadId);
|
|
2131
|
-
if (this.toSession.get(key) === sessionId)
|
|
2311
|
+
if (this.toSession.get(key) === sessionId) {
|
|
2312
|
+
if (metaChanged)
|
|
2313
|
+
this.persist();
|
|
2132
2314
|
return;
|
|
2315
|
+
}
|
|
2133
2316
|
this.invalidateRouteOperation(key);
|
|
2134
2317
|
this.toSession.set(key, sessionId);
|
|
2135
2318
|
this.toTarget.set(sessionId, target);
|
|
@@ -2147,17 +2330,18 @@ var SessionRouter = class {
|
|
|
2147
2330
|
}
|
|
2148
2331
|
changed = this.toTarget.delete(sessionId) || changed;
|
|
2149
2332
|
changed = this.toCwd.delete(sessionId) || changed;
|
|
2333
|
+
changed = this.toManagedMeta.delete(sessionId) || changed;
|
|
2150
2334
|
changed = this.liveSessionIds.delete(sessionId) || changed;
|
|
2335
|
+
this.staleBridgeBindings.delete(sessionId);
|
|
2151
2336
|
if (changed)
|
|
2152
2337
|
this.persist();
|
|
2153
2338
|
}
|
|
2154
2339
|
async detachManagedSession(sessionId) {
|
|
2155
2340
|
try {
|
|
2156
|
-
if (this.
|
|
2157
|
-
if (!this.bridge.discardSession) {
|
|
2158
|
-
throw new Error("Managed session detach is not supported");
|
|
2159
|
-
}
|
|
2341
|
+
if (this.bridge.discardSession) {
|
|
2160
2342
|
await this.bridge.discardSession(sessionId);
|
|
2343
|
+
} else if (this.liveSessionIds.has(sessionId)) {
|
|
2344
|
+
throw new Error("Managed session detach is not supported");
|
|
2161
2345
|
}
|
|
2162
2346
|
} finally {
|
|
2163
2347
|
this.forgetManagedSession(sessionId);
|
|
@@ -2213,6 +2397,9 @@ var SessionRouter = class {
|
|
|
2213
2397
|
if (this.toCwd.delete(sessionId)) {
|
|
2214
2398
|
removed = true;
|
|
2215
2399
|
}
|
|
2400
|
+
if (this.toManagedMeta.delete(sessionId)) {
|
|
2401
|
+
removed = true;
|
|
2402
|
+
}
|
|
2216
2403
|
this.liveSessionIds.delete(sessionId);
|
|
2217
2404
|
if (!removed && this.sessionLoadWindows.size > 0) {
|
|
2218
2405
|
for (const loadWindow of this.sessionLoadWindows) {
|
|
@@ -2242,6 +2429,7 @@ var SessionRouter = class {
|
|
|
2242
2429
|
this.toSession.delete(key);
|
|
2243
2430
|
this.toTarget.delete(sessionId);
|
|
2244
2431
|
this.toCwd.delete(sessionId);
|
|
2432
|
+
this.toManagedMeta.delete(sessionId);
|
|
2245
2433
|
this.liveSessionIds.delete(sessionId);
|
|
2246
2434
|
return sessionId;
|
|
2247
2435
|
}
|
|
@@ -2278,6 +2466,12 @@ var SessionRouter = class {
|
|
|
2278
2466
|
this.toSession.set(key, entry.sessionId);
|
|
2279
2467
|
this.toTarget.set(entry.sessionId, entry.target);
|
|
2280
2468
|
this.toCwd.set(entry.sessionId, entry.cwd);
|
|
2469
|
+
if (entry.isolation === "worktree" && entry.workspaceCwd !== void 0) {
|
|
2470
|
+
this.toManagedMeta.set(entry.sessionId, {
|
|
2471
|
+
isolation: "worktree",
|
|
2472
|
+
workspaceCwd: entry.workspaceCwd
|
|
2473
|
+
});
|
|
2474
|
+
}
|
|
2281
2475
|
restored++;
|
|
2282
2476
|
}
|
|
2283
2477
|
if (persisted.dropped > 0)
|
|
@@ -2321,6 +2515,32 @@ var SessionRouter = class {
|
|
|
2321
2515
|
try {
|
|
2322
2516
|
this.assertOperationCurrent(operation);
|
|
2323
2517
|
const options = this.sessionOptions(entry.target.channelName);
|
|
2518
|
+
if (entry.isolation === "worktree" && entry.workspaceCwd !== void 0) {
|
|
2519
|
+
const managed = await this.loadManagedSession(entry.sessionId, entry.target, entry.workspaceCwd, entry.cwd, "worktree");
|
|
2520
|
+
try {
|
|
2521
|
+
this.assertOperationCurrent(operation);
|
|
2522
|
+
} catch (error) {
|
|
2523
|
+
if (![...this.toSession.values()].includes(managed.sessionId)) {
|
|
2524
|
+
void this.bridge.discardSession?.(managed.sessionId).catch(() => void 0);
|
|
2525
|
+
this.toTarget.delete(managed.sessionId);
|
|
2526
|
+
this.toCwd.delete(managed.sessionId);
|
|
2527
|
+
this.toManagedMeta.delete(managed.sessionId);
|
|
2528
|
+
this.liveSessionIds.delete(managed.sessionId);
|
|
2529
|
+
}
|
|
2530
|
+
throw error;
|
|
2531
|
+
}
|
|
2532
|
+
this.toSession.set(key, managed.sessionId);
|
|
2533
|
+
this.toManagedMeta.set(managed.sessionId, {
|
|
2534
|
+
isolation: "worktree",
|
|
2535
|
+
workspaceCwd: entry.workspaceCwd
|
|
2536
|
+
});
|
|
2537
|
+
reservation.resolve(managed.sessionId);
|
|
2538
|
+
if (managed.sessionId !== entry.sessionId) {
|
|
2539
|
+
changed = true;
|
|
2540
|
+
}
|
|
2541
|
+
restored++;
|
|
2542
|
+
continue;
|
|
2543
|
+
}
|
|
2324
2544
|
const sessionId = await this.bridge.loadSession(entry.sessionId, entry.cwd, options, operation);
|
|
2325
2545
|
try {
|
|
2326
2546
|
this.assertOperationCurrent(operation);
|
|
@@ -2373,9 +2593,11 @@ var SessionRouter = class {
|
|
|
2373
2593
|
this.toSession.clear();
|
|
2374
2594
|
this.toTarget.clear();
|
|
2375
2595
|
this.toCwd.clear();
|
|
2596
|
+
this.toManagedMeta.clear();
|
|
2376
2597
|
this.creatingSessions.clear();
|
|
2377
2598
|
this.sessionLoadWindows.clear();
|
|
2378
2599
|
this.liveSessionIds.clear();
|
|
2600
|
+
this.staleBridgeBindings.clear();
|
|
2379
2601
|
this.routeTokens.clear();
|
|
2380
2602
|
}
|
|
2381
2603
|
/** Clear in-memory state and delete persist file. Used on clean shutdown. */
|
|
@@ -2433,7 +2655,12 @@ var SessionRouter = class {
|
|
|
2433
2655
|
if (typeof target !== "object" || target === null)
|
|
2434
2656
|
return false;
|
|
2435
2657
|
const typedTarget = target;
|
|
2436
|
-
|
|
2658
|
+
const wellFormed = typeof entry["sessionId"] === "string" && entry["sessionId"].length > 0 && typeof entry["cwd"] === "string" && entry["cwd"].length > 0 && typeof typedTarget["channelName"] === "string" && typeof typedTarget["senderId"] === "string" && typeof typedTarget["chatId"] === "string" && (typedTarget["threadId"] === void 0 || typeof typedTarget["threadId"] === "string") && (typedTarget["isGroup"] === void 0 || typeof typedTarget["isGroup"] === "boolean");
|
|
2659
|
+
if (!wellFormed)
|
|
2660
|
+
return false;
|
|
2661
|
+
if (entry["isolation"] === void 0)
|
|
2662
|
+
return true;
|
|
2663
|
+
return entry["isolation"] === "worktree" && typeof entry["workspaceCwd"] === "string" && entry["workspaceCwd"].length > 0;
|
|
2437
2664
|
}
|
|
2438
2665
|
persist() {
|
|
2439
2666
|
if (!this.persistPath)
|
|
@@ -2446,7 +2673,8 @@ var SessionRouter = class {
|
|
|
2446
2673
|
data[key] = {
|
|
2447
2674
|
sessionId,
|
|
2448
2675
|
target,
|
|
2449
|
-
cwd: this.toCwd.get(sessionId) ?? this.defaultCwd
|
|
2676
|
+
cwd: this.toCwd.get(sessionId) ?? this.defaultCwd,
|
|
2677
|
+
...this.toManagedMeta.get(sessionId) ?? {}
|
|
2450
2678
|
};
|
|
2451
2679
|
}
|
|
2452
2680
|
const dir = dirname3(this.persistPath);
|
|
@@ -2594,6 +2822,16 @@ import process3 from "node:process";
|
|
|
2594
2822
|
var REGISTRY_VERSION = 1;
|
|
2595
2823
|
var MAX_OPEN_TASKS = 8;
|
|
2596
2824
|
var TASK_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9_-]{0,31}$/;
|
|
2825
|
+
var NamedSessionTaskError = class extends Error {
|
|
2826
|
+
static {
|
|
2827
|
+
__name(this, "NamedSessionTaskError");
|
|
2828
|
+
}
|
|
2829
|
+
taskName;
|
|
2830
|
+
constructor(message, taskName, options) {
|
|
2831
|
+
super(message, options);
|
|
2832
|
+
this.taskName = taskName;
|
|
2833
|
+
}
|
|
2834
|
+
};
|
|
2597
2835
|
var NamedSessionManager = class {
|
|
2598
2836
|
static {
|
|
2599
2837
|
__name(this, "NamedSessionManager");
|
|
@@ -2608,6 +2846,12 @@ var NamedSessionManager = class {
|
|
|
2608
2846
|
registry;
|
|
2609
2847
|
taskBySessionId;
|
|
2610
2848
|
ownerOperations = /* @__PURE__ */ new Map();
|
|
2849
|
+
/**
|
|
2850
|
+
* Superseded session id → the replacement its task moved onto. A queued turn
|
|
2851
|
+
* stays bound to the id it reserved, so the reservation lookup has to follow
|
|
2852
|
+
* the task or every turn after the first one is stranded on the old id.
|
|
2853
|
+
*/
|
|
2854
|
+
supersededSessionIds = /* @__PURE__ */ new Map();
|
|
2611
2855
|
constructor(options) {
|
|
2612
2856
|
this.channelName = options.channelName;
|
|
2613
2857
|
this.cwd = options.cwd;
|
|
@@ -2706,14 +2950,20 @@ var NamedSessionManager = class {
|
|
|
2706
2950
|
return task ? this.selection(owner, task) : void 0;
|
|
2707
2951
|
});
|
|
2708
2952
|
}
|
|
2953
|
+
/**
|
|
2954
|
+
* Reload a task a queued turn is already bound to. Resolves to the session
|
|
2955
|
+
* id the caller must dispatch on — the healed replacement when a superseded
|
|
2956
|
+
* redirect fired — or undefined when the task is no longer reservable.
|
|
2957
|
+
*/
|
|
2709
2958
|
resumeReserved(input, sessionId) {
|
|
2710
2959
|
return this.withOwnerLock(input, async () => {
|
|
2711
2960
|
const owner = await this.ensureOwner(input, false);
|
|
2712
|
-
const
|
|
2961
|
+
const reservedSessionId = this.supersededSessionIds.get(sessionId) ?? sessionId;
|
|
2962
|
+
const task = owner?.tasks.find((candidate) => candidate.sessionId === reservedSessionId && candidate.status === "open");
|
|
2713
2963
|
if (!task)
|
|
2714
|
-
return
|
|
2715
|
-
await this.loadTask(task, `Could not reload reserved task "${task.name}".`);
|
|
2716
|
-
return
|
|
2964
|
+
return void 0;
|
|
2965
|
+
const result = await this.loadTask(task, `Could not reload reserved task "${task.name}".`);
|
|
2966
|
+
return result.sessionId;
|
|
2717
2967
|
});
|
|
2718
2968
|
}
|
|
2719
2969
|
create(input, name, isolation = "shared") {
|
|
@@ -2757,7 +3007,10 @@ var NamedSessionManager = class {
|
|
|
2757
3007
|
await this.router.detachManagedSession(sessionId).catch(() => void 0);
|
|
2758
3008
|
throw error;
|
|
2759
3009
|
}
|
|
2760
|
-
this.router.activateManagedSession(sessionId, target, task.cwd
|
|
3010
|
+
this.router.activateManagedSession(sessionId, target, task.cwd, {
|
|
3011
|
+
isolation: task.isolation,
|
|
3012
|
+
workspaceCwd: this.cwd
|
|
3013
|
+
});
|
|
2761
3014
|
return this.selection(nextOwner, task);
|
|
2762
3015
|
});
|
|
2763
3016
|
}
|
|
@@ -2773,9 +3026,10 @@ var NamedSessionManager = class {
|
|
|
2773
3026
|
throw new Error("You already have eight open tasks. Close one before reopening another.");
|
|
2774
3027
|
}
|
|
2775
3028
|
const timestamp = this.nextTimestamp(owner);
|
|
2776
|
-
const
|
|
3029
|
+
const loadResult = await this.loadTask(task, `Could not load task "${task.name}". The current task was not changed.`);
|
|
2777
3030
|
const updatedTask = {
|
|
2778
3031
|
...task,
|
|
3032
|
+
sessionId: loadResult.sessionId,
|
|
2779
3033
|
status: "open",
|
|
2780
3034
|
updatedAt: timestamp,
|
|
2781
3035
|
lastSelectedAt: timestamp
|
|
@@ -2784,12 +3038,12 @@ var NamedSessionManager = class {
|
|
|
2784
3038
|
try {
|
|
2785
3039
|
this.commitOwner(nextOwner);
|
|
2786
3040
|
} catch (error) {
|
|
2787
|
-
if (loaded) {
|
|
2788
|
-
await this.router.detachManagedSession(
|
|
3041
|
+
if (loadResult.loaded) {
|
|
3042
|
+
await this.router.detachManagedSession(loadResult.sessionId).catch(() => void 0);
|
|
2789
3043
|
}
|
|
2790
3044
|
throw error;
|
|
2791
3045
|
}
|
|
2792
|
-
this.router.activateManagedSession(
|
|
3046
|
+
this.router.activateManagedSession(loadResult.sessionId, updatedTask.target, updatedTask.cwd, { isolation: updatedTask.isolation, workspaceCwd: this.cwd });
|
|
2793
3047
|
return this.selection(nextOwner, updatedTask);
|
|
2794
3048
|
});
|
|
2795
3049
|
}
|
|
@@ -2811,8 +3065,11 @@ var NamedSessionManager = class {
|
|
|
2811
3065
|
const timestamp = this.nextTimestamp(owner);
|
|
2812
3066
|
const replacement = wasActive ? owner.tasks.filter((candidate) => candidate.status === "open" && !this.sameName(candidate.name, task.name)).sort((a, b) => b.lastSelectedAt - a.lastSelectedAt)[0] : void 0;
|
|
2813
3067
|
let replacementLoaded = false;
|
|
3068
|
+
let replacementSessionId;
|
|
2814
3069
|
if (replacement) {
|
|
2815
|
-
|
|
3070
|
+
const replacementLoad = await this.loadTask(replacement, `Could not load fallback task "${replacement.name}". Task "${task.name}" was not closed.`);
|
|
3071
|
+
replacementLoaded = replacementLoad.loaded;
|
|
3072
|
+
replacementSessionId = replacementLoad.sessionId;
|
|
2816
3073
|
}
|
|
2817
3074
|
const closedTask = {
|
|
2818
3075
|
...task,
|
|
@@ -2822,6 +3079,7 @@ var NamedSessionManager = class {
|
|
|
2822
3079
|
let nextOwner = this.replaceTask(owner, closedTask, wasActive ? replacement?.name ?? null : owner.activeTaskName);
|
|
2823
3080
|
const selectedReplacement = replacement ? {
|
|
2824
3081
|
...replacement,
|
|
3082
|
+
sessionId: replacementSessionId ?? replacement.sessionId,
|
|
2825
3083
|
updatedAt: timestamp,
|
|
2826
3084
|
lastSelectedAt: timestamp
|
|
2827
3085
|
} : void 0;
|
|
@@ -2832,21 +3090,22 @@ var NamedSessionManager = class {
|
|
|
2832
3090
|
this.commitOwner(nextOwner);
|
|
2833
3091
|
} catch (error) {
|
|
2834
3092
|
if (replacement && replacementLoaded) {
|
|
2835
|
-
await this.router.detachManagedSession(replacement.sessionId).catch(() => void 0);
|
|
3093
|
+
await this.router.detachManagedSession(replacementSessionId ?? replacement.sessionId).catch(() => void 0);
|
|
2836
3094
|
}
|
|
2837
3095
|
throw error;
|
|
2838
3096
|
}
|
|
2839
3097
|
if (replacement) {
|
|
2840
|
-
this.router.activateManagedSession(replacement.sessionId, replacement.target, replacement.cwd);
|
|
3098
|
+
this.router.activateManagedSession(replacementSessionId ?? replacement.sessionId, replacement.target, replacement.cwd, { isolation: replacement.isolation, workspaceCwd: this.cwd });
|
|
2841
3099
|
}
|
|
2842
3100
|
try {
|
|
2843
3101
|
await this.router.detachManagedSession(task.sessionId);
|
|
2844
3102
|
} catch (error) {
|
|
2845
|
-
|
|
3103
|
+
const healedReplacement = replacement !== void 0 && replacementSessionId !== void 0 && replacementSessionId !== replacement.sessionId ? { ...replacement, sessionId: replacementSessionId } : void 0;
|
|
3104
|
+
this.commitOwner(healedReplacement ? this.replaceTask(owner, healedReplacement, owner.activeTaskName) : owner);
|
|
2846
3105
|
this.router.forgetManagedSession(task.sessionId);
|
|
2847
|
-
await this.loadTask(task, `Task "${task.name}" could not be restored after close failed.`);
|
|
3106
|
+
const restored = await this.loadTask(task, `Task "${task.name}" could not be restored after close failed.`);
|
|
2848
3107
|
if (wasActive) {
|
|
2849
|
-
this.router.activateManagedSession(
|
|
3108
|
+
this.router.activateManagedSession(restored.sessionId, task.target, task.cwd, { isolation: task.isolation, workspaceCwd: this.cwd });
|
|
2850
3109
|
}
|
|
2851
3110
|
throw new Error(`Failed to close task "${task.name}".`, {
|
|
2852
3111
|
cause: error
|
|
@@ -2867,10 +3126,36 @@ var NamedSessionManager = class {
|
|
|
2867
3126
|
const task = this.findTask(owner, owner.activeTaskName);
|
|
2868
3127
|
if (!task || task.status !== "open")
|
|
2869
3128
|
return void 0;
|
|
3129
|
+
const timestamp = this.nextTimestamp(owner);
|
|
2870
3130
|
if (task.isolation === "worktree") {
|
|
2871
|
-
|
|
3131
|
+
if (this.isBusy(task.sessionId)) {
|
|
3132
|
+
throw new Error(`Task "${task.name}" is busy. Wait for the running prompt to finish (or cancel it), then try again.`);
|
|
3133
|
+
}
|
|
3134
|
+
const sessionId2 = await this.resetWorktreeSession(task);
|
|
3135
|
+
const updatedTask2 = {
|
|
3136
|
+
...task,
|
|
3137
|
+
sessionId: sessionId2,
|
|
3138
|
+
updatedAt: timestamp,
|
|
3139
|
+
lastSelectedAt: timestamp
|
|
3140
|
+
};
|
|
3141
|
+
const nextOwner2 = this.replaceTask(owner, updatedTask2, task.name);
|
|
3142
|
+
try {
|
|
3143
|
+
this.commitOwner(nextOwner2);
|
|
3144
|
+
} catch (error) {
|
|
3145
|
+
await this.router.detachManagedSession(sessionId2).catch(() => void 0);
|
|
3146
|
+
throw error;
|
|
3147
|
+
}
|
|
3148
|
+
this.router.activateManagedSession(sessionId2, updatedTask2.target, updatedTask2.cwd, { isolation: updatedTask2.isolation, workspaceCwd: this.cwd });
|
|
3149
|
+
this.router.forgetManagedSession(task.sessionId);
|
|
3150
|
+
this.repointSupersededSessionIds(task.sessionId, sessionId2);
|
|
3151
|
+
this.supersededSessionIds.delete(task.sessionId);
|
|
3152
|
+
return {
|
|
3153
|
+
name: task.name,
|
|
3154
|
+
previousSessionId: task.sessionId,
|
|
3155
|
+
sessionId: sessionId2,
|
|
3156
|
+
worktreeKept: true
|
|
3157
|
+
};
|
|
2872
3158
|
}
|
|
2873
|
-
const timestamp = this.nextTimestamp(owner);
|
|
2874
3159
|
const sessionId = await this.createSession(task.target, task.isolation, `Could not reset task "${task.name}".`);
|
|
2875
3160
|
const updatedTask = {
|
|
2876
3161
|
...task,
|
|
@@ -2885,12 +3170,15 @@ var NamedSessionManager = class {
|
|
|
2885
3170
|
await this.router.detachManagedSession(sessionId).catch(() => void 0);
|
|
2886
3171
|
throw error;
|
|
2887
3172
|
}
|
|
2888
|
-
this.router.activateManagedSession(sessionId, updatedTask.target, updatedTask.cwd);
|
|
3173
|
+
this.router.activateManagedSession(sessionId, updatedTask.target, updatedTask.cwd, { isolation: updatedTask.isolation, workspaceCwd: this.cwd });
|
|
2889
3174
|
this.router.forgetManagedSession(task.sessionId);
|
|
3175
|
+
this.repointSupersededSessionIds(task.sessionId, sessionId);
|
|
3176
|
+
this.supersededSessionIds.delete(task.sessionId);
|
|
2890
3177
|
return {
|
|
2891
3178
|
name: task.name,
|
|
2892
3179
|
previousSessionId: task.sessionId,
|
|
2893
|
-
sessionId
|
|
3180
|
+
sessionId,
|
|
3181
|
+
worktreeKept: false
|
|
2894
3182
|
};
|
|
2895
3183
|
});
|
|
2896
3184
|
}
|
|
@@ -2960,12 +3248,17 @@ var NamedSessionManager = class {
|
|
|
2960
3248
|
throw new Error("The selected Channel task is unavailable.");
|
|
2961
3249
|
}
|
|
2962
3250
|
const release = reserve?.(task.sessionId);
|
|
3251
|
+
let activeRelease = release;
|
|
2963
3252
|
try {
|
|
2964
|
-
await this.loadTask(task, `Could not load task "${task.name}". No replacement session was created.`);
|
|
2965
|
-
|
|
2966
|
-
|
|
3253
|
+
const result = await this.loadTask(task, `Could not load task "${task.name}". No replacement session was created.`);
|
|
3254
|
+
if (result.sessionId !== task.sessionId && reserve) {
|
|
3255
|
+
release?.();
|
|
3256
|
+
activeRelease = reserve(result.sessionId);
|
|
3257
|
+
}
|
|
3258
|
+
this.router.activateManagedSession(result.sessionId, task.target, task.cwd, { isolation: task.isolation, workspaceCwd: this.cwd });
|
|
3259
|
+
return result.sessionId;
|
|
2967
3260
|
} catch (error) {
|
|
2968
|
-
|
|
3261
|
+
activeRelease?.();
|
|
2969
3262
|
throw error;
|
|
2970
3263
|
}
|
|
2971
3264
|
}
|
|
@@ -2998,9 +3291,55 @@ var NamedSessionManager = class {
|
|
|
2998
3291
|
}
|
|
2999
3292
|
async loadTask(task, failureMessage) {
|
|
3000
3293
|
try {
|
|
3001
|
-
|
|
3294
|
+
const result = await this.router.loadManagedSession(task.sessionId, task.target, this.cwd, task.cwd, task.isolation);
|
|
3295
|
+
if (result.redirectedFrom !== void 0 && result.sessionId !== task.sessionId) {
|
|
3296
|
+
try {
|
|
3297
|
+
this.healSupersededTask(task, result.sessionId);
|
|
3298
|
+
} catch {
|
|
3299
|
+
}
|
|
3300
|
+
}
|
|
3301
|
+
return result;
|
|
3002
3302
|
} catch (error) {
|
|
3003
|
-
throw new
|
|
3303
|
+
throw new NamedSessionTaskError(failureMessage, task.name, {
|
|
3304
|
+
cause: error
|
|
3305
|
+
});
|
|
3306
|
+
}
|
|
3307
|
+
}
|
|
3308
|
+
/**
|
|
3309
|
+
* Point a task at its replacement session after a superseded redirect
|
|
3310
|
+
* healed the route. No-op when the registry entry already moved on (a
|
|
3311
|
+
* concurrent reset under the same owner lock cannot interleave, but a
|
|
3312
|
+
* stale in-memory snapshot could).
|
|
3313
|
+
*/
|
|
3314
|
+
healSupersededTask(task, sessionId) {
|
|
3315
|
+
const owner = this.getOwner(task.target);
|
|
3316
|
+
if (!owner)
|
|
3317
|
+
return;
|
|
3318
|
+
const current = this.findTask(owner, task.name);
|
|
3319
|
+
if (!current || current.sessionId !== task.sessionId)
|
|
3320
|
+
return;
|
|
3321
|
+
const timestamp = this.nextTimestamp(owner);
|
|
3322
|
+
this.commitOwner(this.replaceTask(owner, { ...current, sessionId, updatedAt: timestamp }, owner.activeTaskName));
|
|
3323
|
+
this.repointSupersededSessionIds(task.sessionId, sessionId);
|
|
3324
|
+
this.supersededSessionIds.set(task.sessionId, sessionId);
|
|
3325
|
+
}
|
|
3326
|
+
/**
|
|
3327
|
+
* Follow every id that still resolves to `oldSessionId` onto its
|
|
3328
|
+
* replacement, so a task superseded more than once stays reachable from the
|
|
3329
|
+
* oldest id a turn is bound to and the map does not grow once per reset.
|
|
3330
|
+
*/
|
|
3331
|
+
repointSupersededSessionIds(oldSessionId, newSessionId) {
|
|
3332
|
+
for (const boundSessionId of [...this.supersededSessionIds.keys()]) {
|
|
3333
|
+
if (this.supersededSessionIds.get(boundSessionId) === oldSessionId) {
|
|
3334
|
+
this.supersededSessionIds.set(boundSessionId, newSessionId);
|
|
3335
|
+
}
|
|
3336
|
+
}
|
|
3337
|
+
}
|
|
3338
|
+
async resetWorktreeSession(task) {
|
|
3339
|
+
try {
|
|
3340
|
+
return await this.router.replaceManagedWorktreeSession(task.sessionId, task.target, this.cwd, task.cwd);
|
|
3341
|
+
} catch (error) {
|
|
3342
|
+
throw new NamedSessionTaskError(`Could not reset task "${task.name}".`, task.name, { cause: error });
|
|
3004
3343
|
}
|
|
3005
3344
|
}
|
|
3006
3345
|
async createSession(target, isolation, failureMessage) {
|
|
@@ -4088,6 +4427,9 @@ var ChannelBase = class {
|
|
|
4088
4427
|
bridgeSessionDiedListener = /* @__PURE__ */ __name((event) => {
|
|
4089
4428
|
this.onSessionDied(event.sessionId);
|
|
4090
4429
|
}, "bridgeSessionDiedListener");
|
|
4430
|
+
bridgeDisconnectedListener = /* @__PURE__ */ __name(() => {
|
|
4431
|
+
this.onBridgeDisconnected();
|
|
4432
|
+
}, "bridgeDisconnectedListener");
|
|
4091
4433
|
bridgePermissionRequestListener = /* @__PURE__ */ __name((event) => {
|
|
4092
4434
|
void this.dispatchPermissionRequest(event).catch((err) => {
|
|
4093
4435
|
process.stderr.write(`[${this.name}] permission relay failed for request ${sanitizeLogText(event.requestId, 128)}: ${this.lifecycleError(err)}
|
|
@@ -5570,12 +5912,21 @@ ${promptText}` : promptText;
|
|
|
5570
5912
|
this.unattendedMemorySessions.delete(sessionId);
|
|
5571
5913
|
this.removePendingPermissionsForSession(sessionId);
|
|
5572
5914
|
}
|
|
5915
|
+
/**
|
|
5916
|
+
* Called when the standalone ACP bridge process exits. Its in-flight turns
|
|
5917
|
+
* never settle, but crash recovery restores the sessions on a fresh bridge,
|
|
5918
|
+
* so overrides must clear only turn-scoped transient state (never session
|
|
5919
|
+
* routing) and must not fabricate terminal outcomes for interrupted turns.
|
|
5920
|
+
*/
|
|
5921
|
+
onBridgeDisconnected() {
|
|
5922
|
+
}
|
|
5573
5923
|
onSessionRetiring(_sessionId) {
|
|
5574
5924
|
}
|
|
5575
5925
|
attachBridgeEvents(bridge) {
|
|
5576
5926
|
bridge.on("toolCall", this.bridgeToolCallListener);
|
|
5577
5927
|
bridge.on("backgroundResponse", this.bridgeBackgroundResponseListener);
|
|
5578
5928
|
bridge.on("sessionDied", this.bridgeSessionDiedListener);
|
|
5929
|
+
bridge.on("disconnected", this.bridgeDisconnectedListener);
|
|
5579
5930
|
bridge.on("permissionRequest", this.bridgePermissionRequestListener);
|
|
5580
5931
|
bridge.on("permissionResolved", this.bridgePermissionResolvedListener);
|
|
5581
5932
|
}
|
|
@@ -5583,6 +5934,7 @@ ${promptText}` : promptText;
|
|
|
5583
5934
|
bridge.off("toolCall", this.bridgeToolCallListener);
|
|
5584
5935
|
bridge.off("backgroundResponse", this.bridgeBackgroundResponseListener);
|
|
5585
5936
|
bridge.off("sessionDied", this.bridgeSessionDiedListener);
|
|
5937
|
+
bridge.off("disconnected", this.bridgeDisconnectedListener);
|
|
5586
5938
|
bridge.off("permissionRequest", this.bridgePermissionRequestListener);
|
|
5587
5939
|
bridge.off("permissionResolved", this.bridgePermissionResolvedListener);
|
|
5588
5940
|
}
|
|
@@ -6020,6 +6372,21 @@ ${requestList}`);
|
|
|
6020
6372
|
binding.released = true;
|
|
6021
6373
|
this.releaseQueuedTurn(binding.sessionId);
|
|
6022
6374
|
}
|
|
6375
|
+
/**
|
|
6376
|
+
* Follow a task onto the session its reload healed to (a superseded
|
|
6377
|
+
* redirect). The queue reservation and the staleness generation are keyed
|
|
6378
|
+
* by session id, so both must move with the binding: leaving them behind
|
|
6379
|
+
* keeps the stale id "busy" forever and drops the turn on a generation the
|
|
6380
|
+
* replacement never had.
|
|
6381
|
+
*/
|
|
6382
|
+
moveNamedTurnBinding(binding, sessionId) {
|
|
6383
|
+
if (binding.sessionId !== null) {
|
|
6384
|
+
this.releaseQueuedTurn(binding.sessionId);
|
|
6385
|
+
}
|
|
6386
|
+
binding.sessionId = sessionId;
|
|
6387
|
+
binding.generation = this.sessionGenerations.get(sessionId) ?? 0;
|
|
6388
|
+
this.reserveQueuedTurn(sessionId);
|
|
6389
|
+
}
|
|
6023
6390
|
finishNamedTurnBinding(envelope) {
|
|
6024
6391
|
const binding = this.namedTurnBindings.get(envelope);
|
|
6025
6392
|
if (!binding)
|
|
@@ -6075,12 +6442,51 @@ ${requestList}`);
|
|
|
6075
6442
|
return true;
|
|
6076
6443
|
}
|
|
6077
6444
|
}
|
|
6445
|
+
/**
|
|
6446
|
+
* The actionable recovery message for a worktree task whose ownership state
|
|
6447
|
+
* the daemon refused to restore. Both codes come from the load/resume route
|
|
6448
|
+
* — the reset route resumes an interrupted transfer itself and reports a
|
|
6449
|
+
* broken marker as invalid state — so they surface on selection and on a
|
|
6450
|
+
* message, wrapped in the manager's generic load failure.
|
|
6451
|
+
*
|
|
6452
|
+
* Clearing always acts on the *selected* task, so pointing the user at a
|
|
6453
|
+
* clear is only safe when the task that failed is the selected one. Aimed at
|
|
6454
|
+
* any other task it would run a full ownership transfer against a healthy
|
|
6455
|
+
* one and destroy that conversation, so the alternative points at the close
|
|
6456
|
+
* that works on the broken task without loading it. Both name that task.
|
|
6457
|
+
*/
|
|
6458
|
+
async worktreeRecoveryMessage(envelope, error) {
|
|
6459
|
+
const code = readDaemonHttpErrorCode(error);
|
|
6460
|
+
if (code !== "worktree_reset_interrupted" && code !== "worktree_marker_missing") {
|
|
6461
|
+
return void 0;
|
|
6462
|
+
}
|
|
6463
|
+
const interrupted = code === "worktree_reset_interrupted";
|
|
6464
|
+
const failedTaskName = error instanceof NamedSessionTaskError ? error.taskName : void 0;
|
|
6465
|
+
const safeTaskName = failedTaskName === void 0 ? void 0 : sanitizeDisplayText(failedTaskName, 32);
|
|
6466
|
+
const subject = safeTaskName === void 0 ? "The task" : `Task "${safeTaskName}"`;
|
|
6467
|
+
const problem = interrupted ? "was interrupted while being reset" : "cannot verify its worktree because its ownership marker is missing";
|
|
6468
|
+
if (safeTaskName !== void 0 && failedTaskName === await this.selectedTaskName(envelope)) {
|
|
6469
|
+
return `${subject} ${problem}. Its files were not changed. ${interrupted ? "Clear the task again to finish the reset." : "Clear the task to restart it in the same worktree, or close it."}`;
|
|
6470
|
+
}
|
|
6471
|
+
const remedy = safeTaskName === void 0 ? "select this task first or close it" : `select this task first or close it with ${this.prefixedCommand(`/session close ${safeTaskName}`)}`;
|
|
6472
|
+
return `${subject} ${problem}. Its files were not changed. Clearing now would reset the selected task instead, so ${remedy}.`;
|
|
6473
|
+
}
|
|
6474
|
+
async selectedTaskName(envelope) {
|
|
6475
|
+
const namedSessions = this.namedSessions;
|
|
6476
|
+
if (!namedSessions)
|
|
6477
|
+
return void 0;
|
|
6478
|
+
try {
|
|
6479
|
+
return (await namedSessions.current(this.namedSessionOwner(envelope)))?.name;
|
|
6480
|
+
} catch {
|
|
6481
|
+
return void 0;
|
|
6482
|
+
}
|
|
6483
|
+
}
|
|
6078
6484
|
async sendNamedSessionError(envelope, error) {
|
|
6079
6485
|
if (error instanceof Error && error.cause !== void 0) {
|
|
6080
6486
|
process.stderr.write(`[${sanitizeLogText(this.name, 64)}] named-session operation failed: ${this.lifecycleError(error)} | cause: ${this.lifecycleError(error.cause)}
|
|
6081
6487
|
`);
|
|
6082
6488
|
}
|
|
6083
|
-
const message = error instanceof Error ? sanitizeDisplayText(error.message, 500) : "Named-session operation failed.";
|
|
6489
|
+
const message = await this.worktreeRecoveryMessage(envelope, error) ?? (error instanceof Error ? sanitizeDisplayText(error.message, 500) : "Named-session operation failed.");
|
|
6084
6490
|
await this.sendThreadMessage(envelope.chatId, envelope.threadId, message || "Named-session operation failed.");
|
|
6085
6491
|
}
|
|
6086
6492
|
async handleNamedSessionsCommand(envelope, args) {
|
|
@@ -6125,7 +6531,7 @@ ${requestList}`);
|
|
|
6125
6531
|
}
|
|
6126
6532
|
case "new": {
|
|
6127
6533
|
const isolation = parts.length === 2 && parts[1] === "--worktree" ? "worktree" : "shared";
|
|
6128
|
-
if (isolation === "shared" && parts.length !== 1 || isolation === "worktree" && parts.length !== 2) {
|
|
6534
|
+
if (isolation === "shared" && parts.length !== 1 || isolation === "worktree" && parts.length !== 2 || parts[0]?.startsWith("-")) {
|
|
6129
6535
|
break;
|
|
6130
6536
|
}
|
|
6131
6537
|
const created = await namedSessions.create(owner, parts[0], isolation);
|
|
@@ -6186,6 +6592,7 @@ ${requestList}`);
|
|
|
6186
6592
|
registerSharedCommands() {
|
|
6187
6593
|
const doClear = /* @__PURE__ */ __name(async (envelope) => {
|
|
6188
6594
|
let resetTaskName;
|
|
6595
|
+
let resetWorktreeKept = false;
|
|
6189
6596
|
let removedIds;
|
|
6190
6597
|
const retiringSessionId = this.namedSessions ? void 0 : this.router.getSession(this.name, envelope.senderId, envelope.chatId, envelope.threadId);
|
|
6191
6598
|
if (retiringSessionId)
|
|
@@ -6194,8 +6601,18 @@ ${requestList}`);
|
|
|
6194
6601
|
try {
|
|
6195
6602
|
const reset = await this.namedSessions.reset(this.namedSessionOwner(envelope));
|
|
6196
6603
|
resetTaskName = reset?.name;
|
|
6604
|
+
resetWorktreeKept = reset?.worktreeKept ?? false;
|
|
6197
6605
|
removedIds = reset ? [reset.previousSessionId] : [];
|
|
6198
6606
|
} catch (error) {
|
|
6607
|
+
const code = readDaemonHttpErrorCode(error);
|
|
6608
|
+
if (code !== void 0) {
|
|
6609
|
+
process.stderr.write(`[${sanitizeLogText(this.name, 64)}] worktree reset failed (${sanitizeLogText(code, 64)}): ${this.lifecycleError(error)}
|
|
6610
|
+
`);
|
|
6611
|
+
}
|
|
6612
|
+
if (code === "worktree_reset_active") {
|
|
6613
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, "Task is busy. Wait for the running prompt to finish (or cancel it), then try again.");
|
|
6614
|
+
return;
|
|
6615
|
+
}
|
|
6199
6616
|
await this.sendNamedSessionError(envelope, error);
|
|
6200
6617
|
return;
|
|
6201
6618
|
}
|
|
@@ -6250,7 +6667,7 @@ ${requestList}`);
|
|
|
6250
6667
|
}
|
|
6251
6668
|
this.discardRetiredSession(this.bridge, id, "cleared");
|
|
6252
6669
|
}
|
|
6253
|
-
await this.sendThreadMessage(envelope.chatId, envelope.threadId, resetTaskName ? `Task "${resetTaskName}" reset with a fresh conversation.` : "Session cleared. The next message starts a fresh conversation.");
|
|
6670
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, resetTaskName ? resetWorktreeKept ? `Task "${resetTaskName}" reset with a fresh conversation; its worktree and files were kept.` : `Task "${resetTaskName}" reset with a fresh conversation.` : "Session cleared. The next message starts a fresh conversation.");
|
|
6254
6671
|
} else {
|
|
6255
6672
|
await this.sendThreadMessage(envelope.chatId, envelope.threadId, "No active session to clear.");
|
|
6256
6673
|
}
|
|
@@ -7775,8 +8192,10 @@ ${text}`;
|
|
|
7775
8192
|
return;
|
|
7776
8193
|
}
|
|
7777
8194
|
try {
|
|
7778
|
-
|
|
7779
|
-
sessionId
|
|
8195
|
+
sessionId = await this.namedSessions.resumeReserved(this.namedSessionOwner(envelope), namedTurn.sessionId);
|
|
8196
|
+
if (sessionId && sessionId !== namedTurn.sessionId) {
|
|
8197
|
+
this.moveNamedTurnBinding(namedTurn, sessionId);
|
|
8198
|
+
}
|
|
7780
8199
|
} catch (error) {
|
|
7781
8200
|
await this.sendNamedSessionError(envelope, error);
|
|
7782
8201
|
return;
|
|
@@ -8489,6 +8908,7 @@ var DaemonChannelBridge = class extends EventEmitter2 {
|
|
|
8489
8908
|
activePrompts = /* @__PURE__ */ new Set();
|
|
8490
8909
|
activePromptControllers = /* @__PURE__ */ new Map();
|
|
8491
8910
|
availableCommandsBySession = /* @__PURE__ */ new Map();
|
|
8911
|
+
toolCallKindsBySession = /* @__PURE__ */ new Map();
|
|
8492
8912
|
turnBarriers = /* @__PURE__ */ new Map();
|
|
8493
8913
|
channelLoopToolHandlers = [];
|
|
8494
8914
|
channelLoopDisabledSessions = /* @__PURE__ */ new Set();
|
|
@@ -8595,6 +9015,38 @@ var DaemonChannelBridge = class extends EventEmitter2 {
|
|
|
8595
9015
|
}
|
|
8596
9016
|
return session.sessionId;
|
|
8597
9017
|
}
|
|
9018
|
+
/**
|
|
9019
|
+
* Transfer a worktree session's checkout ownership to a fresh replacement
|
|
9020
|
+
* session (daemon `session_worktree_reset_v1`). The returned id is the
|
|
9021
|
+
* replacement's; the superseded session's clients stay bound to it (and
|
|
9022
|
+
* are forgotten by the caller). Gated on the capability flag so a daemon
|
|
9023
|
+
* without reset support fails before any session is created.
|
|
9024
|
+
*/
|
|
9025
|
+
async resetWorktreeSession(sessionId, cwd, options, bindingToken) {
|
|
9026
|
+
if (!this.options.sessionWorktreeReset) {
|
|
9027
|
+
throw new Error("The daemon does not support worktree reset for Channel tasks.");
|
|
9028
|
+
}
|
|
9029
|
+
const lifecycleGeneration = this.lifecycleGeneration;
|
|
9030
|
+
const session = await this.options.sessionFactory({
|
|
9031
|
+
workspaceCwd: cwd || this.options.cwd,
|
|
9032
|
+
modelServiceId: this.options.modelServiceId,
|
|
9033
|
+
sessionScope: this.options.sessionScope ?? "thread",
|
|
9034
|
+
...options?.approvalMode ? { approvalMode: options.approvalMode } : {},
|
|
9035
|
+
...options?.sourceId ? { sourceId: options.sourceId } : {},
|
|
9036
|
+
worktreeReset: { sessionId }
|
|
9037
|
+
});
|
|
9038
|
+
if (lifecycleGeneration !== this.lifecycleGeneration) {
|
|
9039
|
+
await this.rejectStaleSession(session);
|
|
9040
|
+
}
|
|
9041
|
+
this.attachSession(session, bindingToken);
|
|
9042
|
+
if (options?.enableChannelLoops === false) {
|
|
9043
|
+
this.channelLoopDisabledSessions.add(session.sessionId);
|
|
9044
|
+
void this.reconcileChannelLoopMcpForSession(session.sessionId);
|
|
9045
|
+
} else {
|
|
9046
|
+
await this.reconcileChannelLoopMcpForSession(session.sessionId);
|
|
9047
|
+
}
|
|
9048
|
+
return session.sessionId;
|
|
9049
|
+
}
|
|
8598
9050
|
registerChannelLoopToolHandler(handler) {
|
|
8599
9051
|
if (!this.channelLoopToolHandlers.includes(handler)) {
|
|
8600
9052
|
this.channelLoopToolHandlers.push(handler);
|
|
@@ -9001,15 +9453,23 @@ var DaemonChannelBridge = class extends EventEmitter2 {
|
|
|
9001
9453
|
case "tool_call":
|
|
9002
9454
|
case "tool_call_update": {
|
|
9003
9455
|
const toolCallId = getString(update["toolCallId"]);
|
|
9004
|
-
const
|
|
9456
|
+
const explicitKind = getString(update["kind"]);
|
|
9005
9457
|
const meta = isRecord3(update["_meta"]) ? update["_meta"] : void 0;
|
|
9006
|
-
if (!
|
|
9458
|
+
if (!explicitKind && toolCallId && getString(update["status"]) === "in_progress" && (meta?.["shellProgress"] !== void 0 || meta?.["subagentProgress"] === true)) {
|
|
9007
9459
|
break;
|
|
9008
9460
|
}
|
|
9461
|
+
let sessionKinds = this.toolCallKindsBySession.get(sessionId);
|
|
9462
|
+
const kind = explicitKind || sessionKinds?.get(toolCallId ?? "");
|
|
9009
9463
|
if (!toolCallId || !kind) {
|
|
9010
9464
|
this.emitProtocolError(`Malformed daemon ${type} event`, update);
|
|
9011
9465
|
break;
|
|
9012
9466
|
}
|
|
9467
|
+
if (type === "tool_call" || explicitKind) {
|
|
9468
|
+
const kinds = sessionKinds ?? /* @__PURE__ */ new Map();
|
|
9469
|
+
kinds.set(toolCallId, kind);
|
|
9470
|
+
this.toolCallKindsBySession.set(sessionId, kinds);
|
|
9471
|
+
sessionKinds = kinds;
|
|
9472
|
+
}
|
|
9013
9473
|
const event = {
|
|
9014
9474
|
sessionId,
|
|
9015
9475
|
toolCallId,
|
|
@@ -9022,6 +9482,12 @@ var DaemonChannelBridge = class extends EventEmitter2 {
|
|
|
9022
9482
|
this.emitResponseBoundary(sessionId);
|
|
9023
9483
|
}
|
|
9024
9484
|
this.emit("toolCall", event);
|
|
9485
|
+
if (event.status === "completed" || event.status === "failed") {
|
|
9486
|
+
sessionKinds?.delete(toolCallId);
|
|
9487
|
+
if (sessionKinds?.size === 0) {
|
|
9488
|
+
this.toolCallKindsBySession.delete(sessionId);
|
|
9489
|
+
}
|
|
9490
|
+
}
|
|
9025
9491
|
break;
|
|
9026
9492
|
}
|
|
9027
9493
|
case "plan": {
|
|
@@ -9149,6 +9615,7 @@ var DaemonChannelBridge = class extends EventEmitter2 {
|
|
|
9149
9615
|
this.abortActivePrompts(sessionId);
|
|
9150
9616
|
this.activePrompts.delete(sessionId);
|
|
9151
9617
|
this.availableCommandsBySession.delete(sessionId);
|
|
9618
|
+
this.toolCallKindsBySession.delete(sessionId);
|
|
9152
9619
|
if (this.latestAvailableCommandsSessionId === sessionId) {
|
|
9153
9620
|
this.latestAvailableCommandsSessionId = Array.from(this.availableCommandsBySession.keys()).at(-1);
|
|
9154
9621
|
}
|