@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
package/chunks/chunk-BW4KCQFD.js
DELETED
|
@@ -1,1103 +0,0 @@
|
|
|
1
|
-
// Force strict mode and setup for ESM
|
|
2
|
-
"use strict";
|
|
3
|
-
import {
|
|
4
|
-
ClientSideConnection,
|
|
5
|
-
PROTOCOL_VERSION,
|
|
6
|
-
ndJsonStream
|
|
7
|
-
} from "./chunk-UFC57OYT.js";
|
|
8
|
-
import {
|
|
9
|
-
init_esbuild_shims
|
|
10
|
-
} from "./chunk-A4BMJM77.js";
|
|
11
|
-
import {
|
|
12
|
-
__name
|
|
13
|
-
} from "./chunk-J2S4EL5Y.js";
|
|
14
|
-
|
|
15
|
-
// packages/channels/base/dist/paths.js
|
|
16
|
-
init_esbuild_shims();
|
|
17
|
-
import * as path from "node:path";
|
|
18
|
-
import * as os from "node:os";
|
|
19
|
-
function resolvePath(dir) {
|
|
20
|
-
let resolved = dir;
|
|
21
|
-
if (resolved === "~" || resolved.startsWith("~/") || resolved.startsWith("~\\")) {
|
|
22
|
-
const relativeSegments = resolved === "~" ? [] : resolved.slice(2).split(/[/\\]+/).filter(Boolean);
|
|
23
|
-
resolved = path.join(os.homedir(), ...relativeSegments);
|
|
24
|
-
}
|
|
25
|
-
if (!path.isAbsolute(resolved)) {
|
|
26
|
-
resolved = path.resolve(resolved);
|
|
27
|
-
}
|
|
28
|
-
return resolved;
|
|
29
|
-
}
|
|
30
|
-
__name(resolvePath, "resolvePath");
|
|
31
|
-
function getGlobalQwenDir() {
|
|
32
|
-
const envDir = process.env["QWEN_HOME"];
|
|
33
|
-
if (envDir) {
|
|
34
|
-
return resolvePath(envDir);
|
|
35
|
-
}
|
|
36
|
-
const homeDir = os.homedir();
|
|
37
|
-
return homeDir ? path.join(homeDir, ".qwen") : path.join(os.tmpdir(), ".qwen");
|
|
38
|
-
}
|
|
39
|
-
__name(getGlobalQwenDir, "getGlobalQwenDir");
|
|
40
|
-
|
|
41
|
-
// packages/channels/base/dist/SessionRouter.js
|
|
42
|
-
init_esbuild_shims();
|
|
43
|
-
import { existsSync, readFileSync, writeFileSync, unlinkSync } from "node:fs";
|
|
44
|
-
var SessionRouter = class {
|
|
45
|
-
static {
|
|
46
|
-
__name(this, "SessionRouter");
|
|
47
|
-
}
|
|
48
|
-
toSession = /* @__PURE__ */ new Map();
|
|
49
|
-
// routing key → session ID
|
|
50
|
-
toTarget = /* @__PURE__ */ new Map();
|
|
51
|
-
// session ID → target
|
|
52
|
-
toCwd = /* @__PURE__ */ new Map();
|
|
53
|
-
// session ID → cwd
|
|
54
|
-
bridge;
|
|
55
|
-
defaultCwd;
|
|
56
|
-
defaultScope;
|
|
57
|
-
channelScopes = /* @__PURE__ */ new Map();
|
|
58
|
-
persistPath;
|
|
59
|
-
constructor(bridge, defaultCwd, scope = "user", persistPath) {
|
|
60
|
-
this.bridge = bridge;
|
|
61
|
-
this.defaultCwd = defaultCwd;
|
|
62
|
-
this.defaultScope = scope;
|
|
63
|
-
this.persistPath = persistPath;
|
|
64
|
-
}
|
|
65
|
-
/** Replace the bridge instance (used after crash recovery restart). */
|
|
66
|
-
setBridge(bridge) {
|
|
67
|
-
this.bridge = bridge;
|
|
68
|
-
}
|
|
69
|
-
/** Set scope override for a specific channel. */
|
|
70
|
-
setChannelScope(channelName, scope) {
|
|
71
|
-
this.channelScopes.set(channelName, scope);
|
|
72
|
-
}
|
|
73
|
-
routingKey(channelName, senderId, chatId, threadId) {
|
|
74
|
-
const scope = this.channelScopes.get(channelName) || this.defaultScope;
|
|
75
|
-
switch (scope) {
|
|
76
|
-
case "thread":
|
|
77
|
-
return `${channelName}:${threadId || chatId}`;
|
|
78
|
-
case "single":
|
|
79
|
-
return `${channelName}:__single__`;
|
|
80
|
-
case "user":
|
|
81
|
-
default:
|
|
82
|
-
return `${channelName}:${senderId}:${chatId}`;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Sender-scoped key prefix for by-sender (no chatId) scans. The trailing
|
|
87
|
-
* ':' delimiter ensures a sender id matches as a whole segment — without it
|
|
88
|
-
* sender "bob" would also match another sender "bobby"
|
|
89
|
-
* (key `${channelName}:bobby:${chatId}`).
|
|
90
|
-
*/
|
|
91
|
-
senderPrefix(channelName, senderId) {
|
|
92
|
-
return `${channelName}:${senderId}:`;
|
|
93
|
-
}
|
|
94
|
-
async resolve(channelName, senderId, chatId, threadId, cwd) {
|
|
95
|
-
const key = this.routingKey(channelName, senderId, chatId, threadId);
|
|
96
|
-
const existing = this.toSession.get(key);
|
|
97
|
-
if (existing) {
|
|
98
|
-
return existing;
|
|
99
|
-
}
|
|
100
|
-
const sessionCwd = cwd || this.defaultCwd;
|
|
101
|
-
const sessionId = await this.bridge.newSession(sessionCwd);
|
|
102
|
-
this.toSession.set(key, sessionId);
|
|
103
|
-
this.toTarget.set(sessionId, { channelName, senderId, chatId, threadId });
|
|
104
|
-
this.toCwd.set(sessionId, sessionCwd);
|
|
105
|
-
this.persist();
|
|
106
|
-
return sessionId;
|
|
107
|
-
}
|
|
108
|
-
getTarget(sessionId) {
|
|
109
|
-
return this.toTarget.get(sessionId);
|
|
110
|
-
}
|
|
111
|
-
getSession(channelName, senderId, chatId, threadId) {
|
|
112
|
-
return this.toSession.get(this.routingKey(channelName, senderId, chatId, threadId));
|
|
113
|
-
}
|
|
114
|
-
hasSession(channelName, senderId, chatId) {
|
|
115
|
-
if (chatId) {
|
|
116
|
-
return this.toSession.has(this.routingKey(channelName, senderId, chatId));
|
|
117
|
-
}
|
|
118
|
-
const prefix = this.senderPrefix(channelName, senderId);
|
|
119
|
-
for (const k of this.toSession.keys()) {
|
|
120
|
-
if (k.startsWith(prefix))
|
|
121
|
-
return true;
|
|
122
|
-
}
|
|
123
|
-
return false;
|
|
124
|
-
}
|
|
125
|
-
/**
|
|
126
|
-
* Remove session(s) for the given sender. Returns the removed session IDs.
|
|
127
|
-
*/
|
|
128
|
-
removeSession(channelName, senderId, chatId) {
|
|
129
|
-
const removedIds = [];
|
|
130
|
-
if (chatId) {
|
|
131
|
-
const key = this.routingKey(channelName, senderId, chatId);
|
|
132
|
-
const sessionId = this.deleteByKey(key);
|
|
133
|
-
if (sessionId)
|
|
134
|
-
removedIds.push(sessionId);
|
|
135
|
-
} else {
|
|
136
|
-
const prefix = this.senderPrefix(channelName, senderId);
|
|
137
|
-
for (const k of [...this.toSession.keys()]) {
|
|
138
|
-
if (k.startsWith(prefix)) {
|
|
139
|
-
const sessionId = this.deleteByKey(k);
|
|
140
|
-
if (sessionId)
|
|
141
|
-
removedIds.push(sessionId);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
if (removedIds.length > 0)
|
|
146
|
-
this.persist();
|
|
147
|
-
return removedIds;
|
|
148
|
-
}
|
|
149
|
-
deleteByKey(key) {
|
|
150
|
-
const sessionId = this.toSession.get(key);
|
|
151
|
-
if (!sessionId)
|
|
152
|
-
return null;
|
|
153
|
-
this.toSession.delete(key);
|
|
154
|
-
this.toTarget.delete(sessionId);
|
|
155
|
-
this.toCwd.delete(sessionId);
|
|
156
|
-
return sessionId;
|
|
157
|
-
}
|
|
158
|
-
/** Get all session entries for crash recovery. */
|
|
159
|
-
getAll() {
|
|
160
|
-
const entries = [];
|
|
161
|
-
for (const [key, sessionId] of this.toSession) {
|
|
162
|
-
const target = this.toTarget.get(sessionId);
|
|
163
|
-
if (target) {
|
|
164
|
-
entries.push({ key, sessionId, target });
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
return entries;
|
|
168
|
-
}
|
|
169
|
-
/**
|
|
170
|
-
* Restore session mappings from a previous bridge.
|
|
171
|
-
* Called after bridge restart — attempts loadSession for each saved mapping.
|
|
172
|
-
* Failed loads are silently dropped (new session on next message).
|
|
173
|
-
*/
|
|
174
|
-
async restoreSessions() {
|
|
175
|
-
if (!this.persistPath || !existsSync(this.persistPath)) {
|
|
176
|
-
return { restored: 0, failed: 0 };
|
|
177
|
-
}
|
|
178
|
-
let entries;
|
|
179
|
-
try {
|
|
180
|
-
entries = JSON.parse(readFileSync(this.persistPath, "utf-8"));
|
|
181
|
-
} catch {
|
|
182
|
-
return { restored: 0, failed: 0 };
|
|
183
|
-
}
|
|
184
|
-
let restored = 0;
|
|
185
|
-
let failed = 0;
|
|
186
|
-
for (const [key, entry] of Object.entries(entries)) {
|
|
187
|
-
try {
|
|
188
|
-
const sessionId = await this.bridge.loadSession(entry.sessionId, entry.cwd);
|
|
189
|
-
this.toSession.set(key, sessionId);
|
|
190
|
-
this.toTarget.set(sessionId, entry.target);
|
|
191
|
-
this.toCwd.set(sessionId, entry.cwd);
|
|
192
|
-
restored++;
|
|
193
|
-
} catch {
|
|
194
|
-
failed++;
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
if (failed > 0) {
|
|
198
|
-
this.persist();
|
|
199
|
-
}
|
|
200
|
-
return { restored, failed };
|
|
201
|
-
}
|
|
202
|
-
/** Clear in-memory state and delete persist file. Used on clean shutdown. */
|
|
203
|
-
clearAll() {
|
|
204
|
-
this.toSession.clear();
|
|
205
|
-
this.toTarget.clear();
|
|
206
|
-
this.toCwd.clear();
|
|
207
|
-
if (this.persistPath && existsSync(this.persistPath)) {
|
|
208
|
-
try {
|
|
209
|
-
unlinkSync(this.persistPath);
|
|
210
|
-
} catch {
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
persist() {
|
|
215
|
-
if (!this.persistPath)
|
|
216
|
-
return;
|
|
217
|
-
const data = {};
|
|
218
|
-
for (const [key, sessionId] of this.toSession) {
|
|
219
|
-
const target = this.toTarget.get(sessionId);
|
|
220
|
-
if (target) {
|
|
221
|
-
data[key] = {
|
|
222
|
-
sessionId,
|
|
223
|
-
target,
|
|
224
|
-
cwd: this.toCwd.get(sessionId) || this.defaultCwd
|
|
225
|
-
};
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
try {
|
|
229
|
-
writeFileSync(this.persistPath, JSON.stringify(data, null, 2), "utf-8");
|
|
230
|
-
} catch {
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
};
|
|
234
|
-
|
|
235
|
-
// packages/channels/base/dist/ChannelBase.js
|
|
236
|
-
init_esbuild_shims();
|
|
237
|
-
|
|
238
|
-
// packages/channels/base/dist/BlockStreamer.js
|
|
239
|
-
init_esbuild_shims();
|
|
240
|
-
var BlockStreamer = class {
|
|
241
|
-
static {
|
|
242
|
-
__name(this, "BlockStreamer");
|
|
243
|
-
}
|
|
244
|
-
buffer = "";
|
|
245
|
-
idleTimer = null;
|
|
246
|
-
sending = Promise.resolve();
|
|
247
|
-
opts;
|
|
248
|
-
/** Number of blocks emitted so far. */
|
|
249
|
-
blockCount = 0;
|
|
250
|
-
constructor(opts) {
|
|
251
|
-
this.opts = opts;
|
|
252
|
-
}
|
|
253
|
-
/** Feed a new text chunk from the agent stream. */
|
|
254
|
-
push(chunk) {
|
|
255
|
-
this.buffer += chunk;
|
|
256
|
-
this.clearIdleTimer();
|
|
257
|
-
this.checkEmit();
|
|
258
|
-
if (this.buffer.length > 0 && this.opts.idleMs > 0) {
|
|
259
|
-
this.idleTimer = setTimeout(() => this.onIdle(), this.opts.idleMs);
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
/** Flush all remaining buffered text. Awaits all pending sends. */
|
|
263
|
-
async flush() {
|
|
264
|
-
this.clearIdleTimer();
|
|
265
|
-
if (this.buffer.length > 0) {
|
|
266
|
-
this.emitBlock(this.buffer);
|
|
267
|
-
this.buffer = "";
|
|
268
|
-
}
|
|
269
|
-
await this.sending;
|
|
270
|
-
}
|
|
271
|
-
/** Drop buffered text and cancel future idle emission. */
|
|
272
|
-
stop() {
|
|
273
|
-
this.clearIdleTimer();
|
|
274
|
-
this.buffer = "";
|
|
275
|
-
}
|
|
276
|
-
// ---------------------------------------------------------------------------
|
|
277
|
-
// Internal
|
|
278
|
-
// ---------------------------------------------------------------------------
|
|
279
|
-
checkEmit() {
|
|
280
|
-
while (this.buffer.length >= this.opts.maxChars) {
|
|
281
|
-
const bp = this.findBreakPoint(this.buffer, this.opts.maxChars);
|
|
282
|
-
this.emitBlock(this.buffer.slice(0, bp));
|
|
283
|
-
this.buffer = this.buffer.slice(bp);
|
|
284
|
-
}
|
|
285
|
-
if (this.buffer.length >= this.opts.minChars) {
|
|
286
|
-
const bp = this.findBlockBoundary(this.buffer);
|
|
287
|
-
if (bp > 0) {
|
|
288
|
-
this.emitBlock(this.buffer.slice(0, bp));
|
|
289
|
-
this.buffer = this.buffer.slice(bp);
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
onIdle() {
|
|
294
|
-
this.idleTimer = null;
|
|
295
|
-
if (this.buffer.length >= this.opts.minChars) {
|
|
296
|
-
this.emitBlock(this.buffer);
|
|
297
|
-
this.buffer = "";
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
emitBlock(text) {
|
|
301
|
-
const trimmed = text.trim();
|
|
302
|
-
if (!trimmed)
|
|
303
|
-
return;
|
|
304
|
-
this.blockCount++;
|
|
305
|
-
this.sending = this.sending.then(() => this.opts.send(trimmed)).catch(() => {
|
|
306
|
-
});
|
|
307
|
-
}
|
|
308
|
-
/**
|
|
309
|
-
* Find the last paragraph boundary (\n\n) in the buffer.
|
|
310
|
-
* Returns the position after the boundary, or -1 if no suitable boundary
|
|
311
|
-
* exists at or after minChars.
|
|
312
|
-
*/
|
|
313
|
-
findBlockBoundary(text) {
|
|
314
|
-
const last = text.lastIndexOf("\n\n");
|
|
315
|
-
if (last < 0 || last < this.opts.minChars)
|
|
316
|
-
return -1;
|
|
317
|
-
return last + 2;
|
|
318
|
-
}
|
|
319
|
-
/**
|
|
320
|
-
* Find the best break point at or before maxPos.
|
|
321
|
-
* Prefers paragraph break > newline > space > maxPos.
|
|
322
|
-
*/
|
|
323
|
-
findBreakPoint(text, maxPos) {
|
|
324
|
-
const sub = text.slice(0, maxPos);
|
|
325
|
-
const para = sub.lastIndexOf("\n\n");
|
|
326
|
-
if (para > 0)
|
|
327
|
-
return para + 2;
|
|
328
|
-
const nl = sub.lastIndexOf("\n");
|
|
329
|
-
if (nl > 0)
|
|
330
|
-
return nl + 1;
|
|
331
|
-
const sp = sub.lastIndexOf(" ");
|
|
332
|
-
if (sp > 0)
|
|
333
|
-
return sp + 1;
|
|
334
|
-
return maxPos;
|
|
335
|
-
}
|
|
336
|
-
clearIdleTimer() {
|
|
337
|
-
if (this.idleTimer !== null) {
|
|
338
|
-
clearTimeout(this.idleTimer);
|
|
339
|
-
this.idleTimer = null;
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
};
|
|
343
|
-
|
|
344
|
-
// packages/channels/base/dist/GroupGate.js
|
|
345
|
-
init_esbuild_shims();
|
|
346
|
-
var GroupGate = class {
|
|
347
|
-
static {
|
|
348
|
-
__name(this, "GroupGate");
|
|
349
|
-
}
|
|
350
|
-
policy;
|
|
351
|
-
groups;
|
|
352
|
-
constructor(policy = "disabled", groups = {}) {
|
|
353
|
-
this.policy = policy;
|
|
354
|
-
this.groups = groups;
|
|
355
|
-
}
|
|
356
|
-
/**
|
|
357
|
-
* Full group check: policy + allowlist + mention gating.
|
|
358
|
-
* Evaluation order:
|
|
359
|
-
* 1. groupPolicy (disabled → drop)
|
|
360
|
-
* 2. group allowlist (allowlist mode, no match → drop)
|
|
361
|
-
* 3. mention gating (requireMention + not mentioned → drop silently)
|
|
362
|
-
*
|
|
363
|
-
* Mention gating runs before sender gate so that unmentioned messages
|
|
364
|
-
* in groups don't trigger pairing flows.
|
|
365
|
-
*/
|
|
366
|
-
check(envelope) {
|
|
367
|
-
if (!envelope.isGroup) {
|
|
368
|
-
return { allowed: true };
|
|
369
|
-
}
|
|
370
|
-
if (this.policy === "disabled") {
|
|
371
|
-
return { allowed: false, reason: "disabled" };
|
|
372
|
-
}
|
|
373
|
-
if (this.policy === "allowlist") {
|
|
374
|
-
if (!this.groups[envelope.chatId]) {
|
|
375
|
-
return { allowed: false, reason: "not_allowlisted" };
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
const groupConfig = this.groups[envelope.chatId] || this.groups["*"] || {};
|
|
379
|
-
const requireMention = groupConfig.requireMention ?? true;
|
|
380
|
-
if (requireMention && !envelope.isMentioned && !envelope.isReplyToBot) {
|
|
381
|
-
return { allowed: false, reason: "mention_required" };
|
|
382
|
-
}
|
|
383
|
-
return { allowed: true };
|
|
384
|
-
}
|
|
385
|
-
};
|
|
386
|
-
|
|
387
|
-
// packages/channels/base/dist/SenderGate.js
|
|
388
|
-
init_esbuild_shims();
|
|
389
|
-
var SenderGate = class {
|
|
390
|
-
static {
|
|
391
|
-
__name(this, "SenderGate");
|
|
392
|
-
}
|
|
393
|
-
policy;
|
|
394
|
-
allowedUsers;
|
|
395
|
-
pairingStore;
|
|
396
|
-
constructor(policy, allowedUsers = [], pairingStore) {
|
|
397
|
-
this.policy = policy;
|
|
398
|
-
this.allowedUsers = new Set(allowedUsers);
|
|
399
|
-
this.pairingStore = pairingStore || null;
|
|
400
|
-
}
|
|
401
|
-
check(senderId, senderName) {
|
|
402
|
-
switch (this.policy) {
|
|
403
|
-
case "open":
|
|
404
|
-
return { allowed: true };
|
|
405
|
-
case "allowlist":
|
|
406
|
-
return { allowed: this.allowedUsers.has(senderId) };
|
|
407
|
-
case "pairing": {
|
|
408
|
-
if (this.allowedUsers.has(senderId)) {
|
|
409
|
-
return { allowed: true };
|
|
410
|
-
}
|
|
411
|
-
if (this.pairingStore?.isApproved(senderId)) {
|
|
412
|
-
return { allowed: true };
|
|
413
|
-
}
|
|
414
|
-
const code = this.pairingStore?.createRequest(senderId, senderName || senderId);
|
|
415
|
-
return { allowed: false, pairingCode: code ?? null };
|
|
416
|
-
}
|
|
417
|
-
default:
|
|
418
|
-
throw new Error(`Unknown sender policy: ${this.policy}`);
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
};
|
|
422
|
-
|
|
423
|
-
// packages/channels/base/dist/PairingStore.js
|
|
424
|
-
init_esbuild_shims();
|
|
425
|
-
import * as crypto from "node:crypto";
|
|
426
|
-
import * as fs from "node:fs";
|
|
427
|
-
import * as path2 from "node:path";
|
|
428
|
-
var SAFE_ALPHABET = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
|
|
429
|
-
var CODE_LENGTH = 8;
|
|
430
|
-
var EXPIRY_MS = 60 * 60 * 1e3;
|
|
431
|
-
var MAX_PENDING = 3;
|
|
432
|
-
var PairingStore = class {
|
|
433
|
-
static {
|
|
434
|
-
__name(this, "PairingStore");
|
|
435
|
-
}
|
|
436
|
-
dir;
|
|
437
|
-
pendingPath;
|
|
438
|
-
allowlistPath;
|
|
439
|
-
constructor(channelName) {
|
|
440
|
-
this.dir = path2.join(getGlobalQwenDir(), "channels");
|
|
441
|
-
this.pendingPath = path2.join(this.dir, `${channelName}-pairing.json`);
|
|
442
|
-
this.allowlistPath = path2.join(this.dir, `${channelName}-allowlist.json`);
|
|
443
|
-
}
|
|
444
|
-
isApproved(senderId) {
|
|
445
|
-
const list = this.readAllowlist();
|
|
446
|
-
return list.includes(senderId);
|
|
447
|
-
}
|
|
448
|
-
/**
|
|
449
|
-
* Create a pairing request for an unknown sender.
|
|
450
|
-
* Returns the code if created, or null if the pending cap is reached.
|
|
451
|
-
* If the sender already has a non-expired pending request, returns that code.
|
|
452
|
-
*/
|
|
453
|
-
createRequest(senderId, senderName) {
|
|
454
|
-
const pending = this.readPending();
|
|
455
|
-
const now = Date.now();
|
|
456
|
-
const active = pending.filter((r) => now - r.createdAt < EXPIRY_MS);
|
|
457
|
-
const existing = active.find((r) => r.senderId === senderId);
|
|
458
|
-
if (existing) {
|
|
459
|
-
return existing.code;
|
|
460
|
-
}
|
|
461
|
-
if (active.length >= MAX_PENDING) {
|
|
462
|
-
return null;
|
|
463
|
-
}
|
|
464
|
-
const code = generateCode();
|
|
465
|
-
active.push({ senderId, senderName, code, createdAt: now });
|
|
466
|
-
this.writePending(active);
|
|
467
|
-
return code;
|
|
468
|
-
}
|
|
469
|
-
/**
|
|
470
|
-
* Approve a pairing request by code.
|
|
471
|
-
* Returns the sender ID if found, or null if not found / expired.
|
|
472
|
-
*/
|
|
473
|
-
approve(code) {
|
|
474
|
-
const pending = this.readPending();
|
|
475
|
-
const now = Date.now();
|
|
476
|
-
const idx = pending.findIndex((r) => r.code === code.toUpperCase() && now - r.createdAt < EXPIRY_MS);
|
|
477
|
-
if (idx === -1)
|
|
478
|
-
return null;
|
|
479
|
-
const request = pending[idx];
|
|
480
|
-
pending.splice(idx, 1);
|
|
481
|
-
this.writePending(pending);
|
|
482
|
-
const list = this.readAllowlist();
|
|
483
|
-
if (!list.includes(request.senderId)) {
|
|
484
|
-
list.push(request.senderId);
|
|
485
|
-
this.writeAllowlist(list);
|
|
486
|
-
}
|
|
487
|
-
return request;
|
|
488
|
-
}
|
|
489
|
-
listPending() {
|
|
490
|
-
const pending = this.readPending();
|
|
491
|
-
const now = Date.now();
|
|
492
|
-
return pending.filter((r) => now - r.createdAt < EXPIRY_MS);
|
|
493
|
-
}
|
|
494
|
-
getAllowlist() {
|
|
495
|
-
return this.readAllowlist();
|
|
496
|
-
}
|
|
497
|
-
ensureDir() {
|
|
498
|
-
if (!fs.existsSync(this.dir)) {
|
|
499
|
-
fs.mkdirSync(this.dir, { recursive: true });
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
|
-
readPending() {
|
|
503
|
-
try {
|
|
504
|
-
const data = fs.readFileSync(this.pendingPath, "utf-8");
|
|
505
|
-
return JSON.parse(data);
|
|
506
|
-
} catch {
|
|
507
|
-
return [];
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
writePending(requests) {
|
|
511
|
-
this.ensureDir();
|
|
512
|
-
fs.writeFileSync(this.pendingPath, JSON.stringify(requests, null, 2));
|
|
513
|
-
}
|
|
514
|
-
readAllowlist() {
|
|
515
|
-
try {
|
|
516
|
-
const data = fs.readFileSync(this.allowlistPath, "utf-8");
|
|
517
|
-
return JSON.parse(data);
|
|
518
|
-
} catch {
|
|
519
|
-
return [];
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
writeAllowlist(list) {
|
|
523
|
-
this.ensureDir();
|
|
524
|
-
fs.writeFileSync(this.allowlistPath, JSON.stringify(list, null, 2));
|
|
525
|
-
}
|
|
526
|
-
};
|
|
527
|
-
function generateCode() {
|
|
528
|
-
let code = "";
|
|
529
|
-
for (let i = 0; i < CODE_LENGTH; i++) {
|
|
530
|
-
code += SAFE_ALPHABET[crypto.randomInt(SAFE_ALPHABET.length)];
|
|
531
|
-
}
|
|
532
|
-
return code;
|
|
533
|
-
}
|
|
534
|
-
__name(generateCode, "generateCode");
|
|
535
|
-
|
|
536
|
-
// packages/channels/base/dist/ChannelBase.js
|
|
537
|
-
var ChannelBase = class {
|
|
538
|
-
static {
|
|
539
|
-
__name(this, "ChannelBase");
|
|
540
|
-
}
|
|
541
|
-
config;
|
|
542
|
-
bridge;
|
|
543
|
-
groupGate;
|
|
544
|
-
gate;
|
|
545
|
-
router;
|
|
546
|
-
name;
|
|
547
|
-
/** Resolved proxy URL, available to subclasses for adapter-specific clients. */
|
|
548
|
-
proxy;
|
|
549
|
-
instructedSessions = /* @__PURE__ */ new Set();
|
|
550
|
-
commands = /* @__PURE__ */ new Map();
|
|
551
|
-
/** Per-session promise chain to serialize prompt + send (followup mode). */
|
|
552
|
-
sessionQueues = /* @__PURE__ */ new Map();
|
|
553
|
-
/** Per-session active prompt tracking for dispatch modes. */
|
|
554
|
-
activePrompts = /* @__PURE__ */ new Map();
|
|
555
|
-
/** Per-session message buffer for collect mode. */
|
|
556
|
-
collectBuffers = /* @__PURE__ */ new Map();
|
|
557
|
-
constructor(name, config, bridge, options) {
|
|
558
|
-
this.name = name;
|
|
559
|
-
this.config = config;
|
|
560
|
-
this.bridge = bridge;
|
|
561
|
-
this.proxy = options?.proxy;
|
|
562
|
-
this.groupGate = new GroupGate(config.groupPolicy, config.groups);
|
|
563
|
-
const pairingStore = config.senderPolicy === "pairing" ? new PairingStore(name) : void 0;
|
|
564
|
-
this.gate = new SenderGate(config.senderPolicy, config.allowedUsers, pairingStore);
|
|
565
|
-
this.router = options?.router || new SessionRouter(bridge, config.cwd, config.sessionScope);
|
|
566
|
-
this.registerSharedCommands();
|
|
567
|
-
if (!options?.router) {
|
|
568
|
-
bridge.on("toolCall", (event) => {
|
|
569
|
-
const target = this.router.getTarget(event.sessionId);
|
|
570
|
-
if (target) {
|
|
571
|
-
this.onToolCall(target.chatId, event);
|
|
572
|
-
}
|
|
573
|
-
});
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
/** Replace the bridge instance (used after crash recovery restart). */
|
|
577
|
-
setBridge(bridge) {
|
|
578
|
-
this.bridge = bridge;
|
|
579
|
-
}
|
|
580
|
-
onToolCall(_chatId, _event) {
|
|
581
|
-
}
|
|
582
|
-
/**
|
|
583
|
-
* Called when a prompt actually begins processing (inside the session queue).
|
|
584
|
-
* Override to show a platform-specific working indicator (e.g., typing, reaction).
|
|
585
|
-
* Not called for buffered messages (collect mode) or gated/blocked messages.
|
|
586
|
-
*/
|
|
587
|
-
onPromptStart(_chatId, _sessionId, _messageId) {
|
|
588
|
-
}
|
|
589
|
-
/**
|
|
590
|
-
* Called when a prompt finishes (response sent or cancelled).
|
|
591
|
-
* Override to hide the working indicator.
|
|
592
|
-
*/
|
|
593
|
-
onPromptEnd(_chatId, _sessionId, _messageId) {
|
|
594
|
-
}
|
|
595
|
-
/**
|
|
596
|
-
* Called for each text chunk as the agent streams its response.
|
|
597
|
-
* Override to implement progressive display (e.g., updating an AI card in-place).
|
|
598
|
-
* Default: no-op (chunks are collected internally and delivered via onResponseComplete).
|
|
599
|
-
*/
|
|
600
|
-
onResponseChunk(_chatId, _chunk, _sessionId) {
|
|
601
|
-
}
|
|
602
|
-
/**
|
|
603
|
-
* Called when the agent's full response is ready.
|
|
604
|
-
* Override to customize delivery (e.g., finalize an AI card).
|
|
605
|
-
* Default: calls sendMessage() with the full response text.
|
|
606
|
-
*/
|
|
607
|
-
async onResponseComplete(chatId, fullText, _sessionId) {
|
|
608
|
-
await this.sendMessage(chatId, fullText);
|
|
609
|
-
}
|
|
610
|
-
/**
|
|
611
|
-
* Register a slash command handler. Subclasses can call this to add
|
|
612
|
-
* platform-specific commands (e.g., /start for Telegram).
|
|
613
|
-
* Overrides shared commands if the same name is registered.
|
|
614
|
-
*/
|
|
615
|
-
registerCommand(name, handler) {
|
|
616
|
-
this.commands.set(name.toLowerCase(), handler);
|
|
617
|
-
}
|
|
618
|
-
registerCancelCommand(name = "cancel") {
|
|
619
|
-
this.registerCommand(name, async (envelope) => {
|
|
620
|
-
const activeSessionId = this.findActiveSessionId(envelope);
|
|
621
|
-
if (!activeSessionId) {
|
|
622
|
-
await this.sendMessage(envelope.chatId, "No request is currently running.");
|
|
623
|
-
return true;
|
|
624
|
-
}
|
|
625
|
-
const active = this.activePrompts.get(activeSessionId);
|
|
626
|
-
if (!active) {
|
|
627
|
-
await this.sendMessage(envelope.chatId, "No request is currently running.");
|
|
628
|
-
return true;
|
|
629
|
-
}
|
|
630
|
-
const cancelRequested = active.cancelRequested ?? this.bridge.cancelSession(activeSessionId).then(() => true, (err) => {
|
|
631
|
-
process.stderr.write(`[${this.name}] cancelSession failed for session=${activeSessionId}: ${err instanceof Error ? err.message : err}
|
|
632
|
-
`);
|
|
633
|
-
active.cancelRequested = void 0;
|
|
634
|
-
return false;
|
|
635
|
-
});
|
|
636
|
-
active.cancelRequested = cancelRequested;
|
|
637
|
-
const cancelSucceeded = await cancelRequested;
|
|
638
|
-
if (!cancelSucceeded) {
|
|
639
|
-
await this.sendMessage(envelope.chatId, "Failed to cancel current request.");
|
|
640
|
-
return true;
|
|
641
|
-
}
|
|
642
|
-
active.cancelled = true;
|
|
643
|
-
active.stopStreaming?.();
|
|
644
|
-
this.collectBuffers.delete(activeSessionId);
|
|
645
|
-
await this.sendMessage(envelope.chatId, "Cancelled current request.");
|
|
646
|
-
return true;
|
|
647
|
-
});
|
|
648
|
-
}
|
|
649
|
-
/** Register shared slash commands. Called from constructor. */
|
|
650
|
-
registerSharedCommands() {
|
|
651
|
-
const clearHandler = /* @__PURE__ */ __name(async (envelope) => {
|
|
652
|
-
const removedIds = this.router.removeSession(this.name, envelope.senderId, envelope.chatId);
|
|
653
|
-
if (removedIds.length > 0) {
|
|
654
|
-
for (const id of removedIds) {
|
|
655
|
-
this.instructedSessions.delete(id);
|
|
656
|
-
}
|
|
657
|
-
await this.sendMessage(envelope.chatId, "Session cleared. Your next message will start a fresh conversation.");
|
|
658
|
-
} else {
|
|
659
|
-
await this.sendMessage(envelope.chatId, "No active session to clear.");
|
|
660
|
-
}
|
|
661
|
-
return true;
|
|
662
|
-
}, "clearHandler");
|
|
663
|
-
this.registerCommand("clear", clearHandler);
|
|
664
|
-
this.registerCommand("reset", clearHandler);
|
|
665
|
-
this.registerCommand("new", clearHandler);
|
|
666
|
-
this.registerCommand("help", async (envelope) => {
|
|
667
|
-
const lines = [
|
|
668
|
-
"Commands:",
|
|
669
|
-
"/help \u2014 Show this help",
|
|
670
|
-
"/clear \u2014 Clear your session (aliases: /reset, /new)",
|
|
671
|
-
"/status \u2014 Show session info"
|
|
672
|
-
];
|
|
673
|
-
const sharedCmds = /* @__PURE__ */ new Set(["help", "clear", "reset", "new", "status"]);
|
|
674
|
-
const platformCmds = [...this.commands.keys()].filter((c) => !sharedCmds.has(c));
|
|
675
|
-
if (platformCmds.length > 0) {
|
|
676
|
-
for (const cmd of platformCmds) {
|
|
677
|
-
lines.push(`/${cmd}`);
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
const agentCommands = this.bridge.availableCommands;
|
|
681
|
-
if (agentCommands.length > 0) {
|
|
682
|
-
lines.push("", "Agent commands (forwarded to Qwen Code):");
|
|
683
|
-
for (const cmd of agentCommands) {
|
|
684
|
-
lines.push(`/${cmd.name} \u2014 ${cmd.description}`);
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
lines.push("", "Send any text to chat with the agent.");
|
|
688
|
-
await this.sendMessage(envelope.chatId, lines.join("\n"));
|
|
689
|
-
return true;
|
|
690
|
-
});
|
|
691
|
-
this.registerCommand("status", async (envelope) => {
|
|
692
|
-
const hasSession = this.router.hasSession(this.name, envelope.senderId, envelope.chatId);
|
|
693
|
-
const policy = this.config.senderPolicy;
|
|
694
|
-
const lines = [
|
|
695
|
-
`Session: ${hasSession ? "active" : "none"}`,
|
|
696
|
-
`Access: ${policy}`,
|
|
697
|
-
`Channel: ${this.name}`
|
|
698
|
-
];
|
|
699
|
-
await this.sendMessage(envelope.chatId, lines.join("\n"));
|
|
700
|
-
return true;
|
|
701
|
-
});
|
|
702
|
-
}
|
|
703
|
-
/** Check if a message text matches a registered local command. */
|
|
704
|
-
isLocalCommand(text) {
|
|
705
|
-
const parsed = this.parseCommand(text);
|
|
706
|
-
return parsed !== null && this.commands.has(parsed.command);
|
|
707
|
-
}
|
|
708
|
-
findActiveSessionId(envelope) {
|
|
709
|
-
const sessionId = this.router.getSession(this.name, envelope.senderId, envelope.chatId, envelope.threadId);
|
|
710
|
-
return sessionId && this.activePrompts.has(sessionId) ? sessionId : void 0;
|
|
711
|
-
}
|
|
712
|
-
/**
|
|
713
|
-
* Parse a slash command from message text.
|
|
714
|
-
* Returns { command, args } or null if not a slash command.
|
|
715
|
-
*/
|
|
716
|
-
parseCommand(text) {
|
|
717
|
-
if (!text.startsWith("/"))
|
|
718
|
-
return null;
|
|
719
|
-
const match = text.match(/^\/([a-zA-Z0-9_]+)(?:@\S+)?\s*(.*)/s);
|
|
720
|
-
if (!match)
|
|
721
|
-
return null;
|
|
722
|
-
return { command: match[1].toLowerCase(), args: match[2].trim() };
|
|
723
|
-
}
|
|
724
|
-
async handleInbound(envelope) {
|
|
725
|
-
const groupResult = this.groupGate.check(envelope);
|
|
726
|
-
if (!groupResult.allowed) {
|
|
727
|
-
return;
|
|
728
|
-
}
|
|
729
|
-
const result = this.gate.check(envelope.senderId, envelope.senderName);
|
|
730
|
-
if (!result.allowed) {
|
|
731
|
-
if (result.pairingCode !== void 0) {
|
|
732
|
-
await this.onPairingRequired(envelope.chatId, result.pairingCode);
|
|
733
|
-
}
|
|
734
|
-
return;
|
|
735
|
-
}
|
|
736
|
-
const parsed = this.parseCommand(envelope.text);
|
|
737
|
-
if (parsed) {
|
|
738
|
-
const handler = this.commands.get(parsed.command);
|
|
739
|
-
if (handler) {
|
|
740
|
-
const handled = await handler(envelope, parsed.args);
|
|
741
|
-
if (handled)
|
|
742
|
-
return;
|
|
743
|
-
}
|
|
744
|
-
}
|
|
745
|
-
const sessionId = await this.router.resolve(this.name, envelope.senderId, envelope.chatId, envelope.threadId, this.config.cwd);
|
|
746
|
-
if (envelope.text.startsWith("!")) {
|
|
747
|
-
const cmd = envelope.text.slice(1).trim();
|
|
748
|
-
const bridgeShellCommand = this.bridge["shellCommand"];
|
|
749
|
-
if (cmd && typeof bridgeShellCommand === "function") {
|
|
750
|
-
try {
|
|
751
|
-
const result2 = await bridgeShellCommand(sessionId, cmd);
|
|
752
|
-
const longestRun = Math.max(0, ...Array.from((result2.output || "").matchAll(/`+/g), (m) => m[0].length));
|
|
753
|
-
const fence = "`".repeat(Math.max(3, longestRun + 1));
|
|
754
|
-
const output = result2.output ? `${fence}
|
|
755
|
-
${result2.output}
|
|
756
|
-
${fence}` : "(no output)";
|
|
757
|
-
const exitLine = result2.exitCode !== null && result2.exitCode !== 0 ? `
|
|
758
|
-
Exit code: ${result2.exitCode}` : "";
|
|
759
|
-
await this.sendMessage(envelope.chatId, `$ ${cmd}
|
|
760
|
-
${output}${exitLine}`);
|
|
761
|
-
} catch (error) {
|
|
762
|
-
await this.sendMessage(envelope.chatId, `Shell command failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
763
|
-
}
|
|
764
|
-
return;
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
let promptText = envelope.text;
|
|
768
|
-
if (envelope.referencedText) {
|
|
769
|
-
promptText = `[Replying to: "${envelope.referencedText}"]
|
|
770
|
-
|
|
771
|
-
${promptText}`;
|
|
772
|
-
}
|
|
773
|
-
let imageBase64 = envelope.imageBase64;
|
|
774
|
-
let imageMimeType = envelope.imageMimeType;
|
|
775
|
-
if (envelope.attachments?.length) {
|
|
776
|
-
const filePaths = [];
|
|
777
|
-
for (const att of envelope.attachments) {
|
|
778
|
-
if (att.type === "image" && att.data && !imageBase64) {
|
|
779
|
-
imageBase64 = att.data;
|
|
780
|
-
imageMimeType = att.mimeType;
|
|
781
|
-
} else if (att.filePath) {
|
|
782
|
-
const label = att.type === "file" ? "file" : att.type;
|
|
783
|
-
const name = att.fileName ? ` "${att.fileName}"` : "";
|
|
784
|
-
filePaths.push(`User sent a ${label}${name}. It has been saved to: ${att.filePath}`);
|
|
785
|
-
}
|
|
786
|
-
}
|
|
787
|
-
if (filePaths.length > 0) {
|
|
788
|
-
promptText = promptText + "\n\n" + filePaths.join("\n");
|
|
789
|
-
}
|
|
790
|
-
}
|
|
791
|
-
if (this.config.instructions && !this.instructedSessions.has(sessionId)) {
|
|
792
|
-
promptText = `${this.config.instructions}
|
|
793
|
-
|
|
794
|
-
${promptText}`;
|
|
795
|
-
this.instructedSessions.add(sessionId);
|
|
796
|
-
}
|
|
797
|
-
const groupCfg = envelope.isGroup ? this.config.groups[envelope.chatId] || this.config.groups["*"] : void 0;
|
|
798
|
-
const mode = groupCfg?.dispatchMode || this.config.dispatchMode || "steer";
|
|
799
|
-
const active = this.activePrompts.get(sessionId);
|
|
800
|
-
if (active) {
|
|
801
|
-
switch (mode) {
|
|
802
|
-
case "collect": {
|
|
803
|
-
let buffer = this.collectBuffers.get(sessionId);
|
|
804
|
-
if (!buffer) {
|
|
805
|
-
buffer = [];
|
|
806
|
-
this.collectBuffers.set(sessionId, buffer);
|
|
807
|
-
}
|
|
808
|
-
buffer.push({ text: promptText, envelope });
|
|
809
|
-
return;
|
|
810
|
-
}
|
|
811
|
-
case "steer": {
|
|
812
|
-
active.cancelled = true;
|
|
813
|
-
await this.bridge.cancelSession(sessionId).catch(() => {
|
|
814
|
-
});
|
|
815
|
-
await active.done;
|
|
816
|
-
promptText = `[The user sent a new message while you were working. Their previous request has been cancelled.]
|
|
817
|
-
|
|
818
|
-
${promptText}`;
|
|
819
|
-
break;
|
|
820
|
-
}
|
|
821
|
-
case "followup": {
|
|
822
|
-
break;
|
|
823
|
-
}
|
|
824
|
-
default: {
|
|
825
|
-
const _exhaustive = mode;
|
|
826
|
-
throw new Error(`Unknown dispatch mode: ${_exhaustive}`);
|
|
827
|
-
}
|
|
828
|
-
}
|
|
829
|
-
}
|
|
830
|
-
const prev = this.sessionQueues.get(sessionId) ?? Promise.resolve();
|
|
831
|
-
const useBlockStreaming = this.config.blockStreaming === "on";
|
|
832
|
-
const current = prev.then(async () => {
|
|
833
|
-
let doneResolve = /* @__PURE__ */ __name(() => {
|
|
834
|
-
}, "doneResolve");
|
|
835
|
-
const done = new Promise((r) => {
|
|
836
|
-
doneResolve = r;
|
|
837
|
-
});
|
|
838
|
-
const promptState = {
|
|
839
|
-
cancelled: false,
|
|
840
|
-
done,
|
|
841
|
-
resolve: doneResolve
|
|
842
|
-
};
|
|
843
|
-
this.activePrompts.set(sessionId, promptState);
|
|
844
|
-
this.onPromptStart(envelope.chatId, sessionId, envelope.messageId);
|
|
845
|
-
const streamer = useBlockStreaming ? new BlockStreamer({
|
|
846
|
-
minChars: this.config.blockStreamingChunk?.minChars ?? 400,
|
|
847
|
-
maxChars: this.config.blockStreamingChunk?.maxChars ?? 1e3,
|
|
848
|
-
idleMs: this.config.blockStreamingCoalesce?.idleMs ?? 1500,
|
|
849
|
-
send: /* @__PURE__ */ __name((text) => this.sendMessage(envelope.chatId, text), "send")
|
|
850
|
-
}) : null;
|
|
851
|
-
promptState.stopStreaming = () => streamer?.stop();
|
|
852
|
-
const onChunk = /* @__PURE__ */ __name((sid, chunk) => {
|
|
853
|
-
if (sid === sessionId && !promptState.cancelled) {
|
|
854
|
-
this.onResponseChunk(envelope.chatId, chunk, sessionId);
|
|
855
|
-
streamer?.push(chunk);
|
|
856
|
-
}
|
|
857
|
-
}, "onChunk");
|
|
858
|
-
this.bridge.on("textChunk", onChunk);
|
|
859
|
-
try {
|
|
860
|
-
const response = await this.bridge.prompt(sessionId, promptText, {
|
|
861
|
-
imageBase64,
|
|
862
|
-
imageMimeType
|
|
863
|
-
});
|
|
864
|
-
if (promptState.cancelRequested && !promptState.cancelled) {
|
|
865
|
-
promptState.cancelled = await promptState.cancelRequested;
|
|
866
|
-
}
|
|
867
|
-
if (!promptState.cancelled && response) {
|
|
868
|
-
if (streamer) {
|
|
869
|
-
await streamer.flush();
|
|
870
|
-
} else {
|
|
871
|
-
await this.onResponseComplete(envelope.chatId, response, sessionId);
|
|
872
|
-
}
|
|
873
|
-
}
|
|
874
|
-
} finally {
|
|
875
|
-
this.bridge.off("textChunk", onChunk);
|
|
876
|
-
streamer?.stop();
|
|
877
|
-
this.onPromptEnd(envelope.chatId, sessionId, envelope.messageId);
|
|
878
|
-
this.activePrompts.delete(sessionId);
|
|
879
|
-
promptState.resolve();
|
|
880
|
-
const buffer = this.collectBuffers.get(sessionId);
|
|
881
|
-
if (buffer && buffer.length > 0) {
|
|
882
|
-
this.collectBuffers.delete(sessionId);
|
|
883
|
-
const coalesced = buffer.map((b) => b.text).join("\n\n");
|
|
884
|
-
const lastEnvelope = buffer[buffer.length - 1].envelope;
|
|
885
|
-
const syntheticEnvelope = {
|
|
886
|
-
...lastEnvelope,
|
|
887
|
-
text: coalesced,
|
|
888
|
-
// Clear attachments/references — already resolved in original text
|
|
889
|
-
referencedText: void 0,
|
|
890
|
-
attachments: void 0,
|
|
891
|
-
imageBase64: void 0,
|
|
892
|
-
imageMimeType: void 0
|
|
893
|
-
};
|
|
894
|
-
this.handleInbound(syntheticEnvelope).catch(() => {
|
|
895
|
-
});
|
|
896
|
-
}
|
|
897
|
-
}
|
|
898
|
-
});
|
|
899
|
-
this.sessionQueues.set(sessionId, current.catch(() => {
|
|
900
|
-
}));
|
|
901
|
-
await current;
|
|
902
|
-
}
|
|
903
|
-
async onPairingRequired(chatId, code) {
|
|
904
|
-
if (code) {
|
|
905
|
-
await this.sendMessage(chatId, `Your pairing code is: ${code}
|
|
906
|
-
|
|
907
|
-
Ask the bot operator to approve you with:
|
|
908
|
-
qwen channel pairing approve ${this.name} ${code}`);
|
|
909
|
-
} else {
|
|
910
|
-
await this.sendMessage(chatId, "Too many pending pairing requests. Please try again later.");
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
|
-
};
|
|
914
|
-
|
|
915
|
-
// packages/channels/base/dist/index.js
|
|
916
|
-
init_esbuild_shims();
|
|
917
|
-
|
|
918
|
-
// packages/channels/base/dist/AcpBridge.js
|
|
919
|
-
init_esbuild_shims();
|
|
920
|
-
import { spawn } from "node:child_process";
|
|
921
|
-
import { Readable, Writable } from "node:stream";
|
|
922
|
-
import { EventEmitter } from "node:events";
|
|
923
|
-
var AcpBridge = class extends EventEmitter {
|
|
924
|
-
static {
|
|
925
|
-
__name(this, "AcpBridge");
|
|
926
|
-
}
|
|
927
|
-
child = null;
|
|
928
|
-
connection = null;
|
|
929
|
-
options;
|
|
930
|
-
_availableCommands = [];
|
|
931
|
-
constructor(options) {
|
|
932
|
-
super();
|
|
933
|
-
this.options = options;
|
|
934
|
-
}
|
|
935
|
-
get availableCommands() {
|
|
936
|
-
return this._availableCommands;
|
|
937
|
-
}
|
|
938
|
-
async start() {
|
|
939
|
-
const { cliEntryPath, cwd } = this.options;
|
|
940
|
-
const args = [
|
|
941
|
-
...process.execArgv.filter((a) => !/^--inspect(-brk)?($|=)/.test(a)),
|
|
942
|
-
cliEntryPath,
|
|
943
|
-
"--acp"
|
|
944
|
-
];
|
|
945
|
-
if (this.options.model) {
|
|
946
|
-
args.push("--model", this.options.model);
|
|
947
|
-
}
|
|
948
|
-
this.child = spawn(process.execPath, args, {
|
|
949
|
-
cwd,
|
|
950
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
951
|
-
env: { ...process.env },
|
|
952
|
-
shell: false
|
|
953
|
-
});
|
|
954
|
-
this.child.stderr?.on("data", (data) => {
|
|
955
|
-
const msg = data.toString().trim();
|
|
956
|
-
if (msg) {
|
|
957
|
-
process.stderr.write(`[AcpBridge] ${msg}
|
|
958
|
-
`);
|
|
959
|
-
}
|
|
960
|
-
});
|
|
961
|
-
this.child.on("exit", (code, signal) => {
|
|
962
|
-
process.stderr.write(`[AcpBridge] Process exited (code=${code}, signal=${signal})
|
|
963
|
-
`);
|
|
964
|
-
this.connection = null;
|
|
965
|
-
this.child = null;
|
|
966
|
-
this.emit("disconnected", code, signal);
|
|
967
|
-
});
|
|
968
|
-
await new Promise((resolve2) => setTimeout(resolve2, 1e3));
|
|
969
|
-
if (!this.child || this.child.killed) {
|
|
970
|
-
throw new Error("ACP process failed to start");
|
|
971
|
-
}
|
|
972
|
-
const stdout = Readable.toWeb(this.child.stdout);
|
|
973
|
-
const stdin = Writable.toWeb(this.child.stdin);
|
|
974
|
-
const stream = ndJsonStream(stdin, stdout);
|
|
975
|
-
this.connection = new ClientSideConnection(() => ({
|
|
976
|
-
sessionUpdate: /* @__PURE__ */ __name((params) => {
|
|
977
|
-
this.handleSessionUpdate(params);
|
|
978
|
-
return Promise.resolve();
|
|
979
|
-
}, "sessionUpdate"),
|
|
980
|
-
requestPermission: /* @__PURE__ */ __name(async (params) => {
|
|
981
|
-
const options = Array.isArray(params.options) ? params.options : [];
|
|
982
|
-
const optionId = options.find((o) => o.optionId === "proceed_once")?.optionId || options[0]?.optionId || "proceed_once";
|
|
983
|
-
return { outcome: { outcome: "selected", optionId } };
|
|
984
|
-
}, "requestPermission"),
|
|
985
|
-
extNotification: /* @__PURE__ */ __name(async () => {
|
|
986
|
-
}, "extNotification")
|
|
987
|
-
}), stream);
|
|
988
|
-
await this.connection.initialize({
|
|
989
|
-
protocolVersion: PROTOCOL_VERSION,
|
|
990
|
-
clientCapabilities: {}
|
|
991
|
-
});
|
|
992
|
-
}
|
|
993
|
-
async newSession(cwd) {
|
|
994
|
-
const conn = this.ensureConnection();
|
|
995
|
-
const response = await conn.newSession({ cwd, mcpServers: [] });
|
|
996
|
-
return response.sessionId;
|
|
997
|
-
}
|
|
998
|
-
async loadSession(sessionId, cwd) {
|
|
999
|
-
const conn = this.ensureConnection();
|
|
1000
|
-
const response = await conn.loadSession({
|
|
1001
|
-
sessionId,
|
|
1002
|
-
cwd,
|
|
1003
|
-
mcpServers: []
|
|
1004
|
-
});
|
|
1005
|
-
return response.sessionId;
|
|
1006
|
-
}
|
|
1007
|
-
async prompt(sessionId, text, options) {
|
|
1008
|
-
const conn = this.ensureConnection();
|
|
1009
|
-
const chunks = [];
|
|
1010
|
-
const onChunk = /* @__PURE__ */ __name((sid, chunk) => {
|
|
1011
|
-
if (sid === sessionId)
|
|
1012
|
-
chunks.push(chunk);
|
|
1013
|
-
}, "onChunk");
|
|
1014
|
-
this.on("textChunk", onChunk);
|
|
1015
|
-
const prompt = [];
|
|
1016
|
-
if (options?.imageBase64 && options.imageMimeType) {
|
|
1017
|
-
prompt.push({
|
|
1018
|
-
type: "image",
|
|
1019
|
-
data: options.imageBase64,
|
|
1020
|
-
mimeType: options.imageMimeType
|
|
1021
|
-
});
|
|
1022
|
-
}
|
|
1023
|
-
prompt.push({ type: "text", text });
|
|
1024
|
-
try {
|
|
1025
|
-
await conn.prompt({
|
|
1026
|
-
sessionId,
|
|
1027
|
-
prompt
|
|
1028
|
-
});
|
|
1029
|
-
} finally {
|
|
1030
|
-
this.off("textChunk", onChunk);
|
|
1031
|
-
}
|
|
1032
|
-
return chunks.join("");
|
|
1033
|
-
}
|
|
1034
|
-
async cancelSession(sessionId) {
|
|
1035
|
-
const conn = this.ensureConnection();
|
|
1036
|
-
await conn.cancel({ sessionId });
|
|
1037
|
-
}
|
|
1038
|
-
stop() {
|
|
1039
|
-
if (this.child) {
|
|
1040
|
-
this.child.kill();
|
|
1041
|
-
this.child = null;
|
|
1042
|
-
}
|
|
1043
|
-
this.connection = null;
|
|
1044
|
-
}
|
|
1045
|
-
get isConnected() {
|
|
1046
|
-
return this.child !== null && !this.child.killed && this.child.exitCode === null;
|
|
1047
|
-
}
|
|
1048
|
-
handleSessionUpdate(params) {
|
|
1049
|
-
const { sessionId } = params;
|
|
1050
|
-
const update = params["update"];
|
|
1051
|
-
if (!update)
|
|
1052
|
-
return;
|
|
1053
|
-
const type = update["sessionUpdate"];
|
|
1054
|
-
switch (type) {
|
|
1055
|
-
case "agent_message_chunk": {
|
|
1056
|
-
const content = update["content"];
|
|
1057
|
-
if (content?.type === "text" && content.text) {
|
|
1058
|
-
this.emit("textChunk", sessionId, content.text);
|
|
1059
|
-
}
|
|
1060
|
-
break;
|
|
1061
|
-
}
|
|
1062
|
-
case "tool_call": {
|
|
1063
|
-
const event = {
|
|
1064
|
-
sessionId,
|
|
1065
|
-
toolCallId: update["toolCallId"],
|
|
1066
|
-
kind: update["kind"] || "",
|
|
1067
|
-
title: update["title"] || "",
|
|
1068
|
-
status: update["status"] || "pending",
|
|
1069
|
-
rawInput: update["rawInput"]
|
|
1070
|
-
};
|
|
1071
|
-
this.emit("toolCall", event);
|
|
1072
|
-
break;
|
|
1073
|
-
}
|
|
1074
|
-
case "available_commands_update": {
|
|
1075
|
-
if (Array.isArray(update["availableCommands"])) {
|
|
1076
|
-
this._availableCommands = update["availableCommands"];
|
|
1077
|
-
}
|
|
1078
|
-
break;
|
|
1079
|
-
}
|
|
1080
|
-
default:
|
|
1081
|
-
break;
|
|
1082
|
-
}
|
|
1083
|
-
this.emit("sessionUpdate", params);
|
|
1084
|
-
}
|
|
1085
|
-
ensureConnection() {
|
|
1086
|
-
if (!this.connection || !this.isConnected) {
|
|
1087
|
-
throw new Error("Not connected to ACP agent");
|
|
1088
|
-
}
|
|
1089
|
-
return this.connection;
|
|
1090
|
-
}
|
|
1091
|
-
};
|
|
1092
|
-
|
|
1093
|
-
// packages/channels/base/dist/DaemonChannelBridge.js
|
|
1094
|
-
init_esbuild_shims();
|
|
1095
|
-
|
|
1096
|
-
export {
|
|
1097
|
-
resolvePath,
|
|
1098
|
-
getGlobalQwenDir,
|
|
1099
|
-
AcpBridge,
|
|
1100
|
-
PairingStore,
|
|
1101
|
-
SessionRouter,
|
|
1102
|
-
ChannelBase
|
|
1103
|
-
};
|