@qwen-code/qwen-code 0.19.3 → 0.19.4-nightly.20260702.46814e4f1
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/loop/SKILL.md +22 -3
- package/bundled/loop/SKILL.test.ts +20 -0
- package/bundled/loop/autonomous-loop.test.ts +59 -0
- package/bundled/loop/autonomous-loop.ts +102 -0
- package/bundled/loop/loop-task-file.test.ts +1064 -0
- package/bundled/loop/loop-task-file.ts +404 -0
- package/bundled/loop/loop-tick-resolver.test.ts +906 -0
- package/bundled/loop/loop-tick-resolver.ts +416 -0
- package/bundled/qc-helper/SKILL.md +12 -5
- package/bundled/qc-helper/docs/configuration/auth.md +1 -1
- package/bundled/qc-helper/docs/configuration/settings.md +62 -32
- package/bundled/qc-helper/docs/features/approval-mode.md +3 -0
- package/bundled/qc-helper/docs/features/auto-mode.md +40 -0
- package/bundled/qc-helper/docs/features/channels/overview.md +81 -18
- package/bundled/qc-helper/docs/features/channels/plugins.md +1 -1
- package/bundled/qc-helper/docs/features/code-review.md +17 -61
- package/bundled/qc-helper/docs/features/commands.md +42 -40
- package/bundled/qc-helper/docs/features/headless.md +19 -18
- package/bundled/qc-helper/docs/features/hooks.md +6 -1
- package/bundled/qc-helper/docs/features/mcp.md +3 -1
- package/bundled/qc-helper/docs/features/memory.md +1 -1
- package/bundled/qc-helper/docs/features/scheduled-tasks.md +10 -0
- package/bundled/qc-helper/docs/features/status-line.md +3 -3
- package/bundled/qc-helper/docs/ide-integration/ide-integration.md +4 -4
- package/bundled/qc-helper/docs/qwen-serve.md +53 -0
- package/bundled/qc-helper/docs/support/troubleshooting.md +11 -0
- package/bundled/review/DESIGN.md +21 -26
- package/bundled/review/SKILL.md +45 -129
- package/chunks/MaxSizedBox-GHGRQ2OS.js +69 -0
- package/chunks/{StandaloneSessionPicker-Z52JTYST.js → StandaloneSessionPicker-G7YTTM27.js} +49 -42
- package/chunks/{acpAgent-7RZUOWOM.js → acpAgent-SDOILBSU.js} +1325 -365
- package/chunks/{agent-4FG7WTHJ.js → agent-NTSXGV4L.js} +31 -25
- package/chunks/agent-headless-WYURMSAB.js +62 -0
- package/chunks/{anthropicContentGenerator-PFITVL7Y.js → anthropicContentGenerator-WL3LJOUB.js} +110 -31
- package/chunks/{artifact-tool-D2X7G3C3.js → artifact-tool-W76WC2JX.js} +3 -3
- package/chunks/{askUserQuestion-UGETICJQ.js → askUserQuestion-J3P6TH3V.js} +2 -2
- package/chunks/bridge-AMOL4W4P.js +73 -0
- package/chunks/{ca-IUFWESZL.js → ca-HCMB2I54.js} +10 -9
- package/chunks/channel-worker-supervisor-C3IB63V7.js +659 -0
- package/chunks/{chunk-STUWFKGD.js → chunk-26JIREA5.js} +466 -543
- package/chunks/{chunk-SLNKLLEO.js → chunk-2MRV62AU.js} +37 -8
- package/chunks/{chunk-ODLIHNOY.js → chunk-2U4HUMOL.js} +1 -1
- package/chunks/{chunk-CKQA6AWF.js → chunk-4D73HUOP.js} +1 -1
- package/chunks/{chunk-M2U5NM24.js → chunk-54YZOP7P.js} +309 -72
- package/chunks/{chunk-J7FA27RO.js → chunk-5LKL3PAU.js} +3 -3
- package/chunks/chunk-5P5XGNYH.js +93 -0
- package/chunks/{chunk-UFLGERMB.js → chunk-6JE32BRB.js} +178 -124
- package/chunks/{chunk-FKAVULLM.js → chunk-75AVTQJ2.js} +74 -10
- package/chunks/{chunk-I2LYBGNI.js → chunk-7IOMIYOE.js} +1 -1
- package/chunks/{chunk-4LUZAKMK.js → chunk-7KXAGQJ2.js} +1 -1
- package/chunks/{chunk-BXSHL2SF.js → chunk-7LUOQJ3D.js} +1 -1
- package/chunks/{chunk-YAINVQ3Q.js → chunk-A5OPLHFM.js} +18693 -17055
- package/chunks/chunk-AHNXYU4O.js +24 -0
- package/chunks/{chunk-UX4SGCGN.js → chunk-AVQDCKNF.js} +96 -22
- package/chunks/{chunk-HYCC3XM3.js → chunk-B236XPGF.js} +1 -1
- package/chunks/chunk-B6SZLQAZ.js +3523 -0
- package/chunks/{chunk-5DWXLGOM.js → chunk-BJBWRCSK.js} +1 -1
- package/chunks/chunk-BPFJQGY7.js +193 -0
- package/chunks/{chunk-SKQZZVAV.js → chunk-BZHLWC6T.js} +2 -2
- package/chunks/{chunk-U3KSMM7G.js → chunk-D5KISTLW.js} +339 -383
- package/chunks/{chunk-GT2FGICD.js → chunk-DE7YXUR7.js} +1 -1
- package/chunks/{chunk-BUUQ5HPX.js → chunk-DG573EOO.js} +1 -1
- package/chunks/{chunk-VVLOGDB6.js → chunk-DX3TKXNT.js} +2 -2
- package/chunks/chunk-E5A7LHNN.js +51 -0
- package/chunks/{chunk-3PJXIDKI.js → chunk-E6US47KI.js} +3 -27
- package/chunks/{chunk-QBZ22PQX.js → chunk-EWALXUAD.js} +3 -1
- package/chunks/{chunk-PDE7CSDS.js → chunk-FXKI7OW6.js} +2 -2
- package/chunks/{chunk-F3ZYSEY6.js → chunk-FY4TT4L4.js} +3 -3
- package/chunks/{chunk-QLDPRILK.js → chunk-G7OQ3RFJ.js} +3 -3
- package/chunks/{chunk-R2BXK7SX.js → chunk-GHOTR7HL.js} +6 -1
- package/chunks/{chunk-KMGMKW5Q.js → chunk-GLPV75ES.js} +9 -3
- package/chunks/{chunk-LD2XBG6Z.js → chunk-GO6LNQXT.js} +1 -39
- package/chunks/{chunk-CNLEDYE3.js → chunk-H6TNLOLM.js} +5 -5
- package/chunks/{chunk-JVHEVCAU.js → chunk-HLW4EGKR.js} +31 -6
- package/chunks/{chunk-I4H7PRWQ.js → chunk-HTWHAN44.js} +1 -1
- package/chunks/{chunk-QE6KJYLT.js → chunk-IPYE5BIS.js} +123 -25
- package/chunks/{chunk-EJYJYJZ2.js → chunk-IRJWHZWU.js} +3 -70
- package/chunks/{chunk-EDMZZFDU.js → chunk-J3YPTTNL.js} +930 -798
- package/chunks/{chunk-GGBIN5K7.js → chunk-JGAJMIJZ.js} +1 -1
- package/chunks/{chunk-N4EJFBN5.js → chunk-JVLP5US5.js} +427 -263
- package/chunks/{chunk-R5OP2ATH.js → chunk-JZG7VB6C.js} +11 -11
- package/chunks/{chunk-QI7GOGJR.js → chunk-KKQWC6WS.js} +1 -1
- package/chunks/{chunk-ADCIHOQZ.js → chunk-KX5QZRW2.js} +142 -30
- package/chunks/{chunk-SBBN4BWR.js → chunk-L7OJ3ZO3.js} +1 -1
- package/chunks/{chunk-NDOC6M5S.js → chunk-L7QPM2YD.js} +2 -2
- package/chunks/{chunk-BVSVIN45.js → chunk-LKWAVAB5.js} +3 -3
- package/chunks/{chunk-T4T2FNV4.js → chunk-LOW52WYZ.js} +2 -2
- package/chunks/{chunk-4QK3O43S.js → chunk-LU7BIVWC.js} +4 -4
- package/chunks/{chunk-ZP6UKOPB.js → chunk-LWGLBVWA.js} +1 -1
- package/chunks/{chunk-L7OKCI7T.js → chunk-M7BLWURA.js} +15 -1
- package/chunks/{chunk-PR32FRT6.js → chunk-MIM62IXS.js} +3 -3
- package/chunks/{chunk-RD6YJJJ6.js → chunk-MOUXUCXQ.js} +1 -1
- package/chunks/{chunk-VBZ452JT.js → chunk-MSNGFH6L.js} +494 -114
- package/chunks/{chunk-BX5YO7UW.js → chunk-MTNTVOJR.js} +542 -370
- package/chunks/chunk-MX2YXRER.js +44 -0
- package/chunks/chunk-NIOPRZNN.js +27 -0
- package/chunks/{chunk-SMYQZVZ3.js → chunk-NOGSPTLJ.js} +1 -1
- package/chunks/{chunk-DDMOU62Q.js → chunk-NPQWQYU6.js} +1 -1
- package/chunks/{chunk-MNF6S5PR.js → chunk-P5THQV6A.js} +4 -4
- package/chunks/{chunk-6V4NZFUS.js → chunk-PCYOT4PK.js} +5 -5
- package/chunks/{chunk-CF6BB3LT.js → chunk-PPFWEV7G.js} +10 -1
- package/chunks/{chunk-FXKVLFFY.js → chunk-PSFDB5FZ.js} +3 -3
- package/chunks/{chunk-XJYUPHRC.js → chunk-QOMAHFYI.js} +3 -3
- package/chunks/{chunk-J37FGIOA.js → chunk-QXPI7FEC.js} +38 -4
- package/chunks/{chunk-RRFZXMYP.js → chunk-QZDBHNMV.js} +691 -164
- package/chunks/{chunk-S7AKE7HL.js → chunk-R6RI2HIC.js} +63 -9
- package/chunks/{chunk-HZT4UCFB.js → chunk-RB7S52NJ.js} +4 -4
- package/chunks/{chunk-J33ZR6OJ.js → chunk-RK22ACPP.js} +16 -16
- package/chunks/chunk-RM3PGSGL.js +66 -0
- package/chunks/chunk-RNBYOUGV.js +42 -0
- package/chunks/chunk-S6RLAIUR.js +23 -0
- package/chunks/{chunk-3TV3HUWZ.js → chunk-SCYK2YLI.js} +81 -30
- package/chunks/{chunk-HPZTOP4I.js → chunk-SEKRT4SD.js} +133 -23
- package/chunks/chunk-SEZC2725.js +36 -0
- package/chunks/chunk-SIUQ3YYX.js +78 -0
- package/chunks/{chunk-O2VBQ3Y2.js → chunk-SJBIFVD2.js} +2 -2
- package/chunks/chunk-SYCJMSIJ.js +82 -0
- package/chunks/{chunk-JE5FVRPC.js → chunk-T22H4V4R.js} +48 -23
- package/chunks/{chunk-3227DZO4.js → chunk-T42ACHFI.js} +1 -1
- package/chunks/{chunk-UO5GVXQE.js → chunk-TENOUWY2.js} +3 -3
- package/chunks/{chunk-JOLIREYR.js → chunk-TOAUDIS7.js} +1 -1
- package/chunks/{chunk-QNKBEJO2.js → chunk-UA6XBZT7.js} +2776 -1289
- package/chunks/{chunk-O75BHFQW.js → chunk-UQTYK5SS.js} +2 -2
- package/chunks/{chunk-Y6YMRS3U.js → chunk-UY2TCIZS.js} +17 -3
- package/chunks/{chunk-FNJ7BDPH.js → chunk-UY7ZAYTY.js} +10 -7
- package/chunks/{chunk-UYT3MWEB.js → chunk-UYHWM24C.js} +30 -2
- package/chunks/{chunk-SMXULRAN.js → chunk-VXGPYF7U.js} +1 -1
- package/chunks/{chunk-BTLJ2MF5.js → chunk-W7CG5HPC.js} +3 -3
- package/chunks/{chunk-JJXWTVSK.js → chunk-XHZKDN7M.js} +34 -1
- package/chunks/{chunk-K5XU6E4T.js → chunk-XKSCTXPK.js} +2 -2
- package/chunks/chunk-Y4LITCRB.js +367 -0
- package/chunks/chunk-YHTNWGRR.js +239 -0
- package/chunks/{chunk-BKXBARJZ.js → chunk-YPCPZSZB.js} +1 -1
- package/chunks/{chunk-QWFNTRH4.js → chunk-YSM24SCE.js} +1 -1
- package/chunks/chunk-YTFBURQD.js +313 -0
- package/chunks/{chunk-NL4C3H6C.js → chunk-YXK4GPYO.js} +1 -1
- package/chunks/{chunk-RYLJU2DY.js → chunk-ZN5T4BHI.js} +1 -1
- package/chunks/{computer-use-JGB36FDW.js → computer-use-MTSVPLPY.js} +34 -28
- package/chunks/contextCommand-VGJ3BPTK.js +67 -0
- package/chunks/{cron-create-SKEY55RG.js → cron-create-6YTCOX6P.js} +4 -4
- package/chunks/{cron-delete-I3NAT32Z.js → cron-delete-E3NIFSUK.js} +4 -4
- package/chunks/{cron-list-6XRRL6TH.js → cron-list-Q64MNQNE.js} +4 -4
- package/chunks/daemon-EEB2RYOL.js +8453 -0
- package/chunks/daemon-status-provider-H5SNMK42.js +71 -0
- package/chunks/{de-EOW5PVHF.js → de-PLLFDERI.js} +10 -9
- package/chunks/{dist-NHEYYB2B.js → dist-ADMIQGHI.js} +2 -2
- package/chunks/{dist-J37VXPLD.js → dist-BCQ7INM7.js} +40 -15
- package/chunks/{dist-663NZ6MI.js → dist-KNZFCY5F.js} +116 -11
- package/chunks/{dist-LB6OGPVM.js → dist-LHUWC3K6.js} +26 -5
- package/chunks/{dist-PQPZ5Q4N.js → dist-WBBZ76JZ.js} +20 -9
- package/chunks/{earlyInputCapture-44RISVVJ.js → earlyInputCapture-U4ZIQSQU.js} +32 -26
- package/chunks/{edit-NN6GM5DT.js → edit-SYIQ2KBI.js} +41 -38
- package/chunks/{en-HPWEJBTR.js → en-M4EBUBNU.js} +32 -10
- package/chunks/{enter-worktree-PB3O2C7D.js → enter-worktree-HPPOO244.js} +31 -25
- package/chunks/{enterPlanMode-YQFNNSUA.js → enterPlanMode-56YYO52U.js} +41 -25
- package/chunks/{errors-LS7XU5DZ.js → errors-EO4SXCFP.js} +33 -27
- package/chunks/{exit-worktree-E2FTNSBK.js → exit-worktree-UDM7E6XH.js} +31 -25
- package/chunks/{exitPlanMode-GLYK2BUB.js → exitPlanMode-M6P3AWLJ.js} +149 -33
- package/chunks/{fast-path-WQ6M7LI7.js → fast-path-42P4QYWI.js} +33 -14
- package/chunks/{fast-path-settings-OAGU3X5H.js → fast-path-settings-UQLRFDQP.js} +2 -2
- package/chunks/{fr-BN5NKSAC.js → fr-MBMNQSQ6.js} +10 -9
- package/chunks/{gemini-2YFLVA2M.js → gemini-NRLXS5J7.js} +84 -70
- package/chunks/{geminiContentGenerator-XV6SV6CD.js → geminiContentGenerator-DLJPYYPA.js} +41 -5
- package/chunks/{glob-2H6CDDMK.js → glob-JPY3F74Y.js} +31 -25
- package/chunks/{grep-VXIUXM3C.js → grep-HW23YES5.js} +31 -25
- package/chunks/initializer-HWOZTC4A.js +67 -0
- package/chunks/{ja-7DEUB2TS.js → ja-HFV5QCHR.js} +10 -9
- package/chunks/{keychain-token-storage-YLMDLKXT.js → keychain-token-storage-GPAKRDKQ.js} +2 -2
- package/chunks/list-OZGAGRDG.js +71 -0
- package/chunks/loadedSettingsAdapter-RUTZVVIA.js +66 -0
- package/chunks/{loop-wakeup-CITGGQHA.js → loop-wakeup-G2EHBRGR.js} +5 -5
- package/chunks/{ls-R5WP4BGZ.js → ls-IDHUVSAG.js} +4 -4
- package/chunks/{lsp-GSICJMMW.js → lsp-FSRYXGFT.js} +2 -2
- package/chunks/{monitor-HKLRS2HQ.js → monitor-QVWEIXU3.js} +33 -26
- package/chunks/nonInteractiveCli-RV2WYPML.js +109 -0
- package/chunks/{notebook-edit-Y6SKSGTT.js → notebook-edit-B26W3FFH.js} +37 -34
- package/chunks/{openaiContentGenerator-J7G2FYJT.js → openaiContentGenerator-6TH7AZGQ.js} +15 -13
- package/chunks/pidfile-KW2QQJZI.js +73 -0
- package/chunks/{pt-TNZRNLQB.js → pt-2THT3YHA.js} +10 -9
- package/chunks/{qwenContentGenerator-5XIEM5GV.js → qwenContentGenerator-5IQAC7RN.js} +33 -27
- package/chunks/{qwenOAuth2-AG3PFFLZ.js → qwenOAuth2-LWLA6MQG.js} +5 -4
- package/chunks/{read-file-J7D552ZJ.js → read-file-CWFAHOI2.js} +11 -10
- package/chunks/{read-mcp-resource-DQQW7H7T.js → read-mcp-resource-PIJF24RO.js} +2 -2
- package/chunks/ripGrep-FTZGDKY4.js +60 -0
- package/chunks/{ru-NIAUBKCN.js → ru-Z67YJHBG.js} +10 -9
- package/chunks/{run-qwen-serve-SGEEVMXD.js → run-qwen-serve-FN2SW5ZI.js} +545 -97
- package/chunks/{scheduler-7CQI3S4Q.js → scheduler-BMS23O3I.js} +31 -25
- package/chunks/{send-message-EE4TWKVU.js → send-message-33PYFMCT.js} +20 -4
- package/chunks/serve-PXFYKL65.js +71 -0
- package/chunks/{server-4QMUWXPW.js → server-BRKALJ4F.js} +4132 -1175
- package/chunks/{session-NRO7UFOY.js → session-AQMISBP4.js} +205 -64
- package/chunks/{settings-SGWRDQSC.js → settings-JCPVUZMB.js} +35 -29
- package/chunks/{shell-62ANGIHL.js → shell-POHCRVN2.js} +31 -25
- package/chunks/{skill-VWAQAWW6.js → skill-QPEVHS6H.js} +13 -12
- package/chunks/spawnChannel-V3QT62TE.js +69 -0
- package/chunks/{src-KUV5J5Q2.js → src-IZSP7L6Y.js} +127 -32
- package/chunks/{startInteractiveUI-6EYJN3JV.js → startInteractiveUI-63KATISO.js} +16762 -16075
- package/chunks/{syntheticOutput-T5YHQ6S2.js → syntheticOutput-YOSWIHDJ.js} +3 -3
- package/chunks/{task-create-BLY7RHXX.js → task-create-NHS2NGB3.js} +9 -7
- package/chunks/{task-list-3QUYNVYR.js → task-list-5UIB564R.js} +7 -6
- package/chunks/{task-stop-U4RATK2V.js → task-stop-HGXZ2VZ3.js} +2 -2
- package/chunks/{task-update-U54O7KJX.js → task-update-IYYWUILG.js} +40 -7
- package/chunks/{team-create-LPOGCPM7.js → team-create-E5O2F3CA.js} +31 -25
- package/chunks/{team-delete-LKBYPASD.js → team-delete-FEKJCU4P.js} +7 -6
- package/chunks/team-plan-approval-2TU4YROB.js +202 -0
- package/chunks/theme-manager-37KOGPJL.js +64 -0
- package/chunks/{todoWrite-OYXKTVYN.js → todoWrite-TKMVZ2HT.js} +4 -4
- package/chunks/{tool-search-YPUFJ3ZQ.js → tool-search-4ZTGNSFI.js} +38 -11
- package/chunks/{trustedFolders-5B24TMEA.js → trustedFolders-RJ5WXJ6L.js} +32 -26
- package/chunks/{validateNonInterActiveAuth-BTDTYOVT.js → validateNonInterActiveAuth-ZWMHZAOK.js} +66 -55
- package/chunks/{web-fetch-EEB5LZYU.js → web-fetch-J4PIW36Q.js} +5 -4
- package/chunks/{workflow-LAWIW5LI.js → workflow-6PG2PC5M.js} +68 -39
- package/chunks/workspace-providers-status-4QIZN2W4.js +68 -0
- package/chunks/workspace-service-CYMCOEIO.js +78 -0
- package/chunks/{write-file-PCV226DJ.js → write-file-R354LGQF.js} +41 -40
- package/chunks/{zh-5EUYXASN.js → zh-SLZNSSZB.js} +32 -10
- package/chunks/{zh-TW-TR3XYGE5.js → zh-TW-P53C2SL5.js} +32 -10
- package/cli.js +6 -6
- package/locales/ca.js +15 -13
- package/locales/de.js +15 -13
- package/locales/en.js +52 -15
- package/locales/fr.js +15 -14
- package/locales/ja.js +15 -14
- package/locales/pt.js +15 -13
- package/locales/ru.js +15 -13
- package/locales/zh-TW.js +50 -14
- package/locales/zh.js +50 -14
- package/node_modules/@qwen-code/audio-capture/package.json +1 -1
- package/node_modules/@qwen-code/audio-capture/prebuilds/darwin-arm64/@qwen-code+audio-capture.node +0 -0
- package/node_modules/@qwen-code/audio-capture/prebuilds/darwin-x64/@qwen-code+audio-capture.node +0 -0
- package/node_modules/@qwen-code/audio-capture/prebuilds/win32-x64/@qwen-code+audio-capture.node +0 -0
- package/package.json +15 -6
- package/patches/chrome-devtools-mcp+1.4.0.patch +31 -0
- package/postinstall.js +50 -0
- package/web-shell/assets/{arc-DA7r8Ueo.js → arc-Bd3048nX.js} +1 -1
- package/web-shell/assets/{architectureDiagram-3BPJPVTR-ZDUxPtZ2.js → architectureDiagram-3BPJPVTR-DyzbzABx.js} +1 -1
- package/web-shell/assets/{blockDiagram-GPEHLZMM-vrtOf1kJ.js → blockDiagram-GPEHLZMM-CTjxm9Sy.js} +1 -1
- package/web-shell/assets/{c4Diagram-AAUBKEIU-BHFjzIi4.js → c4Diagram-AAUBKEIU-DSOFWNU6.js} +1 -1
- package/web-shell/assets/channel-oVoup_Ci.js +1 -0
- package/web-shell/assets/{chunk-2J33WTMH-mdeQVz59.js → chunk-2J33WTMH-D_PFdjo2.js} +1 -1
- package/web-shell/assets/{chunk-4BX2VUAB-BkKMlwBX.js → chunk-4BX2VUAB-52eG6wOT.js} +1 -1
- package/web-shell/assets/{chunk-55IACEB6-B7bnXNfu.js → chunk-55IACEB6-CGTZfKkC.js} +1 -1
- package/web-shell/assets/{chunk-727SXJPM-DGz8Mm6i.js → chunk-727SXJPM-CZ-qfRUm.js} +1 -1
- package/web-shell/assets/{chunk-AQP2D5EJ-BQAydUNk.js → chunk-AQP2D5EJ-B2dSDcqM.js} +1 -1
- package/web-shell/assets/{chunk-FMBD7UC4-GHr2LN_p.js → chunk-FMBD7UC4-Cfy3tyA0.js} +1 -1
- package/web-shell/assets/{chunk-ND2GUHAM-7R91lnUx.js → chunk-ND2GUHAM-CApNUpUq.js} +1 -1
- package/web-shell/assets/{chunk-QZHKN3VN-aTJD3lSQ.js → chunk-QZHKN3VN-CVBG8kgg.js} +1 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-B8WsaT2G.js +1 -0
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-B8WsaT2G.js +1 -0
- package/web-shell/assets/{cose-bilkent-S5V4N54A-BTf8t1RL.js → cose-bilkent-S5V4N54A-URd77-_-.js} +1 -1
- package/web-shell/assets/{dagre-BM42HDAG-_sgp3WuA.js → dagre-BM42HDAG-C07H4G9-.js} +1 -1
- package/web-shell/assets/{diagram-2AECGRRQ-CROtRy1w.js → diagram-2AECGRRQ-CYbpXrSn.js} +1 -1
- package/web-shell/assets/{diagram-5GNKFQAL-BqGRzwSc.js → diagram-5GNKFQAL-SI8s6fjX.js} +1 -1
- package/web-shell/assets/{diagram-KO2AKTUF-CMrcEtA7.js → diagram-KO2AKTUF-mBkC4RTW.js} +1 -1
- package/web-shell/assets/{diagram-LMA3HP47-BRydGNW5.js → diagram-LMA3HP47-CyBPDzWJ.js} +1 -1
- package/web-shell/assets/{diagram-OG6HWLK6-D0ilgNjV.js → diagram-OG6HWLK6-DwK7kBCu.js} +1 -1
- package/web-shell/assets/{erDiagram-TEJ5UH35-2lnQeJUM.js → erDiagram-TEJ5UH35-Ds1StEUd.js} +1 -1
- package/web-shell/assets/{flowDiagram-I6XJVG4X-C_ZMdQiC.js → flowDiagram-I6XJVG4X-BDC4-jHO.js} +1 -1
- package/web-shell/assets/{ganttDiagram-6RSMTGT7-Dw9V_Ny0.js → ganttDiagram-6RSMTGT7-CV2aHQqf.js} +1 -1
- package/web-shell/assets/{gitGraphDiagram-PVQCEYII-HDXI-F1B.js → gitGraphDiagram-PVQCEYII-B8RcuV_L.js} +1 -1
- package/web-shell/assets/index-B5WZ0qP1.js +717 -0
- package/web-shell/assets/index-CYE1IMd1.css +5 -0
- package/web-shell/assets/{infoDiagram-5YYISTIA-CuB8Ebua.js → infoDiagram-5YYISTIA-DUPoTf50.js} +1 -1
- package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-D_tyhVwh.js → ishikawaDiagram-YF4QCWOH-FDYOx9rf.js} +1 -1
- package/web-shell/assets/{journeyDiagram-JHISSGLW-CgCwJQNU.js → journeyDiagram-JHISSGLW-C5_ohMRp.js} +1 -1
- package/web-shell/assets/{kanban-definition-UN3LZRKU-PZUtcbPx.js → kanban-definition-UN3LZRKU-Bn4UnOMG.js} +1 -1
- package/web-shell/assets/{linear-CZqRdJIU.js → linear-Bl0pKQtY.js} +1 -1
- package/web-shell/assets/{mermaid.core-CPW_4UEF.js → mermaid.core-sevQFoji.js} +72 -72
- package/web-shell/assets/{mindmap-definition-RKZ34NQL-D_Y75ID7.js → mindmap-definition-RKZ34NQL-DSH4JZF9.js} +1 -1
- package/web-shell/assets/{pieDiagram-4H26LBE5-Q4dTyLeF.js → pieDiagram-4H26LBE5-acWvdQTD.js} +1 -1
- package/web-shell/assets/{quadrantDiagram-W4KKPZXB-ckw329Ft.js → quadrantDiagram-W4KKPZXB-DlggX4Sm.js} +1 -1
- package/web-shell/assets/{requirementDiagram-4Y6WPE33-DbVDm4It.js → requirementDiagram-4Y6WPE33--mMqwmV8.js} +1 -1
- package/web-shell/assets/{sankeyDiagram-5OEKKPKP-CHuZ_ecH.js → sankeyDiagram-5OEKKPKP-BtV9tZ77.js} +1 -1
- package/web-shell/assets/{sequenceDiagram-3UESZ5HK-DU2YSpq-.js → sequenceDiagram-3UESZ5HK-iDQzPFlj.js} +1 -1
- package/web-shell/assets/{stateDiagram-AJRCARHV-CA9PEBUo.js → stateDiagram-AJRCARHV-CsCyQLZ3.js} +1 -1
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-CPapECG9.js +1 -0
- package/web-shell/assets/{timeline-definition-PNZ67QCA-Bhlo4WVc.js → timeline-definition-PNZ67QCA-Dl0rnKvr.js} +1 -1
- package/web-shell/assets/{vennDiagram-CIIHVFJN-6xtPLsyl.js → vennDiagram-CIIHVFJN-qF7nTZzA.js} +1 -1
- package/web-shell/assets/{wardley-L42UT6IY-3eozmXPf.js → wardley-L42UT6IY-fWoK9i7F.js} +1 -1
- package/web-shell/assets/{wardleyDiagram-YWT4CUSO-BOn6hKss.js → wardleyDiagram-YWT4CUSO-pHGfkMnc.js} +1 -1
- package/web-shell/assets/{xychartDiagram-2RQKCTM6-BsP4-I_y.js → xychartDiagram-2RQKCTM6-3Doc4Trz.js} +1 -1
- package/web-shell/index.html +18 -2
- package/chunks/MaxSizedBox-QNF3EIGU.js +0 -63
- package/chunks/agent-headless-RQ5BTX3G.js +0 -56
- package/chunks/bridge-JL2PMCIW.js +0 -66
- package/chunks/chunk-5GOVVXEV.js +0 -73
- package/chunks/chunk-BC3C4F3Q.js +0 -40
- package/chunks/chunk-BW4KCQFD.js +0 -1103
- package/chunks/chunk-RKIZXJMB.js +0 -13
- package/chunks/contextCommand-WYU6OQ2F.js +0 -61
- package/chunks/daemon-status-provider-HH2EC5FI.js +0 -65
- package/chunks/headlessSafetyWarnings-TBE35GJ4.js +0 -55
- package/chunks/initializer-2Y7SLOKV.js +0 -61
- package/chunks/list-ZAFHZ7OS.js +0 -65
- package/chunks/loadedSettingsAdapter-6KJXD6M3.js +0 -60
- package/chunks/nonInteractiveCli-5W4GIZQM.js +0 -96
- package/chunks/ripGrep-IEIFIWP4.js +0 -54
- package/chunks/serve-V6GVZR6U.js +0 -65
- package/chunks/spawnChannel-3VHW5EPY.js +0 -63
- package/chunks/theme-manager-LYLGAERF.js +0 -58
- package/chunks/workspace-providers-status-PIAFVYHA.js +0 -62
- package/chunks/workspace-service-YAIOD4HG.js +0 -71
- package/web-shell/assets/channel-iRo68q4Q.js +0 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-iHF24a8X.js +0 -1
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-iHF24a8X.js +0 -1
- package/web-shell/assets/index-CHmzAWys.css +0 -5
- package/web-shell/assets/index-w6GTOHh1.js +0 -713
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-t1LRI0oY.js +0 -1
|
@@ -2,12 +2,15 @@
|
|
|
2
2
|
"use strict";
|
|
3
3
|
import {
|
|
4
4
|
MID_TURN_QUEUE_DRAIN_METHOD
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-EWALXUAD.js";
|
|
6
6
|
import {
|
|
7
7
|
DEFAULT_RING_SIZE,
|
|
8
8
|
EVENT_SCHEMA_VERSION,
|
|
9
9
|
EventBus
|
|
10
10
|
} from "./chunk-ALX6BUYW.js";
|
|
11
|
+
import {
|
|
12
|
+
defaultSpawnChannelFactory
|
|
13
|
+
} from "./chunk-PSFDB5FZ.js";
|
|
11
14
|
import {
|
|
12
15
|
MCP_RESTART_SERVER_DEADLINE_MS
|
|
13
16
|
} from "./chunk-P7M4GA57.js";
|
|
@@ -29,17 +32,11 @@ import {
|
|
|
29
32
|
SessionShellClientRequiredError,
|
|
30
33
|
SessionShellDisabledError,
|
|
31
34
|
WorkspaceMismatchError,
|
|
32
|
-
canonicalizeWorkspace,
|
|
33
35
|
isNotCurrentlyGeneratingCancelError
|
|
34
|
-
} from "./chunk-
|
|
35
|
-
import {
|
|
36
|
-
defaultSpawnChannelFactory
|
|
37
|
-
} from "./chunk-FXKVLFFY.js";
|
|
36
|
+
} from "./chunk-T22H4V4R.js";
|
|
38
37
|
import {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
RequestError
|
|
42
|
-
} from "./chunk-UFC57OYT.js";
|
|
38
|
+
canonicalizeWorkspace
|
|
39
|
+
} from "./chunk-SEZC2725.js";
|
|
43
40
|
import {
|
|
44
41
|
BridgeChannelClosedError,
|
|
45
42
|
BridgeTimeoutError,
|
|
@@ -48,15 +45,20 @@ import {
|
|
|
48
45
|
STATUS_SCHEMA_VERSION,
|
|
49
46
|
createIdleWorkspaceExtensionsStatus,
|
|
50
47
|
createIdleWorkspaceHooksStatus
|
|
51
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-M7BLWURA.js";
|
|
49
|
+
import {
|
|
50
|
+
ClientSideConnection,
|
|
51
|
+
PROTOCOL_VERSION,
|
|
52
|
+
RequestError
|
|
53
|
+
} from "./chunk-UFC57OYT.js";
|
|
52
54
|
import {
|
|
53
55
|
ShellExecutionService,
|
|
54
56
|
TrustGateError
|
|
55
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-A5OPLHFM.js";
|
|
56
58
|
import {
|
|
57
59
|
DAEMON_TRACEPARENT_META_KEY,
|
|
58
60
|
DAEMON_TRACESTATE_META_KEY
|
|
59
|
-
} from "./chunk-
|
|
61
|
+
} from "./chunk-UA6XBZT7.js";
|
|
60
62
|
import {
|
|
61
63
|
init_esbuild_shims
|
|
62
64
|
} from "./chunk-A4BMJM77.js";
|
|
@@ -1098,7 +1100,7 @@ function sliceLineRange(content, startLine, endLine) {
|
|
|
1098
1100
|
}
|
|
1099
1101
|
__name(sliceLineRange, "sliceLineRange");
|
|
1100
1102
|
var BridgeClient = class {
|
|
1101
|
-
constructor(resolveEntry, resolvePendingRestoreEvents, mediator, permissionTimeoutMs, maxPendingPerSession, fileSystem, onModelPromoted, onModePromoted) {
|
|
1103
|
+
constructor(resolveEntry, resolvePendingRestoreEvents, mediator, permissionTimeoutMs, maxPendingPerSession, fileSystem, onModelPromoted, onModePromoted, clientMcpSender) {
|
|
1102
1104
|
this.resolveEntry = resolveEntry;
|
|
1103
1105
|
this.resolvePendingRestoreEvents = resolvePendingRestoreEvents;
|
|
1104
1106
|
this.mediator = mediator;
|
|
@@ -1107,6 +1109,7 @@ var BridgeClient = class {
|
|
|
1107
1109
|
this.fileSystem = fileSystem;
|
|
1108
1110
|
this.onModelPromoted = onModelPromoted;
|
|
1109
1111
|
this.onModePromoted = onModePromoted;
|
|
1112
|
+
this.clientMcpSender = clientMcpSender;
|
|
1110
1113
|
}
|
|
1111
1114
|
static {
|
|
1112
1115
|
__name(this, "BridgeClient");
|
|
@@ -1253,6 +1256,9 @@ var BridgeClient = class {
|
|
|
1253
1256
|
* treats that as "drain unsupported" and stops asking.
|
|
1254
1257
|
*/
|
|
1255
1258
|
async extMethod(method, params) {
|
|
1259
|
+
if (method === SERVE_CONTROL_EXT_METHODS.clientMcpMessage) {
|
|
1260
|
+
return this.handleClientMcpMessage(params);
|
|
1261
|
+
}
|
|
1256
1262
|
if (method !== MID_TURN_QUEUE_DRAIN_METHOD) {
|
|
1257
1263
|
throw RequestError.methodNotFound(method);
|
|
1258
1264
|
}
|
|
@@ -1282,6 +1288,52 @@ var BridgeClient = class {
|
|
|
1282
1288
|
}
|
|
1283
1289
|
return { messages };
|
|
1284
1290
|
}
|
|
1291
|
+
/**
|
|
1292
|
+
* Reverse tool channel (issue #5626, Phase 2) — answer the child's
|
|
1293
|
+
* `qwen/control/client_mcp/message` ext-method. The child's session
|
|
1294
|
+
* `McpClientManager` calls this when its agent drives a client-hosted
|
|
1295
|
+
* (extension) MCP server: `params` carries the advertised `server` name and
|
|
1296
|
+
* the JSON-RPC `payload` (initialize / tools/list / tools/call / a
|
|
1297
|
+
* notification). We resolve the per-WS-connection sender via the injected
|
|
1298
|
+
* `clientMcpSender` lookup, deliver the payload over the daemon WS, and
|
|
1299
|
+
* return the correlated response as `{ payload }`.
|
|
1300
|
+
*
|
|
1301
|
+
* Rejects with ACP `methodNotFound` when no `clientMcpSender` is wired (Mode
|
|
1302
|
+
* A / tests can't host a client MCP server), and `invalidParams` when the
|
|
1303
|
+
* frame is malformed or the named server is no longer hosted (e.g. the
|
|
1304
|
+
* extension disconnected mid-turn) — the agent's `SdkControlClientTransport`
|
|
1305
|
+
* surfaces that as a transport error rather than hanging.
|
|
1306
|
+
*/
|
|
1307
|
+
async handleClientMcpMessage(params) {
|
|
1308
|
+
if (!this.clientMcpSender) {
|
|
1309
|
+
throw RequestError.methodNotFound(
|
|
1310
|
+
SERVE_CONTROL_EXT_METHODS.clientMcpMessage
|
|
1311
|
+
);
|
|
1312
|
+
}
|
|
1313
|
+
const server = params["server"];
|
|
1314
|
+
if (typeof server !== "string" || server.length === 0) {
|
|
1315
|
+
throw RequestError.invalidParams(
|
|
1316
|
+
void 0,
|
|
1317
|
+
"`server` must be a non-empty string"
|
|
1318
|
+
);
|
|
1319
|
+
}
|
|
1320
|
+
const payload = params["payload"];
|
|
1321
|
+
if (payload === null || typeof payload !== "object") {
|
|
1322
|
+
throw RequestError.invalidParams(
|
|
1323
|
+
void 0,
|
|
1324
|
+
"`payload` must be a JSON-RPC message object"
|
|
1325
|
+
);
|
|
1326
|
+
}
|
|
1327
|
+
const send = this.clientMcpSender(server);
|
|
1328
|
+
if (!send) {
|
|
1329
|
+
throw RequestError.invalidParams(
|
|
1330
|
+
void 0,
|
|
1331
|
+
`client-hosted MCP server '${server}' is not currently connected`
|
|
1332
|
+
);
|
|
1333
|
+
}
|
|
1334
|
+
const response = await send(payload);
|
|
1335
|
+
return { payload: response };
|
|
1336
|
+
}
|
|
1285
1337
|
/**
|
|
1286
1338
|
* Handle child->bridge ACP `extNotification` calls. Six methods are
|
|
1287
1339
|
* recognized — `qwen/notify/session/model-update`,
|
|
@@ -1857,6 +1909,24 @@ function extractPermissionResponseMetadata(response) {
|
|
|
1857
1909
|
return void 0;
|
|
1858
1910
|
}
|
|
1859
1911
|
__name(extractPermissionResponseMetadata, "extractPermissionResponseMetadata");
|
|
1912
|
+
function parseWorkspaceMemoryRememberResult(response) {
|
|
1913
|
+
if (response === null || typeof response !== "object" || Array.isArray(response)) {
|
|
1914
|
+
throw new Error("Malformed workspace memory remember response");
|
|
1915
|
+
}
|
|
1916
|
+
const record = response;
|
|
1917
|
+
const summary = record["summary"];
|
|
1918
|
+
const filesTouched = record["filesTouched"];
|
|
1919
|
+
const touchedScopes = record["touchedScopes"];
|
|
1920
|
+
if (summary !== void 0 && typeof summary !== "string" || !Array.isArray(filesTouched) || !filesTouched.every((file) => typeof file === "string") || !Array.isArray(touchedScopes) || !touchedScopes.every((scope) => scope === "user" || scope === "project")) {
|
|
1921
|
+
throw new Error("Malformed workspace memory remember response");
|
|
1922
|
+
}
|
|
1923
|
+
return {
|
|
1924
|
+
...summary === void 0 ? {} : { summary },
|
|
1925
|
+
filesTouched,
|
|
1926
|
+
touchedScopes
|
|
1927
|
+
};
|
|
1928
|
+
}
|
|
1929
|
+
__name(parseWorkspaceMemoryRememberResult, "parseWorkspaceMemoryRememberResult");
|
|
1860
1930
|
function echoPromptToSessionBus(entry, req, originatorClientId) {
|
|
1861
1931
|
const prompt = req.prompt;
|
|
1862
1932
|
if (!Array.isArray(prompt) || prompt.length === 0) return;
|
|
@@ -1911,15 +1981,18 @@ function broadcastPromptCancelledOnce(entry, sessionId, originatorClientId, reas
|
|
|
1911
1981
|
}
|
|
1912
1982
|
__name(broadcastPromptCancelledOnce, "broadcastPromptCancelledOnce");
|
|
1913
1983
|
function broadcastTurnComplete(entry, sessionId, promptResult, promptId, originatorClientId) {
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1984
|
+
try {
|
|
1985
|
+
entry.events.publish({
|
|
1986
|
+
type: "turn_complete",
|
|
1987
|
+
data: {
|
|
1988
|
+
sessionId,
|
|
1989
|
+
stopReason: promptResult.stopReason ?? "end_turn",
|
|
1990
|
+
...promptId ? { promptId } : {}
|
|
1991
|
+
},
|
|
1992
|
+
...originatorClientId ? { originatorClientId } : {}
|
|
1993
|
+
});
|
|
1994
|
+
} catch {
|
|
1995
|
+
}
|
|
1923
1996
|
}
|
|
1924
1997
|
__name(broadcastTurnComplete, "broadcastTurnComplete");
|
|
1925
1998
|
function extractErrorMessage(err) {
|
|
@@ -1962,16 +2035,19 @@ function broadcastTurnError(entry, sessionId, err, promptId, originatorClientId)
|
|
|
1962
2035
|
const message = extractErrorMessage(err);
|
|
1963
2036
|
const code = extractErrorCode(err);
|
|
1964
2037
|
entry.retryAllowed = true;
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
2038
|
+
try {
|
|
2039
|
+
entry.events.publish({
|
|
2040
|
+
type: "turn_error",
|
|
2041
|
+
data: {
|
|
2042
|
+
sessionId,
|
|
2043
|
+
message,
|
|
2044
|
+
...code ? { code } : {},
|
|
2045
|
+
...promptId ? { promptId } : {}
|
|
2046
|
+
},
|
|
2047
|
+
...originatorClientId ? { originatorClientId } : {}
|
|
2048
|
+
});
|
|
2049
|
+
} catch {
|
|
2050
|
+
}
|
|
1975
2051
|
}
|
|
1976
2052
|
__name(broadcastTurnError, "broadcastTurnError");
|
|
1977
2053
|
function hasControlCharacter(value) {
|
|
@@ -1984,11 +2060,27 @@ function hasControlCharacter(value) {
|
|
|
1984
2060
|
return false;
|
|
1985
2061
|
}
|
|
1986
2062
|
__name(hasControlCharacter, "hasControlCharacter");
|
|
2063
|
+
function extractPromptText(prompt) {
|
|
2064
|
+
if (!Array.isArray(prompt)) return "";
|
|
2065
|
+
let hasImage = false;
|
|
2066
|
+
for (const block of prompt) {
|
|
2067
|
+
if (block["type"] === "image") {
|
|
2068
|
+
hasImage = true;
|
|
2069
|
+
}
|
|
2070
|
+
if (block["type"] === "text" && typeof block["text"] === "string" && block["text"].length > 0) {
|
|
2071
|
+
return block["text"];
|
|
2072
|
+
}
|
|
2073
|
+
}
|
|
2074
|
+
return hasImage ? "[image]" : "";
|
|
2075
|
+
}
|
|
2076
|
+
__name(extractPromptText, "extractPromptText");
|
|
1987
2077
|
var DEFAULT_INIT_TIMEOUT_MS = 1e4;
|
|
1988
2078
|
var PERSIST_TIMEOUT_MS = 5e3;
|
|
1989
2079
|
var MCP_RESTART_TIMEOUT_MS = 3e5;
|
|
2080
|
+
var WORKSPACE_MEMORY_REMEMBER_TIMEOUT_MS = 3e5;
|
|
1990
2081
|
var MCP_OAUTH_TIMEOUT_MS = 6e5;
|
|
1991
2082
|
var DAEMON_RETRY_META_KEY = "qwen.daemon.retry";
|
|
2083
|
+
var DAEMON_CONTINUE_META_KEY = "qwen.daemon.continueLastTurn";
|
|
1992
2084
|
var SESSION_RECAP_TIMEOUT_MS = 6e4;
|
|
1993
2085
|
var SESSION_BTW_TIMEOUT_MS = 6e4;
|
|
1994
2086
|
var SHELL_COMMAND_TIMEOUT_MS = 12e4;
|
|
@@ -2121,7 +2213,7 @@ function createAcpSessionBridge(opts) {
|
|
|
2121
2213
|
cancelIdleTimer();
|
|
2122
2214
|
idleTimer = setTimeout(() => {
|
|
2123
2215
|
idleTimer = void 0;
|
|
2124
|
-
if (ci
|
|
2216
|
+
if (hasNoChannelWork(ci)) {
|
|
2125
2217
|
writeStderrLine(
|
|
2126
2218
|
`qwen serve: idle timeout (${timeoutMs}ms) expired, killing channel`
|
|
2127
2219
|
);
|
|
@@ -2131,6 +2223,33 @@ function createAcpSessionBridge(opts) {
|
|
|
2131
2223
|
idleTimer.unref();
|
|
2132
2224
|
}
|
|
2133
2225
|
__name(startIdleTimer, "startIdleTimer");
|
|
2226
|
+
function hasNoChannelWork(ci, opts2) {
|
|
2227
|
+
const inFlightSpawnCount = ci.sessionSpawnsInFlight - (opts2?.ignoreCurrentSessionSpawn === true ? 1 : 0);
|
|
2228
|
+
const pendingRestoreCount = ci.pendingRestoreIds.size - (opts2?.ignoreRestoreId !== void 0 && ci.pendingRestoreIds.has(opts2.ignoreRestoreId) ? 1 : 0);
|
|
2229
|
+
return ci.sessionIds.size === 0 && pendingRestoreCount === 0 && ci.workspaceControlInFlight === 0 && inFlightSpawnCount === 0;
|
|
2230
|
+
}
|
|
2231
|
+
__name(hasNoChannelWork, "hasNoChannelWork");
|
|
2232
|
+
async function reapPendingEmptyChannel(ci) {
|
|
2233
|
+
if (!ci.emptyReapPending || !hasNoChannelWork(ci)) return;
|
|
2234
|
+
ci.emptyReapPending = false;
|
|
2235
|
+
ci.isDying = true;
|
|
2236
|
+
await ci.channel.kill().catch(() => {
|
|
2237
|
+
});
|
|
2238
|
+
}
|
|
2239
|
+
__name(reapPendingEmptyChannel, "reapPendingEmptyChannel");
|
|
2240
|
+
async function withWorkspaceControl(ci, fn) {
|
|
2241
|
+
ci.workspaceControlInFlight++;
|
|
2242
|
+
try {
|
|
2243
|
+
return await fn();
|
|
2244
|
+
} finally {
|
|
2245
|
+
ci.workspaceControlInFlight = Math.max(
|
|
2246
|
+
0,
|
|
2247
|
+
ci.workspaceControlInFlight - 1
|
|
2248
|
+
);
|
|
2249
|
+
await reapPendingEmptyChannel(ci);
|
|
2250
|
+
}
|
|
2251
|
+
}
|
|
2252
|
+
__name(withWorkspaceControl, "withWorkspaceControl");
|
|
2134
2253
|
function startSessionReaper() {
|
|
2135
2254
|
if (sessionReapIntervalMs <= 0 || sessionIdleTimeoutMs <= 0) {
|
|
2136
2255
|
writeStderrLine("qwen serve: session reaper disabled");
|
|
@@ -2301,7 +2420,14 @@ function createAcpSessionBridge(opts) {
|
|
|
2301
2420
|
},
|
|
2302
2421
|
originator
|
|
2303
2422
|
);
|
|
2304
|
-
}
|
|
2423
|
+
},
|
|
2424
|
+
// Reverse tool channel (issue #5626, Phase 2): forward the optional
|
|
2425
|
+
// client-hosted-MCP sender lookup so `BridgeClient.extMethod` can
|
|
2426
|
+
// answer `qwen/control/client_mcp/message` from the child by reaching
|
|
2427
|
+
// the per-WS-connection `ClientMcpRegistrar`. Omitted callers (tests,
|
|
2428
|
+
// Mode A) never host a client MCP server, so the method stays
|
|
2429
|
+
// unreachable.
|
|
2430
|
+
opts.clientMcpSender
|
|
2305
2431
|
);
|
|
2306
2432
|
const connection = new ClientSideConnection(() => client, channel.stream);
|
|
2307
2433
|
const info = {
|
|
@@ -2310,6 +2436,9 @@ function createAcpSessionBridge(opts) {
|
|
|
2310
2436
|
client,
|
|
2311
2437
|
sessionIds: /* @__PURE__ */ new Set(),
|
|
2312
2438
|
pendingRestoreIds: /* @__PURE__ */ new Set(),
|
|
2439
|
+
sessionSpawnsInFlight: 0,
|
|
2440
|
+
workspaceControlInFlight: 0,
|
|
2441
|
+
emptyReapPending: false,
|
|
2313
2442
|
isDying: false,
|
|
2314
2443
|
handshakeComplete: false
|
|
2315
2444
|
};
|
|
@@ -2413,63 +2542,75 @@ function createAcpSessionBridge(opts) {
|
|
|
2413
2542
|
__name(ensureChannel, "ensureChannel");
|
|
2414
2543
|
async function doSpawn(modelServiceId, effectiveScope, requestedClientId) {
|
|
2415
2544
|
const ci = await ensureChannel();
|
|
2545
|
+
ci.sessionSpawnsInFlight++;
|
|
2546
|
+
let sessionRegistered = false;
|
|
2416
2547
|
let newSessionResp;
|
|
2417
2548
|
try {
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2549
|
+
try {
|
|
2550
|
+
newSessionResp = await telemetry.withSpan(
|
|
2551
|
+
"session.new",
|
|
2552
|
+
{
|
|
2553
|
+
"qwen-code.daemon.bridge.operation": "session.new",
|
|
2554
|
+
"qwen-code.daemon.session_scope": effectiveScope
|
|
2555
|
+
},
|
|
2556
|
+
async () => await withTimeout(
|
|
2557
|
+
ci.connection.newSession({
|
|
2558
|
+
cwd: boundWorkspace,
|
|
2559
|
+
mcpServers: []
|
|
2560
|
+
}),
|
|
2561
|
+
initTimeoutMs,
|
|
2562
|
+
"newSession"
|
|
2563
|
+
)
|
|
2564
|
+
);
|
|
2565
|
+
} catch (err) {
|
|
2566
|
+
if (hasNoChannelWork(ci, { ignoreCurrentSessionSpawn: true })) {
|
|
2567
|
+
ci.isDying = true;
|
|
2568
|
+
await ci.channel.kill().catch(() => {
|
|
2569
|
+
});
|
|
2570
|
+
} else {
|
|
2571
|
+
ci.emptyReapPending = true;
|
|
2572
|
+
}
|
|
2573
|
+
throw err;
|
|
2574
|
+
}
|
|
2575
|
+
if (shuttingDown) {
|
|
2576
|
+
throw new Error("AcpSessionBridge is shutting down");
|
|
2577
|
+
}
|
|
2578
|
+
const entry = createSessionEntry(
|
|
2579
|
+
ci,
|
|
2580
|
+
newSessionResp.sessionId,
|
|
2581
|
+
boundWorkspace
|
|
2432
2582
|
);
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2583
|
+
sessionRegistered = true;
|
|
2584
|
+
seedSnapshotCaches(entry, newSessionResp);
|
|
2585
|
+
const clientId = registerClient(entry, requestedClientId);
|
|
2586
|
+
if (effectiveScope === "single" && !defaultEntry) defaultEntry = entry;
|
|
2587
|
+
if (modelServiceId) {
|
|
2588
|
+
await applyModelServiceId(
|
|
2589
|
+
entry,
|
|
2590
|
+
modelServiceId,
|
|
2591
|
+
initTimeoutMs,
|
|
2592
|
+
clientId
|
|
2593
|
+
).catch(() => {
|
|
2437
2594
|
});
|
|
2438
2595
|
}
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
initTimeoutMs,
|
|
2457
|
-
clientId
|
|
2458
|
-
).catch(() => {
|
|
2459
|
-
});
|
|
2460
|
-
}
|
|
2461
|
-
if (!byId.has(entry.sessionId)) {
|
|
2462
|
-
throw new Error(
|
|
2463
|
-
`Session ${entry.sessionId} died during model-switch initialization`
|
|
2464
|
-
);
|
|
2596
|
+
if (!byId.has(entry.sessionId)) {
|
|
2597
|
+
throw new Error(
|
|
2598
|
+
`Session ${entry.sessionId} died during model-switch initialization`
|
|
2599
|
+
);
|
|
2600
|
+
}
|
|
2601
|
+
return {
|
|
2602
|
+
sessionId: entry.sessionId,
|
|
2603
|
+
workspaceCwd: entry.workspaceCwd,
|
|
2604
|
+
attached: false,
|
|
2605
|
+
clientId,
|
|
2606
|
+
createdAt: entry.createdAt
|
|
2607
|
+
};
|
|
2608
|
+
} finally {
|
|
2609
|
+
ci.sessionSpawnsInFlight = Math.max(0, ci.sessionSpawnsInFlight - 1);
|
|
2610
|
+
if (!sessionRegistered) {
|
|
2611
|
+
await reapPendingEmptyChannel(ci);
|
|
2612
|
+
}
|
|
2465
2613
|
}
|
|
2466
|
-
return {
|
|
2467
|
-
sessionId: entry.sessionId,
|
|
2468
|
-
workspaceCwd: entry.workspaceCwd,
|
|
2469
|
-
attached: false,
|
|
2470
|
-
clientId,
|
|
2471
|
-
createdAt: entry.createdAt
|
|
2472
|
-
};
|
|
2473
2614
|
}
|
|
2474
2615
|
__name(doSpawn, "doSpawn");
|
|
2475
2616
|
async function applyModelServiceId(entry, modelId, timeoutMs, originatorClientId) {
|
|
@@ -2608,13 +2749,24 @@ function createAcpSessionBridge(opts) {
|
|
|
2608
2749
|
]);
|
|
2609
2750
|
return response;
|
|
2610
2751
|
}, "requestSessionStatus");
|
|
2611
|
-
const notifyAgentSessionClose = /* @__PURE__ */ __name(async (entry, ci, label) => {
|
|
2612
|
-
if (!ci || ci.channel !== entry.channel)
|
|
2752
|
+
const notifyAgentSessionClose = /* @__PURE__ */ __name(async (entry, ci, label, opts2) => {
|
|
2753
|
+
if (!ci || ci.channel !== entry.channel) {
|
|
2754
|
+
if (opts2?.throwOnFailure === true) {
|
|
2755
|
+
writeStderrLine(
|
|
2756
|
+
`qwen serve: ${label} ACP session close channel unavailable for session ${JSON.stringify(entry.sessionId)}; agent close skipped`
|
|
2757
|
+
);
|
|
2758
|
+
throw new Error(
|
|
2759
|
+
`ACP session close channel unavailable for ${entry.sessionId}`
|
|
2760
|
+
);
|
|
2761
|
+
}
|
|
2762
|
+
return;
|
|
2763
|
+
}
|
|
2613
2764
|
try {
|
|
2614
2765
|
await Promise.race([
|
|
2615
2766
|
withTimeout(
|
|
2616
2767
|
entry.connection.extMethod(SERVE_CONTROL_EXT_METHODS.sessionClose, {
|
|
2617
|
-
sessionId: entry.sessionId
|
|
2768
|
+
sessionId: entry.sessionId,
|
|
2769
|
+
...opts2?.requireFlush === true ? { requireFlush: true } : {}
|
|
2618
2770
|
}),
|
|
2619
2771
|
initTimeoutMs,
|
|
2620
2772
|
SERVE_CONTROL_EXT_METHODS.sessionClose
|
|
@@ -2627,6 +2779,9 @@ function createAcpSessionBridge(opts) {
|
|
|
2627
2779
|
err instanceof Error ? err.message : err
|
|
2628
2780
|
)}`
|
|
2629
2781
|
);
|
|
2782
|
+
if (opts2?.throwOnFailure === true) {
|
|
2783
|
+
throw err;
|
|
2784
|
+
}
|
|
2630
2785
|
}
|
|
2631
2786
|
}, "notifyAgentSessionClose");
|
|
2632
2787
|
const broadcastWorkspaceEvent = /* @__PURE__ */ __name((envelope, skipSessionId) => {
|
|
@@ -2757,6 +2912,7 @@ function createAcpSessionBridge(opts) {
|
|
|
2757
2912
|
events,
|
|
2758
2913
|
promptQueue: Promise.resolve(),
|
|
2759
2914
|
pendingPromptCount: 0,
|
|
2915
|
+
pendingPromptList: [],
|
|
2760
2916
|
midTurnMessageQueue: [],
|
|
2761
2917
|
modelChangeQueue: Promise.resolve(),
|
|
2762
2918
|
approvalModeQueue: Promise.resolve(),
|
|
@@ -2928,10 +3084,11 @@ function createAcpSessionBridge(opts) {
|
|
|
2928
3084
|
if (isAcpSessionResourceNotFound(err, req.sessionId)) {
|
|
2929
3085
|
throw new SessionNotFoundError(req.sessionId);
|
|
2930
3086
|
}
|
|
2931
|
-
|
|
3087
|
+
ci.emptyReapPending = hasNoChannelWork(ci, {
|
|
3088
|
+
ignoreRestoreId: req.sessionId
|
|
3089
|
+
});
|
|
3090
|
+
if (ci.emptyReapPending) {
|
|
2932
3091
|
ci.isDying = true;
|
|
2933
|
-
await ci.channel.kill().catch(() => {
|
|
2934
|
-
});
|
|
2935
3092
|
}
|
|
2936
3093
|
throw err;
|
|
2937
3094
|
}
|
|
@@ -2982,7 +3139,7 @@ function createAcpSessionBridge(opts) {
|
|
|
2982
3139
|
hasActivePrompt: entry.promptActive,
|
|
2983
3140
|
...replayFieldsFor(entry, action)
|
|
2984
3141
|
};
|
|
2985
|
-
})().finally(() => {
|
|
3142
|
+
})().finally(async () => {
|
|
2986
3143
|
ci?.pendingRestoreIds.delete(req.sessionId);
|
|
2987
3144
|
ci?.client.clearRestoreInFlight(req.sessionId);
|
|
2988
3145
|
pendingRestoreEvents.delete(req.sessionId);
|
|
@@ -2990,6 +3147,9 @@ function createAcpSessionBridge(opts) {
|
|
|
2990
3147
|
restoreEvents.close();
|
|
2991
3148
|
ci?.client.markSessionClosed(req.sessionId);
|
|
2992
3149
|
}
|
|
3150
|
+
if (ci) {
|
|
3151
|
+
await reapPendingEmptyChannel(ci);
|
|
3152
|
+
}
|
|
2993
3153
|
});
|
|
2994
3154
|
inFlightRestores.set(req.sessionId, { action, promise, coalesceState });
|
|
2995
3155
|
try {
|
|
@@ -3022,6 +3182,13 @@ function createAcpSessionBridge(opts) {
|
|
|
3022
3182
|
`qwen serve: closeSession channelInfoForEntry returned undefined for session ${JSON.stringify(sessionId)} \u2014 channel cleanup skipped (entry's channel already torn down)`
|
|
3023
3183
|
);
|
|
3024
3184
|
}
|
|
3185
|
+
const requireAgentClose = closeOpts?.requireAgentClose === true;
|
|
3186
|
+
if (requireAgentClose) {
|
|
3187
|
+
await notifyAgentSessionClose(entry, ci, "closeSession", {
|
|
3188
|
+
throwOnFailure: true,
|
|
3189
|
+
requireFlush: true
|
|
3190
|
+
});
|
|
3191
|
+
}
|
|
3025
3192
|
if (ci && ci.channel === entry.channel) {
|
|
3026
3193
|
ci.sessionIds.delete(sessionId);
|
|
3027
3194
|
}
|
|
@@ -3052,7 +3219,9 @@ function createAcpSessionBridge(opts) {
|
|
|
3052
3219
|
} catch {
|
|
3053
3220
|
}
|
|
3054
3221
|
entry.events.close();
|
|
3055
|
-
|
|
3222
|
+
if (!requireAgentClose) {
|
|
3223
|
+
await notifyAgentSessionClose(entry, ci, "closeSession");
|
|
3224
|
+
}
|
|
3056
3225
|
try {
|
|
3057
3226
|
await telemetry.withSpan(
|
|
3058
3227
|
"session.close.cancel_active_prompt",
|
|
@@ -3064,13 +3233,16 @@ function createAcpSessionBridge(opts) {
|
|
|
3064
3233
|
);
|
|
3065
3234
|
} catch {
|
|
3066
3235
|
}
|
|
3067
|
-
if (ci && ci
|
|
3068
|
-
await
|
|
3236
|
+
if (ci && hasNoChannelWork(ci)) {
|
|
3237
|
+
await reapPendingEmptyChannel(ci);
|
|
3238
|
+
if (!ci.isDying) {
|
|
3239
|
+
await startIdleTimer(ci, `closeSession "${sessionId}"`);
|
|
3240
|
+
}
|
|
3069
3241
|
}
|
|
3070
3242
|
}
|
|
3071
3243
|
__name(closeSessionImpl, "closeSessionImpl");
|
|
3072
3244
|
startSessionReaper();
|
|
3073
|
-
|
|
3245
|
+
const bridgeApi = {
|
|
3074
3246
|
getDaemonStatusSnapshot() {
|
|
3075
3247
|
return {
|
|
3076
3248
|
limits: {
|
|
@@ -3234,10 +3406,60 @@ function createAcpSessionBridge(opts) {
|
|
|
3234
3406
|
promptSlotReleased = true;
|
|
3235
3407
|
entry.pendingPromptCount = Math.max(0, entry.pendingPromptCount - 1);
|
|
3236
3408
|
}, "releasePromptSlot");
|
|
3409
|
+
const promptId = context?.promptId ?? randomUUID2();
|
|
3410
|
+
const isQueued = entry.pendingPromptCount > 1;
|
|
3411
|
+
const pendingAbort = new AbortController();
|
|
3412
|
+
if (signal) {
|
|
3413
|
+
if (signal.aborted) {
|
|
3414
|
+
pendingAbort.abort(signal.reason);
|
|
3415
|
+
} else {
|
|
3416
|
+
signal.addEventListener(
|
|
3417
|
+
"abort",
|
|
3418
|
+
() => pendingAbort.abort(signal.reason),
|
|
3419
|
+
{ once: true }
|
|
3420
|
+
);
|
|
3421
|
+
}
|
|
3422
|
+
}
|
|
3423
|
+
const pendingEntry = {
|
|
3424
|
+
promptId,
|
|
3425
|
+
queuedAt,
|
|
3426
|
+
...originatorClientId !== void 0 ? { originatorClientId } : {},
|
|
3427
|
+
text: extractPromptText(req.prompt),
|
|
3428
|
+
abortController: pendingAbort,
|
|
3429
|
+
state: isQueued ? "queued" : "running"
|
|
3430
|
+
};
|
|
3431
|
+
entry.pendingPromptList.push(pendingEntry);
|
|
3432
|
+
if (isQueued) {
|
|
3433
|
+
entry.events.publish({
|
|
3434
|
+
type: "pending_prompt_added",
|
|
3435
|
+
data: {
|
|
3436
|
+
sessionId,
|
|
3437
|
+
promptId: pendingEntry.promptId,
|
|
3438
|
+
text: pendingEntry.text,
|
|
3439
|
+
queuedAt: pendingEntry.queuedAt
|
|
3440
|
+
},
|
|
3441
|
+
...originatorClientId ? { originatorClientId } : {}
|
|
3442
|
+
});
|
|
3443
|
+
}
|
|
3237
3444
|
const result = entry.promptQueue.then(
|
|
3238
3445
|
() => telemetry.runWithContext(capturedContext, async () => {
|
|
3239
3446
|
const queueWaitMs = Date.now() - queuedAt;
|
|
3240
3447
|
telemetry.metrics?.promptQueueWait(queueWaitMs);
|
|
3448
|
+
if (pendingAbort.signal.aborted) {
|
|
3449
|
+
throw new DOMException("Prompt aborted", "AbortError");
|
|
3450
|
+
}
|
|
3451
|
+
if (pendingEntry.state === "queued") {
|
|
3452
|
+
pendingEntry.state = "running";
|
|
3453
|
+
entry.events.publish({
|
|
3454
|
+
type: "pending_prompt_started",
|
|
3455
|
+
data: {
|
|
3456
|
+
sessionId,
|
|
3457
|
+
promptId: pendingEntry.promptId,
|
|
3458
|
+
text: pendingEntry.text
|
|
3459
|
+
},
|
|
3460
|
+
...originatorClientId ? { originatorClientId } : {}
|
|
3461
|
+
});
|
|
3462
|
+
}
|
|
3241
3463
|
const dispatchStartMs = Date.now();
|
|
3242
3464
|
try {
|
|
3243
3465
|
return await telemetry.withSpan(
|
|
@@ -3255,13 +3477,11 @@ function createAcpSessionBridge(opts) {
|
|
|
3255
3477
|
sessionId
|
|
3256
3478
|
}
|
|
3257
3479
|
);
|
|
3258
|
-
if (signal?.aborted) {
|
|
3259
|
-
throw new DOMException("Prompt aborted", "AbortError");
|
|
3260
|
-
}
|
|
3261
3480
|
assertLivePromptEntry(sessionId, entry);
|
|
3262
3481
|
const requestedRetry = req.retry === true;
|
|
3263
3482
|
const isRetry = requestedRetry && entry.retryAllowed;
|
|
3264
3483
|
entry.retryAllowed = false;
|
|
3484
|
+
const isContinue = context?.continue === true;
|
|
3265
3485
|
const promptRequest = (() => {
|
|
3266
3486
|
const copy = {
|
|
3267
3487
|
...normalized
|
|
@@ -3269,9 +3489,13 @@ function createAcpSessionBridge(opts) {
|
|
|
3269
3489
|
delete copy.retry;
|
|
3270
3490
|
const meta = copy._meta && typeof copy._meta === "object" ? { ...copy._meta } : {};
|
|
3271
3491
|
delete meta[DAEMON_RETRY_META_KEY];
|
|
3492
|
+
delete meta[DAEMON_CONTINUE_META_KEY];
|
|
3272
3493
|
if (isRetry) {
|
|
3273
3494
|
meta[DAEMON_RETRY_META_KEY] = true;
|
|
3274
3495
|
}
|
|
3496
|
+
if (isContinue) {
|
|
3497
|
+
meta[DAEMON_CONTINUE_META_KEY] = true;
|
|
3498
|
+
}
|
|
3275
3499
|
if (Object.keys(meta).length > 0) {
|
|
3276
3500
|
copy._meta = meta;
|
|
3277
3501
|
} else {
|
|
@@ -3290,7 +3514,7 @@ function createAcpSessionBridge(opts) {
|
|
|
3290
3514
|
}
|
|
3291
3515
|
try {
|
|
3292
3516
|
entry.cancelBroadcast = false;
|
|
3293
|
-
if (!isRetry) {
|
|
3517
|
+
if (!isRetry && !isContinue) {
|
|
3294
3518
|
echoPromptToSessionBus(
|
|
3295
3519
|
entry,
|
|
3296
3520
|
promptRequest,
|
|
@@ -3332,6 +3556,12 @@ function createAcpSessionBridge(opts) {
|
|
|
3332
3556
|
() => {
|
|
3333
3557
|
},
|
|
3334
3558
|
(err) => {
|
|
3559
|
+
if (err instanceof DOMException && err.name === "AbortError" && pendingEntry.state === "queued") {
|
|
3560
|
+
writeStderrLine(
|
|
3561
|
+
`sendPrompt: queued prompt removed before agent forward for session ${sessionId}`
|
|
3562
|
+
);
|
|
3563
|
+
return;
|
|
3564
|
+
}
|
|
3335
3565
|
writeStderrLine(
|
|
3336
3566
|
`sendPrompt: forward failed for session ${sessionId}: ${extractErrorMessage(err)}`
|
|
3337
3567
|
);
|
|
@@ -3342,12 +3572,15 @@ function createAcpSessionBridge(opts) {
|
|
|
3342
3572
|
"forward_failed"
|
|
3343
3573
|
);
|
|
3344
3574
|
cancelPendingForSession(sessionId);
|
|
3345
|
-
entry.connection.cancel({ sessionId }).catch(() => {
|
|
3575
|
+
entry.connection.cancel({ sessionId }).catch((err2) => {
|
|
3576
|
+
writeStderrLine(
|
|
3577
|
+
`[pending-prompt] cancel forward failed after prompt abort session=${sessionId}: ${extractErrorMessage(err2)}`
|
|
3578
|
+
);
|
|
3346
3579
|
});
|
|
3347
3580
|
}
|
|
3348
3581
|
).catch(() => {
|
|
3349
3582
|
});
|
|
3350
|
-
|
|
3583
|
+
const abortSignal = pendingAbort.signal;
|
|
3351
3584
|
const onAbort = /* @__PURE__ */ __name(() => {
|
|
3352
3585
|
broadcastPromptCancelledOnce(
|
|
3353
3586
|
entry,
|
|
@@ -3355,15 +3588,22 @@ function createAcpSessionBridge(opts) {
|
|
|
3355
3588
|
originatorClientId
|
|
3356
3589
|
);
|
|
3357
3590
|
cancelPendingForSession(sessionId);
|
|
3358
|
-
entry.connection.cancel({ sessionId }).catch(() => {
|
|
3591
|
+
entry.connection.cancel({ sessionId }).catch((err) => {
|
|
3592
|
+
writeStderrLine(
|
|
3593
|
+
`[pending-prompt] cancel forward failed after removePendingPrompt session=${sessionId}: ${extractErrorMessage(err)}`
|
|
3594
|
+
);
|
|
3359
3595
|
});
|
|
3360
3596
|
}, "onAbort");
|
|
3361
|
-
if (
|
|
3597
|
+
if (abortSignal.aborted) {
|
|
3362
3598
|
onAbort();
|
|
3363
3599
|
} else {
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3600
|
+
abortSignal.addEventListener("abort", onAbort, {
|
|
3601
|
+
once: true
|
|
3602
|
+
});
|
|
3603
|
+
if (abortSignal.aborted) onAbort();
|
|
3604
|
+
racedPromise.finally(
|
|
3605
|
+
() => abortSignal.removeEventListener("abort", onAbort)
|
|
3606
|
+
).catch(() => {
|
|
3367
3607
|
});
|
|
3368
3608
|
}
|
|
3369
3609
|
return racedPromise;
|
|
@@ -3374,14 +3614,13 @@ function createAcpSessionBridge(opts) {
|
|
|
3374
3614
|
}
|
|
3375
3615
|
})
|
|
3376
3616
|
);
|
|
3377
|
-
const promptId = context?.promptId;
|
|
3378
3617
|
result.then(
|
|
3379
3618
|
(promptResult) => {
|
|
3380
3619
|
broadcastTurnComplete(
|
|
3381
3620
|
entry,
|
|
3382
3621
|
sessionId,
|
|
3383
3622
|
promptResult,
|
|
3384
|
-
promptId,
|
|
3623
|
+
pendingEntry.promptId,
|
|
3385
3624
|
originatorClientId
|
|
3386
3625
|
);
|
|
3387
3626
|
},
|
|
@@ -3391,7 +3630,7 @@ function createAcpSessionBridge(opts) {
|
|
|
3391
3630
|
entry,
|
|
3392
3631
|
sessionId,
|
|
3393
3632
|
err,
|
|
3394
|
-
promptId,
|
|
3633
|
+
pendingEntry.promptId,
|
|
3395
3634
|
originatorClientId
|
|
3396
3635
|
);
|
|
3397
3636
|
}
|
|
@@ -3401,6 +3640,24 @@ function createAcpSessionBridge(opts) {
|
|
|
3401
3640
|
() => void 0
|
|
3402
3641
|
);
|
|
3403
3642
|
result.finally(() => {
|
|
3643
|
+
const listIdx = entry.pendingPromptList.indexOf(pendingEntry);
|
|
3644
|
+
if (listIdx !== -1) {
|
|
3645
|
+
entry.pendingPromptList.splice(listIdx, 1);
|
|
3646
|
+
if (isQueued) {
|
|
3647
|
+
try {
|
|
3648
|
+
entry.events.publish({
|
|
3649
|
+
type: "pending_prompt_completed",
|
|
3650
|
+
data: {
|
|
3651
|
+
sessionId,
|
|
3652
|
+
promptId: pendingEntry.promptId,
|
|
3653
|
+
state: "completed"
|
|
3654
|
+
},
|
|
3655
|
+
...originatorClientId ? { originatorClientId } : {}
|
|
3656
|
+
});
|
|
3657
|
+
} catch {
|
|
3658
|
+
}
|
|
3659
|
+
}
|
|
3660
|
+
}
|
|
3404
3661
|
releasePromptSlot();
|
|
3405
3662
|
if (entry.pendingPromptCount === 0 && entry.midTurnMessageQueue.length > 0) {
|
|
3406
3663
|
writeStderrLine(
|
|
@@ -3837,6 +4094,54 @@ function createAcpSessionBridge(opts) {
|
|
|
3837
4094
|
);
|
|
3838
4095
|
return response;
|
|
3839
4096
|
},
|
|
4097
|
+
async isWorkspaceMemoryRememberAvailable() {
|
|
4098
|
+
const info = await ensureChannel();
|
|
4099
|
+
try {
|
|
4100
|
+
const response = await withWorkspaceControl(
|
|
4101
|
+
info,
|
|
4102
|
+
() => withTimeout(
|
|
4103
|
+
Promise.race([
|
|
4104
|
+
info.connection.extMethod(
|
|
4105
|
+
SERVE_CONTROL_EXT_METHODS.workspaceMemoryRememberAvailability,
|
|
4106
|
+
{ cwd: boundWorkspace }
|
|
4107
|
+
),
|
|
4108
|
+
getChannelClosedReject(info)
|
|
4109
|
+
]),
|
|
4110
|
+
initTimeoutMs,
|
|
4111
|
+
SERVE_CONTROL_EXT_METHODS.workspaceMemoryRememberAvailability
|
|
4112
|
+
)
|
|
4113
|
+
);
|
|
4114
|
+
return response !== null && typeof response === "object" && response["available"] === true;
|
|
4115
|
+
} finally {
|
|
4116
|
+
if (hasNoChannelWork(info)) {
|
|
4117
|
+
await startIdleTimer(info, "workspace memory remember availability");
|
|
4118
|
+
}
|
|
4119
|
+
}
|
|
4120
|
+
},
|
|
4121
|
+
async runWorkspaceMemoryRemember(request) {
|
|
4122
|
+
const info = await ensureChannel();
|
|
4123
|
+
try {
|
|
4124
|
+
const response = await withWorkspaceControl(
|
|
4125
|
+
info,
|
|
4126
|
+
() => withTimeout(
|
|
4127
|
+
Promise.race([
|
|
4128
|
+
info.connection.extMethod(
|
|
4129
|
+
SERVE_CONTROL_EXT_METHODS.workspaceMemoryRemember,
|
|
4130
|
+
{ ...request, cwd: boundWorkspace }
|
|
4131
|
+
),
|
|
4132
|
+
getChannelClosedReject(info)
|
|
4133
|
+
]),
|
|
4134
|
+
WORKSPACE_MEMORY_REMEMBER_TIMEOUT_MS,
|
|
4135
|
+
SERVE_CONTROL_EXT_METHODS.workspaceMemoryRemember
|
|
4136
|
+
)
|
|
4137
|
+
);
|
|
4138
|
+
return parseWorkspaceMemoryRememberResult(response);
|
|
4139
|
+
} finally {
|
|
4140
|
+
if (hasNoChannelWork(info)) {
|
|
4141
|
+
await startIdleTimer(info, "workspace memory remember");
|
|
4142
|
+
}
|
|
4143
|
+
}
|
|
4144
|
+
},
|
|
3840
4145
|
async getWorkspaceMcpToolsStatus(serverName) {
|
|
3841
4146
|
return requestWorkspaceStatus(
|
|
3842
4147
|
SERVE_STATUS_EXT_METHODS.workspaceMcpTools,
|
|
@@ -3942,6 +4247,39 @@ function createAcpSessionBridge(opts) {
|
|
|
3942
4247
|
SERVE_CONTROL_EXT_METHODS.sessionGoalClear
|
|
3943
4248
|
);
|
|
3944
4249
|
},
|
|
4250
|
+
async continueSession(sessionId, context) {
|
|
4251
|
+
const entry = byId.get(sessionId);
|
|
4252
|
+
if (!entry) throw new SessionNotFoundError(sessionId);
|
|
4253
|
+
resolveTrustedClientId(entry, context?.clientId);
|
|
4254
|
+
const decision = await requestSessionStatus(sessionId, SERVE_CONTROL_EXT_METHODS.sessionContinue);
|
|
4255
|
+
if (!decision.accepted) {
|
|
4256
|
+
return decision;
|
|
4257
|
+
}
|
|
4258
|
+
const liveEntry = byId.get(sessionId);
|
|
4259
|
+
if (!liveEntry) throw new SessionNotFoundError(sessionId);
|
|
4260
|
+
const lastEventId = liveEntry.events.lastEventId;
|
|
4261
|
+
const promptId = context?.promptId;
|
|
4262
|
+
const promptPromise = bridgeApi.sendPrompt(
|
|
4263
|
+
sessionId,
|
|
4264
|
+
{ sessionId, prompt: [] },
|
|
4265
|
+
void 0,
|
|
4266
|
+
{
|
|
4267
|
+
...context?.clientId !== void 0 ? { clientId: context.clientId } : {},
|
|
4268
|
+
...promptId !== void 0 ? { promptId } : {},
|
|
4269
|
+
continue: true
|
|
4270
|
+
}
|
|
4271
|
+
);
|
|
4272
|
+
promptPromise.catch((err) => {
|
|
4273
|
+
teeServeDebugLine(
|
|
4274
|
+
`continueSession: continuation turn failed for ${sessionId}: ${err instanceof Error ? err.message : String(err)}`
|
|
4275
|
+
);
|
|
4276
|
+
});
|
|
4277
|
+
return {
|
|
4278
|
+
...decision,
|
|
4279
|
+
...promptId !== void 0 ? { promptId } : {},
|
|
4280
|
+
lastEventId
|
|
4281
|
+
};
|
|
4282
|
+
},
|
|
3945
4283
|
async getSessionStatsStatus(sessionId) {
|
|
3946
4284
|
return requestSessionStatus(
|
|
3947
4285
|
sessionId,
|
|
@@ -4266,6 +4604,44 @@ function createAcpSessionBridge(opts) {
|
|
|
4266
4604
|
recap: response.recap ?? null
|
|
4267
4605
|
};
|
|
4268
4606
|
},
|
|
4607
|
+
getPendingPrompts(sessionId, context) {
|
|
4608
|
+
const entry = byId.get(sessionId);
|
|
4609
|
+
if (!entry) throw new SessionNotFoundError(sessionId);
|
|
4610
|
+
resolveTrustedClientId(entry, context?.clientId);
|
|
4611
|
+
return entry.pendingPromptList.map((p) => ({
|
|
4612
|
+
promptId: p.promptId,
|
|
4613
|
+
text: p.text,
|
|
4614
|
+
queuedAt: p.queuedAt,
|
|
4615
|
+
state: p.state,
|
|
4616
|
+
...p.originatorClientId !== void 0 ? { originatorClientId: p.originatorClientId } : {}
|
|
4617
|
+
}));
|
|
4618
|
+
},
|
|
4619
|
+
removePendingPrompt(sessionId, promptId, context) {
|
|
4620
|
+
const entry = byId.get(sessionId);
|
|
4621
|
+
if (!entry) throw new SessionNotFoundError(sessionId);
|
|
4622
|
+
resolveTrustedClientId(entry, context?.clientId);
|
|
4623
|
+
const idx = entry.pendingPromptList.findIndex(
|
|
4624
|
+
(p) => p.promptId === promptId
|
|
4625
|
+
);
|
|
4626
|
+
if (idx === -1) return { removed: false };
|
|
4627
|
+
const target = entry.pendingPromptList[idx];
|
|
4628
|
+
writeStderrLine(
|
|
4629
|
+
`[pending-prompt] session=${sessionId} removing promptId=${promptId} state=${target.state}`
|
|
4630
|
+
);
|
|
4631
|
+
target.abortController.abort(
|
|
4632
|
+
new DOMException("Prompt removed by user", "AbortError")
|
|
4633
|
+
);
|
|
4634
|
+
entry.pendingPromptList.splice(idx, 1);
|
|
4635
|
+
try {
|
|
4636
|
+
entry.events.publish({
|
|
4637
|
+
type: "pending_prompt_completed",
|
|
4638
|
+
data: { sessionId, promptId, state: "removed" },
|
|
4639
|
+
...target.originatorClientId ? { originatorClientId: target.originatorClientId } : {}
|
|
4640
|
+
});
|
|
4641
|
+
} catch {
|
|
4642
|
+
}
|
|
4643
|
+
return { removed: true };
|
|
4644
|
+
},
|
|
4269
4645
|
enqueueMidTurnMessage(sessionId, message, context) {
|
|
4270
4646
|
const entry = byId.get(sessionId);
|
|
4271
4647
|
if (!entry) throw new SessionNotFoundError(sessionId);
|
|
@@ -4724,8 +5100,11 @@ function createAcpSessionBridge(opts) {
|
|
|
4724
5100
|
} catch {
|
|
4725
5101
|
}
|
|
4726
5102
|
entry.events.close();
|
|
4727
|
-
if (ci && ci
|
|
4728
|
-
await
|
|
5103
|
+
if (ci && hasNoChannelWork(ci)) {
|
|
5104
|
+
await reapPendingEmptyChannel(ci);
|
|
5105
|
+
if (!ci.isDying) {
|
|
5106
|
+
await startIdleTimer(ci, `killSession "${sessionId}"`);
|
|
5107
|
+
}
|
|
4729
5108
|
}
|
|
4730
5109
|
},
|
|
4731
5110
|
async detachClient(sessionId, clientId) {
|
|
@@ -4812,11 +5191,12 @@ function createAcpSessionBridge(opts) {
|
|
|
4812
5191
|
if (shuttingDown) return;
|
|
4813
5192
|
const ci = await ensureChannel();
|
|
4814
5193
|
const idleMs = resolvedChannelIdleTimeoutMs();
|
|
4815
|
-
if (idleMs > 0 && ci
|
|
5194
|
+
if (idleMs > 0 && hasNoChannelWork(ci)) {
|
|
4816
5195
|
await startIdleTimer(ci);
|
|
4817
5196
|
}
|
|
4818
5197
|
}
|
|
4819
5198
|
};
|
|
5199
|
+
return bridgeApi;
|
|
4820
5200
|
}
|
|
4821
5201
|
__name(createAcpSessionBridge, "createAcpSessionBridge");
|
|
4822
5202
|
async function withTimeout(p, ms, label) {
|