@qwen-code/qwen-code 0.23.2 → 0.23.3-nightly.20260911.aaa6a32aae
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/README.md +35 -15
- package/bundled/computer-use/SKILL.md +1 -1
- package/bundled/goal-draft/SKILL.md +10 -10
- package/bundled/qc-helper/docs/configuration/model-providers.md +66 -28
- package/bundled/qc-helper/docs/configuration/settings.md +8 -3
- package/bundled/qc-helper/docs/features/_meta.ts +1 -0
- package/bundled/qc-helper/docs/features/channels/dingtalk.md +0 -20
- package/bundled/qc-helper/docs/features/channels/dws.md +7 -1
- package/bundled/qc-helper/docs/features/channels/overview.md +5 -6
- package/bundled/qc-helper/docs/features/commands.md +62 -9
- package/bundled/qc-helper/docs/features/computer-use.md +1 -1
- package/bundled/qc-helper/docs/features/cross-session-protocol.md +338 -0
- package/bundled/qc-helper/docs/features/goals.md +22 -18
- package/bundled/qc-helper/docs/features/hooks.md +28 -22
- package/bundled/qc-helper/docs/features/sub-agents.md +27 -0
- package/bundled/qc-helper/docs/qwen-serve.md +23 -6
- package/bundled/review/SKILL.md +93 -80
- package/bundled/review/references/persistence.md +2 -0
- package/bundled/review/references/posting.md +31 -14
- package/bundled/workflow-authoring/SKILL.md +410 -0
- package/bundled/workflow-creator/SKILL.md +1 -1
- package/chunks/{MaxSizedBox-4C3BKKKY.js → MaxSizedBox-7C5XTBZI.js} +64 -53
- package/chunks/{StandaloneSessionPicker-TXVF65YW.js → StandaloneSessionPicker-IGTT3ZRX.js} +88 -76
- package/chunks/{acp-startup-profiler-KEU6VAYR.js → acp-startup-profiler-RUQNTNU5.js} +2 -2
- package/chunks/acp-subagent-executor-IUHVNVVO.js +140 -0
- package/chunks/{acpAgent-H5XBKGB4.js → acpAgent-W43WM2K4.js} +957 -243
- package/chunks/{agent-T5LEFJIU.js → agent-2XMXC5JW.js} +48 -38
- package/chunks/{agent-headless-VZKSRH36.js → agent-headless-2HHBVCP6.js} +48 -38
- package/chunks/{anthropicContentGenerator-PRJWWVYJ.js → anthropicContentGenerator-7RI3MPIW.js} +69 -36
- package/chunks/{artifact-tool-G5LHNECG.js → artifact-tool-HHVHCPNG.js} +59 -109
- package/chunks/{askUserQuestion-I5W5S3D6.js → askUserQuestion-RFMXTD3B.js} +2 -2
- package/chunks/{bridge-AOX5IY44.js → bridge-ID6N4IH5.js} +69 -58
- package/chunks/{ca-KC2AISNS.js → ca-MX3WCEEG.js} +1 -1
- package/chunks/{channel-management-service-MWQGHPAS.js → channel-management-service-ASCXI7FR.js} +6 -6
- package/chunks/{channel-settings-store-XZCGDGHW.js → channel-settings-store-TPJFQAZY.js} +76 -65
- package/chunks/{channel-worker-group-SQ5FRWOH.js → channel-worker-group-JR6JOELM.js} +9 -9
- package/chunks/{channel-worker-manager-TU4ZNWOE.js → channel-worker-manager-AVKJEZFL.js} +19 -10
- package/chunks/{channel-worker-supervisor-EMITFMCP.js → channel-worker-supervisor-OOYY7BAQ.js} +7 -7
- package/chunks/{chunk-4WMGYG3F.js → chunk-22FWWGSM.js} +2 -2
- package/chunks/{chunk-LWX4WDFF.js → chunk-2S5RIGZJ.js} +43 -15
- package/chunks/{chunk-CLKE4IY3.js → chunk-2SZH22YO.js} +1 -1
- package/chunks/{chunk-HJ5UJQQL.js → chunk-2UKKQGRA.js} +3639 -1804
- package/chunks/{chunk-MWIO7MF6.js → chunk-2WSLXP3W.js} +4 -0
- package/chunks/{chunk-HNLMYDQE.js → chunk-33LYAC4R.js} +10 -6
- package/chunks/{chunk-VBLAI2HA.js → chunk-3FPYT6QC.js} +0 -31
- package/chunks/{chunk-F53KKZUD.js → chunk-3LMDSCLU.js} +158 -10
- package/chunks/{chunk-WXFCI3O5.js → chunk-3MAUPOZ4.js} +2 -2
- package/chunks/{chunk-CRZBDVP2.js → chunk-432JQKIO.js} +10 -10
- package/chunks/{chunk-IRGDIDGJ.js → chunk-43RQ552L.js} +364 -84
- package/chunks/{chunk-PFKGV6PO.js → chunk-465USTVK.js} +9 -15
- package/chunks/{chunk-WG7BL3FY.js → chunk-473RJLIH.js} +1 -1
- package/chunks/{chunk-J3VZF2AL.js → chunk-4O2AXZXU.js} +2 -2
- package/chunks/{chunk-N6S3NUYJ.js → chunk-55VOWZ4C.js} +1 -1
- package/chunks/{chunk-OWCFKIFQ.js → chunk-5CZMWDJI.js} +2 -2
- package/chunks/{chunk-7NDZKE2M.js → chunk-5MUIHID6.js} +5 -5
- package/chunks/{chunk-RM244SCQ.js → chunk-5Z74GE4N.js} +1 -1
- package/chunks/{chunk-G5VOXCRX.js → chunk-6375QMAO.js} +2 -2
- package/chunks/{chunk-3LPJ776W.js → chunk-63GQZKXL.js} +164 -31
- package/chunks/{chunk-O2FEO2CB.js → chunk-6GDELAVL.js} +18 -2
- package/chunks/{chunk-7PD7ZMX5.js → chunk-6HI2I3OM.js} +168 -6
- package/chunks/{chunk-CALNF3Z3.js → chunk-7C57HCOR.js} +1 -1
- package/chunks/{chunk-UYDQYDW2.js → chunk-7IBS746B.js} +1 -1
- package/chunks/{chunk-AUTUFD5X.js → chunk-ABNX6E6K.js} +1 -1
- package/chunks/chunk-ACHCT36C.js +28 -0
- package/chunks/{chunk-2WC3Y7YY.js → chunk-AEY27Z35.js} +401 -23
- package/chunks/{chunk-AO2VMS72.js → chunk-AQFRRH73.js} +3 -3
- package/chunks/{chunk-PDN7FJZV.js → chunk-ASWEMQIZ.js} +4 -4
- package/chunks/chunk-AYEJOTIU.js +43 -0
- package/chunks/{chunk-QFJZAY7W.js → chunk-BKFRA4F5.js} +5 -5
- package/chunks/{chunk-KCF2436G.js → chunk-BNLW5N6U.js} +4 -4
- package/chunks/{chunk-GOKAOSCN.js → chunk-BRFOZEPA.js} +2 -2
- package/chunks/{process-registry-OAEG6WGC.js → chunk-BYUAT5OC.js} +1 -0
- package/chunks/chunk-C5CECJ46.js +340 -0
- package/chunks/{chunk-NOO4QFXM.js → chunk-C75BXMPM.js} +1 -3
- package/chunks/chunk-CAAMI77K.js +937 -0
- package/chunks/{chunk-QTB4VP4K.js → chunk-CBGHRAWM.js} +304 -23
- package/chunks/chunk-CF5KXZZX.js +150 -0
- package/chunks/chunk-CFMZLE3L.js +75 -0
- package/chunks/{chunk-TGNNLRC3.js → chunk-CJ3DHN5I.js} +1 -0
- package/chunks/{chunk-ERXNTINK.js → chunk-CQZJYGRX.js} +1 -1
- package/chunks/{chunk-WBU2PIZ5.js → chunk-CSDKDHWV.js} +23 -16
- package/chunks/{chunk-2EKVPSIJ.js → chunk-D754KKNZ.js} +9 -2
- package/chunks/{chunk-E6TI726I.js → chunk-DGC7BKEZ.js} +1 -1
- package/chunks/{chunk-7SVM3RP2.js → chunk-DMMOQWRF.js} +4 -6
- package/chunks/{chunk-J3TJH52D.js → chunk-DOTF2PF2.js} +1 -1
- package/chunks/{chunk-2BMXHB6N.js → chunk-DWBNQR53.js} +7 -7
- package/chunks/{chunk-ZN5TKAVR.js → chunk-E5LTUWKZ.js} +3 -3
- package/chunks/chunk-EGW3ZP6Y.js +32 -0
- package/chunks/chunk-ELRMZTPF.js +374 -0
- package/chunks/{chunk-RNAJVXUG.js → chunk-ENAUXRPG.js} +6 -6
- package/chunks/{chunk-WXD7INFV.js → chunk-EO4U2X47.js} +10 -8
- package/chunks/{chunk-WDVV3LRM.js → chunk-EPVEPTI3.js} +45 -152
- package/chunks/chunk-ERU3SDXT.js +27 -0
- package/chunks/{chunk-4HOEU2OR.js → chunk-EWJTAP3Y.js} +1 -19
- package/chunks/{chunk-GSFV5RQW.js → chunk-EYN3G5XD.js} +328 -4
- package/chunks/{chunk-QB3KS3N3.js → chunk-FGROOEKM.js} +5 -40
- package/chunks/{chunk-TOOOLHVS.js → chunk-FH5AVEWJ.js} +3 -3
- package/chunks/{chunk-DAI65CMX.js → chunk-FJZWRNEW.js} +1 -1
- package/chunks/{chunk-GNY7B3CA.js → chunk-FUQK5ZNL.js} +1 -1
- package/chunks/{chunk-GOEVQADN.js → chunk-GDIPPCW6.js} +330 -175
- package/chunks/{chunk-ALMR3E6Q.js → chunk-GDWE23OR.js} +3 -3
- package/chunks/{chunk-LNYV4GXX.js → chunk-GSKX53AN.js} +0 -139
- package/chunks/{chunk-ELD3OBPU.js → chunk-GWOVD63C.js} +3 -3
- package/chunks/{chunk-IWABUX6T.js → chunk-GX5FF2IE.js} +6 -6
- package/chunks/{chunk-22GORRNY.js → chunk-GZMNHAYC.js} +1 -1
- package/chunks/{chunk-YZTGGCEE.js → chunk-H3TFIFX3.js} +1 -1
- package/chunks/{chunk-6G4V7SE4.js → chunk-HG46TTAG.js} +1 -1
- package/chunks/{chunk-FETY36NQ.js → chunk-HGEUHUEV.js} +1 -1
- package/chunks/{chunk-KEPC5BOL.js → chunk-IBRQG2MP.js} +12 -15
- package/chunks/{chunk-OXR34GCD.js → chunk-IILWL3KY.js} +2054 -146
- package/chunks/{chunk-IW6RQPQB.js → chunk-IJOS26LH.js} +1 -3
- package/chunks/{chunk-ORFIYTI2.js → chunk-IK2MWJP5.js} +1 -1
- package/chunks/{chunk-CMWU6P4D.js → chunk-IRJRB3OD.js} +1 -1
- package/chunks/{chunk-QHLHE2OT.js → chunk-IUN5ZMFY.js} +1 -1
- package/chunks/{chunk-LYT2OU7D.js → chunk-IXXV6BVB.js} +172 -6
- package/chunks/{chunk-R3JIDRUL.js → chunk-J6H4JP25.js} +4 -4
- package/chunks/{chunk-NB3NDQQK.js → chunk-J6SBP5G2.js} +1 -1
- package/chunks/{chunk-TRQNRP2H.js → chunk-J7LBAKDH.js} +46 -3
- package/chunks/{chunk-67XTVRVB.js → chunk-JJFHISXU.js} +30 -25
- package/chunks/chunk-JL6APGBX.js +43 -0
- package/chunks/{chunk-NX7ZTXFF.js → chunk-JSKEW4E7.js} +2 -1
- package/chunks/{chunk-BK7D2JR6.js → chunk-JVTXAA35.js} +3 -3
- package/chunks/chunk-K2OJUPOE.js +78 -0
- package/chunks/{chunk-G3ZUMSFS.js → chunk-K3U6VB3O.js} +6 -6
- package/chunks/{chunk-4I3WFI3U.js → chunk-K4KWLF7Q.js} +12 -12
- package/chunks/{chunk-WXPPUPHM.js → chunk-KWFFJ6AK.js} +1 -1
- package/chunks/{chunk-46MMBZHI.js → chunk-KZYOFJ6V.js} +4 -4
- package/chunks/{chunk-ULZECEIP.js → chunk-LDQHA6L4.js} +2 -20
- package/chunks/{chunk-7LTCFO6T.js → chunk-LQBAFO5D.js} +6 -5
- package/chunks/{chunk-SOA4HKRJ.js → chunk-LT2XFADM.js} +2 -2
- package/chunks/{chunk-JYGIJA4W.js → chunk-LWWRJRCD.js} +1 -1
- package/chunks/{chunk-YQGW3M6Z.js → chunk-MFQWRBFB.js} +5 -5
- package/chunks/{chunk-TODNHE76.js → chunk-MUFGTWQH.js} +5 -5
- package/chunks/{chunk-5DQ4YTIZ.js → chunk-MV5XRRML.js} +3 -3
- package/chunks/{chunk-IR6JKBAP.js → chunk-NOUK63IR.js} +2 -2
- package/chunks/{chunk-XQ4RDO5B.js → chunk-NV77SEX3.js} +1 -1
- package/chunks/{chunk-OFVAS4AR.js → chunk-NWDPOFJI.js} +2 -2
- package/chunks/chunk-NY6OPAPS.js +820 -0
- package/chunks/{chunk-WDN64MVT.js → chunk-O5VX66FB.js} +127 -18
- package/chunks/{chunk-MV5DTLJV.js → chunk-OHCR4O3U.js} +1 -1
- package/chunks/{chunk-LEAOJ43M.js → chunk-OKOPKQ2X.js} +1310 -2107
- package/chunks/{chunk-B25JYXZE.js → chunk-ONLJBOI2.js} +971 -17
- package/chunks/{chunk-QQK4L3UU.js → chunk-OWUAZXXN.js} +132 -26
- package/chunks/{chunk-R457KFV7.js → chunk-P42IUOAO.js} +3 -3
- package/chunks/{chunk-LUNC5KCL.js → chunk-PRELUGCQ.js} +214 -39
- package/chunks/{chunk-5OZUKLL7.js → chunk-QSMQKTXV.js} +4 -4
- package/chunks/{chunk-FAJPLSYF.js → chunk-QTQYLQ5A.js} +85 -81
- package/chunks/{chunk-CALTQWTZ.js → chunk-QVZDV4ZS.js} +2 -2
- package/chunks/{chunk-J6MB5ZHZ.js → chunk-QZW6WRB7.js} +2 -1
- package/chunks/{chunk-KFECPHLV.js → chunk-RBWAGV73.js} +3 -3
- package/chunks/{chunk-4VY3ITHR.js → chunk-RF5RQRTD.js} +3 -3
- package/chunks/{chunk-HIXUUCGY.js → chunk-RPMXMR6U.js} +2 -2
- package/chunks/{chunk-3OAXF3UK.js → chunk-RRQEZBL2.js} +3756 -1343
- package/chunks/{chunk-4ALNJDHL.js → chunk-RSGEAWFJ.js} +19 -1
- package/chunks/{chunk-5BH2AIEY.js → chunk-RUE62UH6.js} +2 -2
- package/chunks/{chunk-PQEISIKS.js → chunk-SAH4BD2J.js} +0 -67
- package/chunks/{chunk-A7EFXK7P.js → chunk-SAOJHRWY.js} +2 -2
- package/chunks/{chunk-JO77FGNZ.js → chunk-SDUIETBG.js} +19 -7
- package/chunks/{chunk-6RZX2HIH.js → chunk-TBEXLLAO.js} +2 -2
- package/chunks/{chunk-PSPAM24S.js → chunk-TBSCTWKF.js} +6 -0
- package/chunks/{chunk-HRPFBHW7.js → chunk-TPKQIA7G.js} +1 -0
- package/chunks/{chunk-XDNFODER.js → chunk-TUIW5LLK.js} +1 -1
- package/chunks/{chunk-APXIW2TF.js → chunk-TVV5FA3G.js} +4 -4
- package/chunks/chunk-U6H3XTFA.js +95 -0
- package/chunks/{chunk-S5QR6CB5.js → chunk-UKMWZ5NS.js} +108 -887
- package/chunks/{chunk-U6REWGVR.js → chunk-VG2BRSEK.js} +2 -2
- package/chunks/chunk-VGBOJH2D.js +127 -0
- package/chunks/chunk-VGY2RGXL.js +100 -0
- package/chunks/{chunk-ZP5XDLSA.js → chunk-VLWG3EHY.js} +12 -12
- package/chunks/{chunk-4JNHNVAZ.js → chunk-W547PYQ7.js} +9 -4
- package/chunks/{chunk-7VEYUF3N.js → chunk-W5ZQMAEM.js} +1 -1
- package/chunks/{chunk-QAZ2MGYT.js → chunk-W7JJLUSB.js} +2 -2
- package/chunks/{chunk-CCBTNJB4.js → chunk-W7Q7XDQI.js} +39 -27
- package/chunks/{chunk-DARWOZY6.js → chunk-WD6YQI5M.js} +1 -1
- package/chunks/{chunk-F2NYVASI.js → chunk-WXAWG3JS.js} +30 -13
- package/chunks/{chunk-NPKCVSXX.js → chunk-XB5JRCAM.js} +11 -9
- package/chunks/{chunk-XSOXPG2L.js → chunk-XE46RQFI.js} +136 -8
- package/chunks/{chunk-QTNCGZHQ.js → chunk-XX5HQLCZ.js} +16 -0
- package/chunks/{chunk-2Z3T52OC.js → chunk-Y5TM7SBV.js} +7 -2
- package/chunks/chunk-YC6XOB5N.js +691 -0
- package/chunks/{chunk-CWVZBIZJ.js → chunk-YDW4ERSS.js} +1 -1
- package/chunks/{chunk-TRWQQBVH.js → chunk-YGCTOXUT.js} +10 -24
- package/chunks/{chunk-WK7P62DV.js → chunk-YKC67ZEF.js} +6 -6
- package/chunks/{chunk-KA5HR3G2.js → chunk-YKM6MITI.js} +5 -5
- package/chunks/{chunk-X7LFJF5D.js → chunk-YM6KUQ2S.js} +36 -84
- package/chunks/{chunk-HZ2HUXX7.js → chunk-YS2ZJSOA.js} +29 -12
- package/chunks/{chunk-G37O7YO6.js → chunk-ZAWM6KRF.js} +3 -3
- package/chunks/{chunk-H3Q3RSKZ.js → chunk-ZFIWHBJ3.js} +1 -1
- package/chunks/{chunk-XBVNNDPK.js → chunk-ZHKTKHMO.js} +8 -1
- package/chunks/{chunk-YLOHCA6I.js → chunk-ZKWO4CF4.js} +2 -2
- package/chunks/{chunk-VJJXG73H.js → chunk-ZMQL5BL5.js} +21 -6
- package/chunks/{chunk-FGHPZGOP.js → chunk-ZMUYBOYB.js} +39 -55
- package/chunks/{chunk-FV4DM2M4.js → chunk-ZNI3YJHS.js} +26 -6
- package/chunks/{chunk-565U2ANU.js → chunk-ZTTC7T4X.js} +1 -1
- package/chunks/{chunk-7OCIQNKX.js → chunk-ZW2EUO2A.js} +1 -1
- package/chunks/codex-subagent-executor-26XOHVKH.js +585 -0
- package/chunks/{config-utils-GPLIABL2.js → config-utils-JUG3MOYN.js} +68 -57
- package/chunks/{contextCommand-NCUQUDBY.js → contextCommand-6K3POZFA.js} +65 -54
- package/chunks/{core-runtime-WKYKWVYU.js → core-runtime-XQFZLA2V.js} +66 -55
- package/chunks/{create-sub-session-TGIX63YU.js → create-sub-session-4UJ6RM6W.js} +5 -2
- package/chunks/{create-sub-session-PPLXB3JJ.js → create-sub-session-T4IYIOC7.js} +178 -91
- package/chunks/{cron-create-GTPVMJCF.js → cron-create-6466RWSO.js} +2 -2
- package/chunks/{cron-delete-ZBK27Z4K.js → cron-delete-W4QUWHOA.js} +2 -2
- package/chunks/{cron-list-KTFKFDKC.js → cron-list-Q5LJ5PZE.js} +2 -2
- package/chunks/{daemon-2CKIAO3I.js → daemon-PHPJUXDZ.js} +4 -2
- package/chunks/{daemon-git-worktree-guard-73ZWOLKL.js → daemon-git-worktree-guard-5WEMZ64U.js} +65 -54
- package/chunks/{daemon-status-provider-OK7VONJG.js → daemon-status-provider-GMD7QD4T.js} +74 -63
- package/chunks/{daemon-trust-policy-CAUCREG2.js → daemon-trust-policy-IPBZES2Z.js} +71 -60
- package/chunks/{daemon-trust-policy-monitor-3Y36OOEQ.js → daemon-trust-policy-monitor-MHYEN7X7.js} +71 -60
- package/chunks/{de-UU2YTO37.js → de-OOLZAU2U.js} +1 -1
- package/chunks/{deferred-core-runtime-Q7WFWYD3.js → deferred-core-runtime-CY43FZNZ.js} +63 -52
- package/chunks/{discovery-XP4RMDUM.js → discovery-5KUEPR65.js} +2 -2
- package/chunks/{display-image-CTNHJRZC.js → display-image-6AZIHP3J.js} +3 -3
- package/chunks/{dist-F34J4FZX.js → dist-2QYIVNS6.js} +2 -5
- package/chunks/{dist-6YDUH3BB.js → dist-GIMQXYLI.js} +10 -631
- package/chunks/{dist-NP7QKLVG.js → dist-GUB7QRYA.js} +3 -6
- package/chunks/{dist-Y5KC3IHW.js → dist-L45UB6DG.js} +233 -35
- package/chunks/{dist-XLV33CLY.js → dist-MPUZZOG5.js} +5 -18
- package/chunks/{dist-ZDNJK74R.js → dist-PA7WPFVE.js} +6 -37
- package/chunks/{dist-F6JLAJLE.js → dist-T6DDPDLQ.js} +16 -36
- package/chunks/{dist-BNQVF565.js → dist-TFGETXFN.js} +14 -37
- package/chunks/{dist-UFTFGI6I.js → dist-VDLSBCLM.js} +2 -6
- package/chunks/{edit-YJD6IETK.js → edit-6NUP5IPX.js} +48 -38
- package/chunks/{en-YJNRUQG4.js → en-ZSZW3PZX.js} +4 -1
- package/chunks/{enter-worktree-YFTKHXHZ.js → enter-worktree-EETDMJRF.js} +5 -5
- package/chunks/{enterPlanMode-EFPVTWIH.js → enterPlanMode-AZHYHEII.js} +48 -38
- package/chunks/{environment-HP3AXFTB.js → environment-ON6GIQ4F.js} +66 -55
- package/chunks/{errors-22ON46G7.js → errors-DQE63SCC.js} +65 -54
- package/chunks/exec-66WQIVYU.js +505 -0
- package/chunks/{exit-worktree-NF2XEMES.js → exit-worktree-DIPJ6S55.js} +5 -5
- package/chunks/{exitPlanMode-MOQUNCBH.js → exitPlanMode-NHBV6LAI.js} +48 -38
- package/chunks/{fast-path-2X7BPMXX.js → fast-path-EPJSUZZC.js} +7 -7
- package/chunks/{fast-path-settings-SATXY3PD.js → fast-path-settings-XDYX7X5Z.js} +2 -2
- package/chunks/{fr-HKNWVXRJ.js → fr-JJWM2HUS.js} +1 -1
- package/chunks/{glob-Y7ACIB3P.js → glob-MNEXQ2NV.js} +51 -41
- package/chunks/{goal-tools-DABMICUC.js → goal-tools-D2A4QBCJ.js} +54 -40
- package/chunks/{grep-BLHF2S5D.js → grep-EFWPV3MM.js} +2 -2
- package/chunks/{handleAutoUpdate-MCAMHYDI.js → handleAutoUpdate-2RY3OQA6.js} +67 -56
- package/chunks/{i18n-C3GDCALP.js → i18n-HTHDB3I7.js} +64 -53
- package/chunks/{image-gen-XP4NNIYG.js → image-gen-2PHED3P4.js} +8 -6
- package/chunks/{initializer-4URDQL2G.js → initializer-JEVLJCQA.js} +71 -60
- package/chunks/{installationInfo-LBOL6SBV.js → installationInfo-ITRB6J4L.js} +63 -52
- package/chunks/{ja-GJS5RZGU.js → ja-L67TXFDJ.js} +1 -1
- package/chunks/list-KOUIMHT5.js +133 -0
- package/chunks/{list-agents-2CXPGJUE.js → list-agents-IY4NEWLP.js} +17 -7
- package/chunks/{llm-2KPNSAVY.js → llm-F7WHGESY.js} +132 -120
- package/chunks/{llm-content-generator-GR3FOHLB.js → llm-content-generator-NYQ2NAVA.js} +6 -5
- package/chunks/{loadedSettingsAdapter-DVKROEJD.js → loadedSettingsAdapter-HZUAX5CX.js} +71 -60
- package/chunks/{loggingContentGenerator-P4K6K5W4.js → loggingContentGenerator-WMNU7C5J.js} +70 -59
- package/chunks/{loop-wakeup-HL6XOWI4.js → loop-wakeup-ANX25YW2.js} +3 -3
- package/chunks/{ls-YV7RKLKY.js → ls-4XCMJNZF.js} +4 -4
- package/chunks/{lsp-NO3AMRZT.js → lsp-K5E2Y64R.js} +1 -1
- package/chunks/{managed-npm-update-VWBKHNIN.js → managed-npm-update-EJJB65QI.js} +63 -52
- package/chunks/mcp-I73R6HS3.js +127 -0
- package/chunks/{monitor-A255TNZR.js → monitor-T56GJNA4.js} +50 -40
- package/chunks/{nonInteractiveCli-LXGIKQAT.js → nonInteractiveCli-CKHHJ423.js} +120 -109
- package/chunks/{notebook-edit-5UYHS2DM.js → notebook-edit-W5TU3EZ3.js} +48 -38
- package/chunks/openai-WX26N5OJ.js +47 -0
- package/chunks/{openaiContentGenerator-A6MAMEO5.js → openaiContentGenerator-TH6YAWAH.js} +33 -25
- package/chunks/openaiResponsesContentGenerator-EWLWQPKS.js +1738 -0
- package/chunks/{pidfile-B7DZC4TP.js → pidfile-RCC6TCEM.js} +63 -52
- package/chunks/process-registry-X6ZCASEN.js +10 -0
- package/chunks/{processUtils-BPZ2MCZS.js → processUtils-DQDQBRMC.js} +2 -2
- package/chunks/{prompt-terminal-ledger-FYYTAOXS.js → prompt-terminal-ledger-2LXWAGWU.js} +64 -53
- package/chunks/{pt-FXMYXEUV.js → pt-77SBDL4B.js} +1 -1
- package/chunks/{qwenContentGenerator-4IOJFD4S.js → qwenContentGenerator-LG65Z2YV.js} +61 -49
- package/chunks/{qwenOAuth2-KX6LVYQ3.js → qwenOAuth2-PJ63CCFD.js} +7 -5
- package/chunks/{read-file-A4H4O3VQ.js → read-file-72HMRUT4.js} +12 -9
- package/chunks/{read-mcp-resource-D3N75DGF.js → read-mcp-resource-NPF44YSC.js} +1 -1
- package/chunks/{record-artifact-Q5CRGJTP.js → record-artifact-MDXCCW2J.js} +3 -3
- package/chunks/record-source-VJLKDGGR.js +22 -0
- package/chunks/{report-findings-TJ34R7QK.js → report-findings-CZTYMZTC.js} +4 -4
- package/chunks/{request-shutdown-LRKMTBAD.js → request-shutdown-KOZHPVZU.js} +5 -5
- package/chunks/{resumeHistoryUtils-YQQ43E4N.js → resumeHistoryUtils-S2Q3M3EH.js} +69 -58
- package/chunks/{ripGrep-W32NWFTA.js → ripGrep-B2I3L5CO.js} +17 -13
- package/chunks/{ru-RMHURE5U.js → ru-UYWHKWF2.js} +1 -1
- package/chunks/{run-qwen-serve-WBSWWIRV.js → run-qwen-serve-AOPYFCVP.js} +305 -132
- package/chunks/{runtime-VRVBX2E5.js → runtime-TZMHKZAP.js} +77 -66
- package/chunks/{scheduled-tasks-D65KJDA3.js → scheduled-tasks-7RL6ZOYT.js} +72 -60
- package/chunks/{scheduler-M2YPN7Z7.js → scheduler-D6RLOFNU.js} +65 -54
- package/chunks/{sdk-exporters-grpc-MXTVSE3C.js → sdk-exporters-grpc-Y2ZUQDUQ.js} +2 -2
- package/chunks/{sdk-exporters-http-7R2ARBPV.js → sdk-exporters-http-VWTF4W6K.js} +3 -3
- package/chunks/{sdk-impl-YOLO7LV4.js → sdk-impl-G6FVTBQZ.js} +9 -9
- package/chunks/{send-message-76BKWKFZ.js → send-message-MMZVSS7P.js} +12 -9
- package/chunks/{serve-BE3H2P6P.js → serve-HWWDYI37.js} +72 -61
- package/chunks/{server-FLY5JERG.js → server-MD2X5U5L.js} +3156 -564
- package/chunks/{session-JVN62R5K.js → session-AFUMFNN7.js} +124 -113
- package/chunks/{session-attachments-root-7ACGLHXA.js → session-attachments-root-QPN3YWTY.js} +63 -52
- package/chunks/{session-pr-refresh-TQS57SDK.js → session-pr-refresh-4Y2ANMJX.js} +72 -60
- package/chunks/{settings-D44YMZFT.js → settings-QQRQ2LR7.js} +74 -63
- package/chunks/{shell-3VE6I4V5.js → shell-NUYUYMVI.js} +48 -38
- package/chunks/{skill-FHEGRRZU.js → skill-KHLDVOXW.js} +68 -30
- package/chunks/{skill-settings-VHEJMBFL.js → skill-settings-INLEGDEZ.js} +70 -59
- package/chunks/{spawnChannel-T6MX2ZDN.js → spawnChannel-KBGZHW2G.js} +67 -56
- package/chunks/{standalone-update-QUGHFMCS.js → standalone-update-3QP5NDVJ.js} +65 -54
- package/chunks/{start-opentui-ui-IHIIZ2LE.js → start-opentui-ui-VBT3XDWN.js} +2682 -2153
- package/chunks/{startInteractiveUI-LR7K2ARZ.js → startInteractiveUI-AZHKCHMR.js} +1562 -2317
- package/chunks/{syntheticOutput-D2P5V6RG.js → syntheticOutput-KRASPDE3.js} +2 -2
- package/chunks/{task-create-MWXJFRRM.js → task-create-TNXNT7ZD.js} +8 -8
- package/chunks/{task-list-EYO3FE57.js → task-list-FHNIJDKT.js} +1 -1
- package/chunks/{task-stop-BFSKRTGV.js → task-stop-MG4ZMTEI.js} +1 -1
- package/chunks/{task-update-2JJJRHMT.js → task-update-4HU62CJT.js} +8 -8
- package/chunks/{team-create-GY3VFY47.js → team-create-K5DNSJXR.js} +50 -40
- package/chunks/{team-delete-IQZ6XGFI.js → team-delete-2T44GUNN.js} +1 -1
- package/chunks/{team-plan-approval-BQPGZOT5.js → team-plan-approval-2ZNAQT2A.js} +48 -38
- package/chunks/{terminal-image-renderer-YNYW5CQG.js → terminal-image-renderer-23CW4A6Q.js} +65 -54
- package/chunks/{theme-manager-U6CIK3GM.js → theme-manager-G2333AMH.js} +63 -52
- package/chunks/{todoWrite-5ERKFWAK.js → todoWrite-BO2GR5MN.js} +4 -4
- package/chunks/{tool-search-XI3QWD5I.js → tool-search-MKQCKXN5.js} +22 -15
- package/chunks/{total-session-admission-3SNSJJ32.js → total-session-admission-ENKTM2KX.js} +69 -58
- package/chunks/{trustedFolders-OVAQKNV5.js → trustedFolders-2ETDL7OD.js} +64 -53
- package/chunks/{update-relaunch-XV5O74E3.js → update-relaunch-FMVNN5KA.js} +5 -5
- package/chunks/{updateCheck-CHUYWD6L.js → updateCheck-KWRV5KLJ.js} +66 -55
- package/chunks/{useAutoAcceptIndicator-VKSVIXZC.js → useAutoAcceptIndicator-7AUXAIQF.js} +73 -62
- package/chunks/{validateNonInterActiveAuth-ZNUTD3E5.js → validateNonInterActiveAuth-NETKLLDV.js} +117 -106
- package/chunks/{version-EK7VAGSI.js → version-DACNN2ZM.js} +1 -1
- package/chunks/{web-fetch-24KZO763.js → web-fetch-CIVCRET4.js} +16 -12
- package/chunks/{web-search-CRNXKZ2X.js → web-search-GOHZRGMM.js} +389 -327
- package/chunks/{web-shell-static-BFDESDD4.js → web-shell-static-T7UGLVE4.js} +2 -7
- package/chunks/workflow-IL2FOALZ.js +1324 -0
- package/chunks/workspace-providers-status-YGXL6N5U.js +131 -0
- package/chunks/{workspace-registration-store-HKLJEDQX.js → workspace-registration-store-E4IAOFFZ.js} +3 -1
- package/chunks/{workspace-registry-7RDDOBLN.js → workspace-registry-KX6BIBYK.js} +69 -58
- package/chunks/{workspace-runtime-coordinator-LEPDPXJO.js → workspace-runtime-coordinator-2KYYGDDR.js} +72 -59
- package/chunks/{workspace-service-5IFDCNN3.js → workspace-service-5Q6LWBYR.js} +76 -65
- package/chunks/{workspace-skills-status-FJ3HNH4H.js → workspace-skills-status-PJZTFPVV.js} +72 -61
- package/chunks/{workspace-trust-reconciler-PQFHIWLR.js → workspace-trust-reconciler-HS6PWNEA.js} +77 -66
- package/chunks/{write-file-ERG67ZFX.js → write-file-JB3DRM7O.js} +50 -40
- package/chunks/{zh-VBFCRQBL.js → zh-7UJA4ICT.js} +4 -1
- package/chunks/{zh-TW-N2TBF2F2.js → zh-TW-RV24PWUI.js} +4 -1
- package/chunks/{zoom-image-WQYEC3SR.js → zoom-image-AVHQFOOQ.js} +12 -9
- package/cli.js +16 -16
- package/codeModeHost.js +4425 -0
- package/export-transcript-document.css +1 -0
- package/export-transcript-document.js +164 -165
- package/locales/ca.js +2 -2
- package/locales/de.js +2 -2
- package/locales/en.js +5 -2
- package/locales/fr.js +2 -2
- package/locales/ja.js +2 -2
- package/locales/pt.js +2 -2
- package/locales/ru.js +2 -2
- package/locales/zh-TW.js +5 -2
- package/locales/zh.js +5 -2
- package/package.json +6 -4
- package/web-shell/assets/{abnfDiagram-VCTEODGH-BRLgQbnT.js → abnfDiagram-VCTEODGH-BH2nK5Z_.js} +1 -1
- package/web-shell/assets/{arc-qAF9_XsR.js → arc-CUUQ6krv.js} +1 -1
- package/web-shell/assets/{architectureDiagram-5GKGNRK7-BorUttEz.js → architectureDiagram-5GKGNRK7-CJjiRuGx.js} +1 -1
- package/web-shell/assets/{blockDiagram-NRAW4CY4-Bj0qZVxu.js → blockDiagram-NRAW4CY4-GCDyU9ZX.js} +1 -1
- package/web-shell/assets/{c4Diagram-UCG6FXSJ-BTqJis32.js → c4Diagram-UCG6FXSJ-C68MiN6h.js} +1 -1
- package/web-shell/assets/channel-DauVlmdF.js +1 -0
- package/web-shell/assets/{chunk-2Q5K7J3B-RrQ5X8m-.js → chunk-2Q5K7J3B-_8B6frXZ.js} +1 -1
- package/web-shell/assets/{chunk-5VM5RSS4-uUjDl8wO.js → chunk-5VM5RSS4-CroSinX7.js} +1 -1
- package/web-shell/assets/{chunk-F27PBJKO-C3JhpyzI.js → chunk-F27PBJKO-CGn4Z0Fx.js} +1 -1
- package/web-shell/assets/{chunk-G27WJ6UU-C8ZNFs7F.js → chunk-G27WJ6UU-BI5nLQcf.js} +1 -1
- package/web-shell/assets/{chunk-JWPE2WC7-DNpXtEOs.js → chunk-JWPE2WC7-CYJH0FuH.js} +1 -1
- package/web-shell/assets/{chunk-LCL6LL3I-DagA2ZLw.js → chunk-LCL6LL3I-DjWZUqA1.js} +1 -1
- package/web-shell/assets/{chunk-POPQ4Y6H-R23uH7Xm.js → chunk-POPQ4Y6H-DcTkIHm8.js} +1 -1
- package/web-shell/assets/{chunk-SVP7TREG-Qz9RN_BR.js → chunk-SVP7TREG-E8sZT5uK.js} +1 -1
- package/web-shell/assets/{chunk-XXDRQBXY-jYb1_hni.js → chunk-XXDRQBXY-CurjPKw_.js} +1 -1
- package/web-shell/assets/classDiagram-DTDB5LWJ-BuIh7bj1.js +1 -0
- package/web-shell/assets/classDiagram-v2-JRS7N3AN-BuIh7bj1.js +1 -0
- package/web-shell/assets/{cose-bilkent-JH36ORCC-Cv2OunpE.js → cose-bilkent-JH36ORCC-CJEnNhth.js} +1 -1
- package/web-shell/assets/{cynefin-OW5HDTMX-LH42KFJx.js → cynefin-OW5HDTMX-jwEkm0yw.js} +1 -1
- package/web-shell/assets/{cynefinDiagram-5FMLGOSQ-Dha4_OoR.js → cynefinDiagram-5FMLGOSQ-B-OVQ6AO.js} +1 -1
- package/web-shell/assets/{dagre-3AP2YEHR-Br5lnUKD.js → dagre-3AP2YEHR-CKKK9WNR.js} +1 -1
- package/web-shell/assets/{diagram-S7CK7UJ4-dpKq2bBX.js → diagram-S7CK7UJ4-D486veFQ.js} +1 -1
- package/web-shell/assets/{diagram-UQ7AKVKN-BAgHWpXr.js → diagram-UQ7AKVKN-C3GujqHv.js} +1 -1
- package/web-shell/assets/{diagram-VSXAHHWV-GRRzpyE2.js → diagram-VSXAHHWV-BrOTDwuU.js} +1 -1
- package/web-shell/assets/{diagram-VX7I27RA-BNFiaYpG.js → diagram-VX7I27RA-C4D9kWE3.js} +1 -1
- package/web-shell/assets/{diagram-Z3DM3KII-BisZzB_h.js → diagram-Z3DM3KII-7rAManT0.js} +1 -1
- package/web-shell/assets/{ebnfDiagram-PWID7BFC-B1xbwycf.js → ebnfDiagram-PWID7BFC-CqVzKOdr.js} +1 -1
- package/web-shell/assets/{erDiagram-SSCWMZ5O-CQMzbGE5.js → erDiagram-SSCWMZ5O-D2s08fc_.js} +1 -1
- package/web-shell/assets/{flowDiagram-A5DVABFB-CZ_Zondl.js → flowDiagram-A5DVABFB-CrKtBxB2.js} +1 -1
- package/web-shell/assets/{ganttDiagram-EL5Y4UJY-BTh2ShxS.js → ganttDiagram-EL5Y4UJY-CD1CKdlt.js} +1 -1
- package/web-shell/assets/{gitGraphDiagram-WWUBYQGX-oHOB-Uxt.js → gitGraphDiagram-WWUBYQGX-CHDXdVNn.js} +1 -1
- package/web-shell/assets/index-D8tzgUOC.css +36 -0
- package/web-shell/assets/{index-DWoFMu5x.js → index-DWz95m74.js} +1 -1
- package/web-shell/assets/index-cDFf68Wd.js +2204 -0
- package/web-shell/assets/{infoDiagram-RXCK75RN-C0QpudbG.js → infoDiagram-RXCK75RN-Cr1oLCwe.js} +1 -1
- package/web-shell/assets/{ishikawaDiagram-5VMMS53U-a6B741uT.js → ishikawaDiagram-5VMMS53U--RghV1mm.js} +1 -1
- package/web-shell/assets/{journeyDiagram-EYS64GPL-Dbht9ICp.js → journeyDiagram-EYS64GPL-MN1ZkGW8.js} +1 -1
- package/web-shell/assets/{kanban-definition-3QL26DDD-D4OFR8-h.js → kanban-definition-3QL26DDD-DL05VTn0.js} +1 -1
- package/web-shell/assets/{layout-Dvdh5jRH.js → layout-D_TvQzvn.js} +1 -1
- package/web-shell/assets/{linear-Dvc6KIW2.js → linear-B_0OH6XF.js} +1 -1
- package/web-shell/assets/{mermaid.core-CB36RfIb.js → mermaid.core-B9Nklh9I.js} +6 -6
- package/web-shell/assets/{mindmap-definition-FBJOCRG2-Fmqo1CjP.js → mindmap-definition-FBJOCRG2-CevIQ0LR.js} +1 -1
- package/web-shell/assets/{pegDiagram-XKGWAZYB-CCxYBoA4.js → pegDiagram-XKGWAZYB-DQ8PIv0d.js} +1 -1
- package/web-shell/assets/{pieDiagram-E7YTZNPT-BVHKQFzt.js → pieDiagram-E7YTZNPT-BVTV1pPe.js} +1 -1
- package/web-shell/assets/{quadrantDiagram-AXDQQJYC-l95IznwR.js → quadrantDiagram-AXDQQJYC-DHN6nhpe.js} +1 -1
- package/web-shell/assets/qwen-code-notification-BRVagufF.png +0 -0
- package/web-shell/assets/{railroadDiagram-O6MQD6OU-BlLdRdXp.js → railroadDiagram-O6MQD6OU-8HOyX0u-.js} +1 -1
- package/web-shell/assets/{requirementDiagram-EFPCY7ZU-BkDLBR5w.js → requirementDiagram-EFPCY7ZU-9W4_14i8.js} +1 -1
- package/web-shell/assets/{sankeyDiagram-P5KCCOFB-jAIqRp65.js → sankeyDiagram-P5KCCOFB-DSUBB2XP.js} +1 -1
- package/web-shell/assets/{sequenceDiagram-WJ2MYXX4-f-soZYPr.js → sequenceDiagram-WJ2MYXX4-DD3jH6Jn.js} +1 -1
- package/web-shell/assets/{sizeCapture-X5ZJPWSS-BzOuAfB2.js → sizeCapture-X5ZJPWSS-RAFTU3Cz.js} +1 -1
- package/web-shell/assets/{stateDiagram-HBIQ2CUA-BPLSs12r.js → stateDiagram-HBIQ2CUA-Drk-oZ2x.js} +1 -1
- package/web-shell/assets/stateDiagram-v2-4QOOHH4V-QzYteVIm.js +1 -0
- package/web-shell/assets/{swimlanes-XN3QIQJK-D-9E_RIR.js → swimlanes-XN3QIQJK-Cy2nlOGx.js} +1 -1
- package/web-shell/assets/swimlanesDiagram-VK2B7HYN-xTr-HG26.js +8 -0
- package/web-shell/assets/{timeline-definition-24CTP7MA-CT56K-gV.js → timeline-definition-24CTP7MA-B7outYof.js} +1 -1
- package/web-shell/assets/{vennDiagram-4TSXK5OY-B-vi4IyO.js → vennDiagram-4TSXK5OY-Di_u1Ic6.js} +1 -1
- package/web-shell/assets/{wardleyDiagram-VM6X3IG4-C9O7Ju98.js → wardleyDiagram-VM6X3IG4-DYocuCAM.js} +1 -1
- package/web-shell/assets/{xychartDiagram-S5SC5T6Z-6d8w3jg2.js → xychartDiagram-S5SC5T6Z-AADDse54.js} +1 -1
- package/web-shell/index.html +29 -5
- package/chunks/chunk-V7RNNPGC.js +0 -44
- package/chunks/list-JOGBAC2R.js +0 -122
- package/chunks/mcp-6YYNSYLK.js +0 -116
- package/chunks/workflow-HD5NYMW5.js +0 -2907
- package/chunks/workspace-providers-status-MAM42IZS.js +0 -120
- package/web-shell/assets/channel-COIuCrVH.js +0 -1
- package/web-shell/assets/classDiagram-DTDB5LWJ-DoX6OYqu.js +0 -1
- package/web-shell/assets/classDiagram-v2-JRS7N3AN-DoX6OYqu.js +0 -1
- package/web-shell/assets/index-CI1ysIEv.js +0 -2154
- package/web-shell/assets/index-CpxXGH-8.css +0 -36
- package/web-shell/assets/stateDiagram-v2-4QOOHH4V-IRul-LaT.js +0 -1
- package/web-shell/assets/swimlanesDiagram-VK2B7HYN-D6lgKepA.js +0 -8
- package/chunks/{chunk-JA5CBKRP.js → chunk-7NXSVSFB.js} +0 -0
- package/chunks/{open-with-auth-6MVIHMXB.js → open-with-auth-XFCCJOO6.js} +3 -3
|
@@ -63,7 +63,6 @@ Channels are configured under the `channels` key in `settings.json`. Each channe
|
|
|
63
63
|
| `allowedUsers` | No | List of user IDs allowed to use the bot (used by `allowlist` and `pairing` policies) |
|
|
64
64
|
| `sessionScope` | No | How sessions are scoped: `user` (default), `chat_thread`, or `single`. Legacy `thread` remains compatible when already configured but is not offered for new Web Shell configurations |
|
|
65
65
|
| `multiSession` | No | Retain up to eight owner-scoped named tasks in one chat. Requires daemon-managed mode, `sessionScope: "user"`, no webhooks or group-history backfill, and no enabled Channel loops |
|
|
66
|
-
| `messagePrefix` | No | Only dispatch user messages that begin with this exact, case-sensitive prefix after any leading `@mentions`; the prefix and following whitespace are removed before dispatch |
|
|
67
66
|
| `cwd` | No | Working directory for the agent. Defaults to the current directory |
|
|
68
67
|
| `approvalMode` | No | Tool approval mode for channel sessions. Unattended webhook tasks require `yolo`; the setting applies to every session on the channel |
|
|
69
68
|
| `instructions` | No | Custom instructions prepended to the first message of each session |
|
|
@@ -74,10 +73,6 @@ Channels are configured under the `channels` key in `settings.json`. Each channe
|
|
|
74
73
|
| `groups` | No | Per-group settings. Keys are group chat IDs or `"*"` for defaults. See [Group Chats](#group-chats) |
|
|
75
74
|
| `dispatchMode` | No | What happens when you send a message while the bot is busy: `steer` (default), `collect`, or `followup`. See [Dispatch Modes](#dispatch-modes) |
|
|
76
75
|
|
|
77
|
-
When `messagePrefix` is set, every user-authored message must begin with the prefix and a non-empty payload, for example `/review inspect #123`. Only the prefix and the mentions ahead of it are removed; a mention the user typed after the prefix reaches the agent unchanged. Shared and agent commands use the same rule (`/review /help`, `/review /clear`, and so on). Telegram's registered command-menu actions remain available without the prefix — unless the configured prefix is itself one of them, in which case the prefix wins and that command has to be sent prefixed too (`/new /new`). Attachments need a matching caption when the platform supports one; captionless Telegram, Feishu, WeChat, DingTalk and WeCom media messages continue to run, and their placeholder text is never quoted back as group history. Native todos, webhooks, and provider-generated assignment or review-request events also continue to run without a prefix because they are system events rather than chat messages.
|
|
78
|
-
|
|
79
|
-
Two behaviours are deliberate and worth knowing before you turn the prefix on. A voice message whose transcript DingTalk or WeCom fills in counts as text the user spoke, so it must carry the prefix like any other message and is dropped otherwise — only an untranscribed voice note runs as captionless media. And the prefix is checked before pairing, so first contact from an unknown sender or an unapproved group has to carry the prefix as well; without that ordering every unprefixed message in a busy group would draw a pairing reply, which is exactly the noise the prefix exists to suppress. Tell new users the prefix out of band, or leave pairing channels unprefixed.
|
|
80
|
-
|
|
81
76
|
### Sender Policy
|
|
82
77
|
|
|
83
78
|
Controls who can interact with the bot:
|
|
@@ -524,7 +519,11 @@ qwen channel status --daemon-url http://127.0.0.1:4170 --token secret
|
|
|
524
519
|
qwen channel stop --daemon-url http://127.0.0.1:4170 --token secret
|
|
525
520
|
```
|
|
526
521
|
|
|
527
|
-
This mode starts workspace-grouped channel worker processes owned by `qwen serve`. Workers connect back to the daemon through the SDK and use the same channel adapters. They are separate from the daemon process, so a channel adapter crash does not crash the daemon.
|
|
522
|
+
This mode starts workspace-grouped channel worker processes owned by `qwen serve`. Workers connect back to the daemon through the SDK and use the same channel adapters. They are separate from the daemon process, so a channel adapter crash does not crash the daemon. An explicit `--channel` selection takes precedence and fails daemon startup if it cannot become ready. On a flagless boot, the trusted primary workspace's `serve.channels` setting is restored. Secondary workspaces do not independently restore their own `serve.channels`. Without either source, the daemon does not load channel adapters or reserve the lease until the first `qwen channel set`.
|
|
523
|
+
|
|
524
|
+
Automatic restore skips invalid startup settings and validation or lease failures that occur before workers start, while preserving unrelated settings. After a worker startup fails, the daemon continues only once cleanup succeeds. A global runtime startup timeout or an unconfirmed worker stop still follows the normal startup-failure path; the service lease remains held while worker termination is unconfirmed. Check the daemon log for messages identifying `serve.channels` when a channel does not restore.
|
|
525
|
+
|
|
526
|
+
Stored startup names must be non-empty, have no leading or trailing whitespace, and contain no unsafe control or invisible characters. Invalid entries are skipped individually and logged by their array index. Startup does not rename instances or rewrite the configuration. The channel startup toggle reflects the saved setting; runtime state shows whether the channel is running.
|
|
528
527
|
|
|
529
528
|
`qwen serve --channel` is not the same service as `qwen channel start`. Standalone `qwen channel start` still uses the ACP-backed channel service and can run channel configs with different `cwd` values. Daemon-managed channels require every selected channel's `cwd` to resolve to a workspace registered by the daemon. In multi-workspace mode, a selection replacement keeps workers for workspaces whose ordered channel list did not change; `all` remains primary-workspace-only.
|
|
530
529
|
|
|
@@ -36,7 +36,7 @@ These commands help you save, restore, and summarize work progress.
|
|
|
36
36
|
|
|
37
37
|
> [!note]
|
|
38
38
|
>
|
|
39
|
-
> Opening an HTML export loads the renderer for that exact Qwen Code version from `unpkg.com`. If the version has not been published or
|
|
39
|
+
> Opening an HTML export loads the renderer and stylesheet for that exact Qwen Code version from `unpkg.com`. If the version has not been published or either asset cannot be reached, the file shows a load error. Markdown, JSON, and JSONL exports remain self-contained.
|
|
40
40
|
|
|
41
41
|
> [!note]
|
|
42
42
|
>
|
|
@@ -757,12 +757,11 @@ qwen sessions list --json | jq .
|
|
|
757
757
|
|
|
758
758
|
#### `qwen sessions ps`
|
|
759
759
|
|
|
760
|
-
Lists the
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
Records left behind by a killed session are swept as they are found.
|
|
764
|
-
|
|
765
|
-
registry, so they are not shown.
|
|
760
|
+
Lists the Qwen Code sessions registered on this machine right now.
|
|
761
|
+
`sessions list` walks saved transcripts ("what have I worked on"); this
|
|
762
|
+
walks the live-process registry ("what is running at this moment").
|
|
763
|
+
Records left behind by a killed session are swept as they are found. A
|
|
764
|
+
one-shot `qwen -p` run never registers, so it is never shown.
|
|
766
765
|
|
|
767
766
|
**Flags:**
|
|
768
767
|
|
|
@@ -772,7 +771,19 @@ registry, so they are not shown.
|
|
|
772
771
|
|
|
773
772
|
**Human-readable output (default):**
|
|
774
773
|
|
|
775
|
-
A table with columns: NAME, PID, AGE, DIRECTORY.
|
|
774
|
+
A table with columns: NAME, KIND, PID, AGE, DIRECTORY.
|
|
775
|
+
|
|
776
|
+
KIND says what registered the session — `tui` for someone at a terminal,
|
|
777
|
+
`external` for a program that is not a Qwen Code session at all (a voice
|
|
778
|
+
front-end, a relay), and `headless` or `serve` for a session another
|
|
779
|
+
program drives. Several `serve` or `headless` rows can share one PID: a
|
|
780
|
+
`qwen --acp` child hosts all its sessions in one process — `serve` when
|
|
781
|
+
the daemon spawned it, `headless` when a client is driving it directly —
|
|
782
|
+
and each of them registers separately. It is a self-report, like NAME and DIRECTORY: every field
|
|
783
|
+
here was written by the process it describes, and nothing about what a
|
|
784
|
+
session is allowed to do depends on it. See
|
|
785
|
+
[Cross-Session Protocol](./cross-session-protocol.md) for the record
|
|
786
|
+
format and for how to register a program of your own.
|
|
776
787
|
|
|
777
788
|
**JSON output (`--json`):**
|
|
778
789
|
|
|
@@ -781,7 +792,7 @@ object with fields:
|
|
|
781
792
|
|
|
782
793
|
```
|
|
783
794
|
schemaVersion, pid, procStart, pidNs, sessionId, cwd, name, startedAt,
|
|
784
|
-
qwenVersion, ipcPath (when peer messaging is available)
|
|
795
|
+
qwenVersion, kind, ipcPath (when peer messaging is available)
|
|
785
796
|
```
|
|
786
797
|
|
|
787
798
|
Nothing else is written to stdout — an empty listing prints nothing at
|
|
@@ -1018,3 +1029,45 @@ on your behalf.
|
|
|
1018
1029
|
Anyone who holds the token can send as that controller, so treat it like
|
|
1019
1030
|
any other credential: give it to one program, keep it out of shared
|
|
1020
1031
|
config, and revoke it when that program is done.
|
|
1032
|
+
|
|
1033
|
+
### Sessions a program drives over ACP
|
|
1034
|
+
|
|
1035
|
+
Any `qwen --acp` child registers each session it hosts — as `serve` when
|
|
1036
|
+
the daemon spawned the process, as `headless` when an editor or another
|
|
1037
|
+
client is driving `qwen --acp` directly — and the session appears in
|
|
1038
|
+
`qwen sessions ps` and in another session's `list_agents` like any
|
|
1039
|
+
other. It can send: its model can call `send_message` to reach a terminal
|
|
1040
|
+
you have open. Several of them share one process and one inbox, so a
|
|
1041
|
+
sender has to name the session it means — every Qwen Code session does
|
|
1042
|
+
that automatically.
|
|
1043
|
+
|
|
1044
|
+
Messages sent _to_ one are refused rather than held. Holding is a
|
|
1045
|
+
question put to a person, and nobody is watching a held-message list on a
|
|
1046
|
+
driven session's behalf; a sender is told at once instead of
|
|
1047
|
+
waiting out an expiry. Where a held message should surface for those
|
|
1048
|
+
sessions is not settled yet.
|
|
1049
|
+
|
|
1050
|
+
A session registers only while its own settings have
|
|
1051
|
+
`agents.crossSessionMessaging` on. With it off it stays invisible,
|
|
1052
|
+
because the only reason to list a session nobody can message would be to
|
|
1053
|
+
advertise an address that never answers.
|
|
1054
|
+
|
|
1055
|
+
### Programs that are not Qwen Code sessions
|
|
1056
|
+
|
|
1057
|
+
Everything above works between sessions, but nothing in it is specific to
|
|
1058
|
+
one. A program that writes a registry record for itself and binds an
|
|
1059
|
+
inbox the same way is listed by `qwen sessions ps` and by `list_agents`,
|
|
1060
|
+
can be addressed by name from `send_message`, and receives delivery
|
|
1061
|
+
receipts for what it sends — a voice front-end, a relay, a build watcher.
|
|
1062
|
+
It should record `kind: "external"` so a listing can say what it is.
|
|
1063
|
+
|
|
1064
|
+
[Cross-Session Protocol](./cross-session-protocol.md) is the contract for
|
|
1065
|
+
writing one: the record schema and how liveness is judged, the socket
|
|
1066
|
+
paths and framing, the auth line, every frame field, the receipt states
|
|
1067
|
+
and their transitions, and what a receiver does with a message before its
|
|
1068
|
+
model sees it.
|
|
1069
|
+
|
|
1070
|
+
A Node program does not have to write any of that by hand:
|
|
1071
|
+
`@qwen-code/sdk/peer` implements the contract. `PeerEndpoint.start({ name })`
|
|
1072
|
+
publishes the record and binds the inbox, `list()` and `send()` address
|
|
1073
|
+
sessions by name, and `onMessage` receives what they send.
|
|
@@ -26,7 +26,7 @@ When first used, the skill runs these commands itself:
|
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
28
|
qwen mcp add --scope user node-repl npx -y @qwen-code/node-repl-mcp@0.1.3
|
|
29
|
-
npm install --no-save --package-lock=false @qwen-code/cua-sdk@0.20.
|
|
29
|
+
npm install --no-save --package-lock=false @qwen-code/cua-sdk@0.20.5
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
Restart Qwen Code after the MCP server is first added. The skill then resumes
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
# Cross-Session Protocol
|
|
2
|
+
|
|
3
|
+
This page is the contract for a program that wants to take part in
|
|
4
|
+
cross-session messaging without being a Qwen Code session: a voice
|
|
5
|
+
front-end, a relay daemon, a script that watches a build. It describes
|
|
6
|
+
what a session writes to the registry, what its inbox reads off a
|
|
7
|
+
connection, and what it sends back. Everything here is what the code
|
|
8
|
+
does today at schema version 1 and frame version 1; the last section
|
|
9
|
+
says what may change and how you will know.
|
|
10
|
+
|
|
11
|
+
For a Node program, `@qwen-code/sdk/peer` implements the joining side of
|
|
12
|
+
this page — the record, the inbox, the auth line, frames and receipts — with
|
|
13
|
+
nothing but Node, and its tests run it against Qwen Code's own implementation
|
|
14
|
+
in both directions. It applies none of §6 to its own inbox: a program that
|
|
15
|
+
needs rate limits, holds or a duplicate window applies them itself. Use it, or
|
|
16
|
+
read on to write your own.
|
|
17
|
+
|
|
18
|
+
Every value that crosses a process boundary is untrusted on arrival and
|
|
19
|
+
validated by the reader. Where this page says a field "must" have some
|
|
20
|
+
shape, a value that does not is dropped, never rejected with an error.
|
|
21
|
+
|
|
22
|
+
## 1. The session registry
|
|
23
|
+
|
|
24
|
+
A running session publishes one record:
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
$QWEN_HOME/sessions/<pid>.json (directory 0700, file 0600)
|
|
28
|
+
$QWEN_HOME/sessions/<pid>-<8 hex>.json (a process hosting several sessions)
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
`$QWEN_HOME` defaults to `~/.qwen`. The file name is keyed by the
|
|
32
|
+
writer's PID — either the bare PID, or the PID, a dash, and eight
|
|
33
|
+
lowercase hex characters minted at registration (see "Several records
|
|
34
|
+
from one process" below). A record whose `pid` field disagrees with the
|
|
35
|
+
PID prefix of its file name — compared in canonical decimal form, so a
|
|
36
|
+
zero-padded name agrees with nothing — is ignored.
|
|
37
|
+
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"schemaVersion": 1,
|
|
41
|
+
"pid": 41337,
|
|
42
|
+
"procStart": "a1b2c3d4-…-boot-uuid:8895124",
|
|
43
|
+
"pidNs": 4026531836,
|
|
44
|
+
"sessionId": "8e016be8-5b48-4c13-ad22-1f5326ae64ac",
|
|
45
|
+
"cwd": "/home/me/project",
|
|
46
|
+
"name": "project-3f",
|
|
47
|
+
"startedAt": 1788959000000,
|
|
48
|
+
"qwenVersion": "0.23.0",
|
|
49
|
+
"kind": "tui",
|
|
50
|
+
"ipcPath": "/run/user/1000/qwen-socks/41337.sock",
|
|
51
|
+
"ipcToken": "c0ffee…64 hex…"
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
| Field | Meaning |
|
|
56
|
+
| --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
57
|
+
| `schemaVersion` | Always `1`. A reader skips a record with a higher version and never deletes it. |
|
|
58
|
+
| `pid` | The writer's process id. Must equal the PID the file name is keyed by: the whole name for the bare form, the digits before the `-<8 hex>` suffix for the minted one. |
|
|
59
|
+
| `procStart` | `<boot id>:<process start ticks>` on Linux (`/proc/sys/kernel/random/boot_id` and field 22 of `/proc/<pid>/stat`); `null` elsewhere. Guards against PID reuse, and against records written on another machine that shares this home directory. |
|
|
60
|
+
| `pidNs` | Inode number of `/proc/self/ns/pid` on Linux; `null` elsewhere. A reader only lists and sweeps records from its own namespace. |
|
|
61
|
+
| `sessionId` | The session's id. `/clear` and `/resume` swap it under the same PID, so re-read the record before each send. |
|
|
62
|
+
| `cwd` | Working directory at registration. |
|
|
63
|
+
| `name` | Display name. Derived from the cwd basename (Unicode letters, marks, digits, `.`, `_`, `-`; up to 32 code points) plus `-` and the first two hex characters of `sha256(sessionId)`, unless the writer chose one. Not unique. |
|
|
64
|
+
| `startedAt` | Epoch milliseconds. Newest first is the listing order and the tie-break between twins. |
|
|
65
|
+
| `qwenVersion` | Free text or `null`. |
|
|
66
|
+
| `kind` | What registered: `tui` (someone at a terminal), `headless`, `serve`, `external`. Lowercase ASCII, digits and dashes, at most 16 characters; anything else is dropped on read. Absent means a writer older than the field, which reads as `tui`. A label for listings — never a credential; see below. |
|
|
67
|
+
| `ipcPath` | The inbox socket, present only while it is bound. Absent means discoverable but not messageable. |
|
|
68
|
+
| `ipcToken` | 64 hex characters. What a connection to `ipcPath` presents on its auth line. Absent means the inbox requires none (records from older builds). |
|
|
69
|
+
|
|
70
|
+
**A record is a self-report.** Every field in it was written by the
|
|
71
|
+
process it describes, so `name`, `cwd` and `kind` are claims, not facts a
|
|
72
|
+
reader can lean on. Nothing that decides what a sender may do reads
|
|
73
|
+
them — that is settled by what a connection presents (§3) and by the
|
|
74
|
+
receiving session's own policy (§6). Set `kind` so a listing can group
|
|
75
|
+
sessions honestly; do not expect it to buy you anything.
|
|
76
|
+
|
|
77
|
+
**Writing your own record.** An external process that wants to be
|
|
78
|
+
found — listed by `qwen sessions ps`, addressable from `send_message`,
|
|
79
|
+
able to receive receipts — writes the same record for itself: its own
|
|
80
|
+
`pid`, `procStart` and `pidNs` computed the same way, a `sessionId` it
|
|
81
|
+
mints (any UUID), `kind: "external"`, a `name` (yours, or derived the
|
|
82
|
+
same way; it is flattened to one line and bounded when displayed), and
|
|
83
|
+
`ipcPath` + `ipcToken` for an inbox it binds itself (§2). On Linux,
|
|
84
|
+
`pidNs` is required: every reader compares it with its own, so a record
|
|
85
|
+
without one is never listed — and never swept. `procStart` is required too,
|
|
86
|
+
for a different reason: without it a reader falls back to plain PID liveness
|
|
87
|
+
and cannot tell a recycled PID from the process that wrote the record. Write
|
|
88
|
+
to a temp file in the same directory and `rename` over the target; create
|
|
89
|
+
the file 0600; refuse to write through a symlink. If `<pid>.json` already
|
|
90
|
+
holds something you cannot prove was left by an earlier process with your
|
|
91
|
+
PID — same `pidNs`, same boot id, different start ticks — write
|
|
92
|
+
`<pid>-<8 hex>.json` instead of replacing it: readers accept both names,
|
|
93
|
+
and the record there may belong to a live process in another namespace or
|
|
94
|
+
on another machine. Remove the record on exit. A record whose process is
|
|
95
|
+
gone is swept by the next session that lists, but only when `procStart`
|
|
96
|
+
proves the PID is not merely reused. `PeerEndpoint.start()` in
|
|
97
|
+
`@qwen-code/sdk/peer` does all of this, and removes the record again on
|
|
98
|
+
`close()`.
|
|
99
|
+
|
|
100
|
+
**Reading.** Anything that can read the directory can read every record,
|
|
101
|
+
including tokens: being able to discover a session and being able to
|
|
102
|
+
authenticate to it are one capability by design. Do not print
|
|
103
|
+
`ipcToken` anywhere a model or a log can see it.
|
|
104
|
+
|
|
105
|
+
**Liveness.** A record is live when all of these hold: the file name is
|
|
106
|
+
`<pid>.json` or `<pid>-<8 hex>.json` and its PID prefix equals `pid`;
|
|
107
|
+
`pidNs` equals the reader's; the boot id inside
|
|
108
|
+
`procStart` equals the reader's (or `procStart` is `null`); and the PID
|
|
109
|
+
is alive with the same start ticks. A live record with an `ipcPath`
|
|
110
|
+
still has to be dialed before it is advertised as reachable — a socket
|
|
111
|
+
file outlives a crash.
|
|
112
|
+
|
|
113
|
+
**Refs.** Displayed handles use `ref = sha256(sessionId)[0:6]`. Two
|
|
114
|
+
sessions may share a `name`; the address grammar a sender types is
|
|
115
|
+
`name`, `name [ref]`, `[ref]` or the bare `ref`, and an ambiguous
|
|
116
|
+
`name` is an error rather than a guess.
|
|
117
|
+
|
|
118
|
+
**Several records from one process.** Any `qwen --acp` child — spawned
|
|
119
|
+
by the daemon, or driven directly by an editor or another client —
|
|
120
|
+
writes one record per session, named `<pid>-<8 hex>.json`, from its
|
|
121
|
+
first session on. The suffix is minted at
|
|
122
|
+
registration and never changes; a session id swapped underneath is a
|
|
123
|
+
patch to the record, not a rename of it. Every one of them carries the
|
|
124
|
+
same `ipcPath`, because the process binds one inbox for all its sessions
|
|
125
|
+
and tells them apart by the `toSessionId` on each frame — so **always
|
|
126
|
+
send `toSessionId`**: a frame without one that reaches such a process is
|
|
127
|
+
answered `misaddressed`, since there is no single session it could have
|
|
128
|
+
meant. Liveness, sweeping and the namespace and boot guards read the
|
|
129
|
+
record exactly as they do for the bare name; only the PID/filename
|
|
130
|
+
agreement check differs, and only in comparing `pid` against the digits
|
|
131
|
+
before the suffix rather than the whole name.
|
|
132
|
+
|
|
133
|
+
## 2. The inbox socket
|
|
134
|
+
|
|
135
|
+
One UNIX domain socket per session, at the first of these that binds:
|
|
136
|
+
|
|
137
|
+
1. `$XDG_RUNTIME_DIR/qwen-socks/<pid>.sock`
|
|
138
|
+
2. `$TMPDIR/qwen-socks-<16 hex>/<pid>.sock`
|
|
139
|
+
3. `/tmp/qwen-socks-<16 hex>/<pid>.sock`
|
|
140
|
+
|
|
141
|
+
The directory is 0700 and the socket 0600. A path longer than 103 bytes
|
|
142
|
+
is skipped. When the PID-keyed name is already held by a live listener
|
|
143
|
+
(two PID namespaces sharing a runtime directory), the session binds
|
|
144
|
+
`<pid>-<8 hex>.sock` next to it instead. Peers never derive a socket
|
|
145
|
+
path; they read `ipcPath` from the record.
|
|
146
|
+
|
|
147
|
+
A connection carries newline-delimited JSON, one object per line, UTF-8.
|
|
148
|
+
A single line longer than 1 MiB (measured in UTF-16 code units) drops
|
|
149
|
+
the connection. A connection that goes 30 seconds without completing a
|
|
150
|
+
line that parses is dropped; junk lines do not extend the deadline. The
|
|
151
|
+
listener accepts at most 64 connections at once.
|
|
152
|
+
|
|
153
|
+
The expected exchange is one message per connection: connect, write the
|
|
154
|
+
auth line and the frame in one write, half-close, wait for the peer to
|
|
155
|
+
close. The receiver never writes on the same connection; anything it
|
|
156
|
+
has to say comes back as a separate connection to your own `ipcPath`.
|
|
157
|
+
|
|
158
|
+
## 3. The auth line
|
|
159
|
+
|
|
160
|
+
When the target record has an `ipcToken`, the first line must be:
|
|
161
|
+
|
|
162
|
+
```json
|
|
163
|
+
{ "msgV": 1, "type": "auth", "token": "<token>" }
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Three kinds of token are accepted, and the inbox remembers which one it
|
|
167
|
+
saw:
|
|
168
|
+
|
|
169
|
+
| Presented | The inbox concludes | Effect |
|
|
170
|
+
| ----------------------------------------------------------------------------- | ------------------------------ | -------------------------------------------------------------------------------- |
|
|
171
|
+
| The `ipcToken` from the target's registry record | an ordinary peer | subject to policy and mode parity (§6) |
|
|
172
|
+
| `QWEN_CODE_MESSAGING_TOKEN` from the target's own environment | a process that session started | delivered under the parity default; `origin="own-process"` |
|
|
173
|
+
| A controller token `qpc_<64 hex>` minted with `qwen sessions controllers add` | a program the user trusts | delivered under the parity default; `origin="controller"` with the grant's label |
|
|
174
|
+
|
|
175
|
+
A first line that is not an auth line, or that presents a token matching
|
|
176
|
+
none of the three, drops the connection silently. When the record has no
|
|
177
|
+
`ipcToken`, do not send an auth line; an older inbox reads it as an
|
|
178
|
+
unknown frame type and skips it, so leading with one is always safe.
|
|
179
|
+
|
|
180
|
+
Nothing here authenticates the _sender_: a token proves the connection is
|
|
181
|
+
allowed, not who opened it. `from`, `fromName`, `fromMode` and every
|
|
182
|
+
field of the record are claims.
|
|
183
|
+
|
|
184
|
+
This is also the whole of the trust model. A program the user wants
|
|
185
|
+
driving their sessions gets a controller token, minted by hand and given
|
|
186
|
+
to that one program; it is what makes the difference between a message
|
|
187
|
+
that is delivered and one that waits for review. Writing
|
|
188
|
+
`kind: "external"` or a familiar-looking `name` buys nothing.
|
|
189
|
+
|
|
190
|
+
## 4. The user frame
|
|
191
|
+
|
|
192
|
+
```json
|
|
193
|
+
{
|
|
194
|
+
"msgV": 1,
|
|
195
|
+
"msgId": "5f1d0c9e-3b2a-4e8f-9c7d-1a2b3c4d5e6f",
|
|
196
|
+
"type": "user",
|
|
197
|
+
"from": "/run/user/1000/qwen-socks/40011.sock",
|
|
198
|
+
"replyToken": "<my own ipcToken>",
|
|
199
|
+
"fromName": "project-3f",
|
|
200
|
+
"fromMode": "prompting",
|
|
201
|
+
"toSessionId": "8e016be8-…",
|
|
202
|
+
"priority": "next",
|
|
203
|
+
"message": { "role": "user", "content": "build finished, 0 failures" }
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
| Field | Rule |
|
|
208
|
+
| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
209
|
+
| `msgV` | Number. Must be ≤ 1; higher is dropped. |
|
|
210
|
+
| `msgId` | `^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$`, and must not canonicalize (dashes stripped, lower-cased) to `all`. Use a fresh UUID per message: the receiver remembers ids it has settled and repeats the old verdict for a re-sent one. |
|
|
211
|
+
| `type` | `"user"`. |
|
|
212
|
+
| `from` | Your `ipcPath`, if you have one. Where receipts go. Absent means no receipts. |
|
|
213
|
+
| `replyToken` | Your `ipcToken`, so the receiver can authenticate its receipts to you. |
|
|
214
|
+
| `fromName` | Display name; flattened to one line, at most 200 characters. |
|
|
215
|
+
| `fromMode` | `"prompting"` (a person reviews each action) or `"bypass"` (some actions apply without review). Absent means "asserts nothing", which is held for review (§6). |
|
|
216
|
+
| `toSessionId` | The `sessionId` you read from the record. A receiver holding a different id answers `misaddressed`. Always send it. |
|
|
217
|
+
| `priority` | `"now"` or `"next"`; anything else reads as `"next"`. Carried for a future interrupt path; today the receiver queues both for the next turn. |
|
|
218
|
+
| `message` | `role` must be `"user"`; `content` a non-empty string. |
|
|
219
|
+
|
|
220
|
+
Unknown fields are ignored.
|
|
221
|
+
|
|
222
|
+
## 5. The delivery-status frame
|
|
223
|
+
|
|
224
|
+
The receiver reports what became of a message with one control frame per
|
|
225
|
+
outcome, sent to the message's `from` and authenticated with its
|
|
226
|
+
`replyToken`:
|
|
227
|
+
|
|
228
|
+
```json
|
|
229
|
+
{
|
|
230
|
+
"msgV": 1,
|
|
231
|
+
"msgId": "<fresh id>",
|
|
232
|
+
"type": "control",
|
|
233
|
+
"action": "delivery_status",
|
|
234
|
+
"status": "held",
|
|
235
|
+
"origMsgId": "5f1d0c9e-…",
|
|
236
|
+
"from": "/run/user/1000/qwen-socks/41337.sock",
|
|
237
|
+
"reason": "Your message is held for the recipient user to review …"
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
| `status` | When | What to do |
|
|
242
|
+
| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
|
|
243
|
+
| `held` | Parked for the user to review. Repeated on a retry, and on a release that could not be queued. | Wait; a decision or an expiry follows. |
|
|
244
|
+
| `delivered` | Queued for the model. | Nothing. Not proof it was read. |
|
|
245
|
+
| `denied` | A person reviewed it and said no. | Do not re-send. |
|
|
246
|
+
| `refused` | The session's policy turns peer messages away; nobody saw it. Only ever the first receipt. | Stop; reach that user another way. |
|
|
247
|
+
| `expired` | A held message ran out its wait, the session exited with it unread, or it arrived while that session was shutting down. Can follow `held` or `delivered`. | Re-send later if it still matters. |
|
|
248
|
+
| `misaddressed` | `toSessionId` does not match the session at that address. | Re-read the registry. |
|
|
249
|
+
| `dropped` | The inbox turned it away before any policy ran (§6). | Treat as unsent. Do not retry in a loop; fold what matters into one later message. |
|
|
250
|
+
|
|
251
|
+
A `dropped` receipt carries two more fields. `dropReason` is
|
|
252
|
+
`rate-limited`, `duplicate` or `queue-full`. `droppedMsgIds` lists up to
|
|
253
|
+
256 further ids the same receipt settles: a burst is answered with one
|
|
254
|
+
receipt rather than one each, so a sender moves every message it lost to
|
|
255
|
+
a terminal state from a single frame. Both are meaningless on any other
|
|
256
|
+
status and are ignored there.
|
|
257
|
+
|
|
258
|
+
`reason` is free text for a human. Order of receipts is not guaranteed
|
|
259
|
+
across connections; apply them as state transitions:
|
|
260
|
+
|
|
261
|
+
```
|
|
262
|
+
pending → held | delivered | denied | refused | expired | misaddressed | dropped
|
|
263
|
+
held → delivered | denied | expired | misaddressed
|
|
264
|
+
delivered → expired | misaddressed
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
Anything else is a repeat and should be ignored. A receipt for an id you
|
|
268
|
+
never sent is noise; ignore it. Receipts are best-effort on the
|
|
269
|
+
receiver's side: a full outbound limit or a dead `from` loses them
|
|
270
|
+
silently, so a sender must tolerate never hearing back.
|
|
271
|
+
|
|
272
|
+
Your own inbox receives these frames from the sessions you messaged. If
|
|
273
|
+
you only ever send, bind an inbox and give `from` anyway: without one you
|
|
274
|
+
are blind to every outcome above.
|
|
275
|
+
|
|
276
|
+
## 6. What the receiver does with a message
|
|
277
|
+
|
|
278
|
+
In order:
|
|
279
|
+
|
|
280
|
+
1. **Admission.** Per sender: a burst of 30, then one message every two seconds. All senders together: a burst of 32, then one a second — a sender names itself on the frame, so rotating that name buys a fresh allowance from the first limit but not the second. The same body from another session inside 30 seconds is a `duplicate`; a process the session started and a trusted controller are exempt from that check, and rate-limited like everyone else. A dropped message is never held, never delivered, and leaves no record, so a sender that waits out its burst and retries still lands.
|
|
281
|
+
2. **Settled ids.** A `msgId` the gate already decided repeats its earlier verdict.
|
|
282
|
+
3. **Policy.** `agents.crossSessionInbound` set to `accept`, `hold` or `refuse` wins. Unset: a process the session started or a trusted controller is accepted; otherwise a message is accepted only when `fromMode` names the same review class the receiver is in, and held in every other case, including when `fromMode` is absent.
|
|
283
|
+
4. **Hold.** Up to 50 messages wait. A message arriving at a full buffer is `dropped` with `queue-full` rather than evicting one already parked. A held message expires after `agents.crossSessionHeldExpiry` (`1m`, `5m`, `10m`, `never`; default `5m`). The user releases or denies from `/peers`; a mode change re-evaluates the backlog.
|
|
284
|
+
5. **Queue.** An accepted message joins the session's input queue, which holds at most 50 from peers. A full queue is `dropped` with `queue-full` too.
|
|
285
|
+
|
|
286
|
+
A sender does not have to discover the limits the hard way: a Qwen Code
|
|
287
|
+
session mirrors them per address and refuses its own send before writing
|
|
288
|
+
it, telling its model to batch instead.
|
|
289
|
+
|
|
290
|
+
The model sees a delivered message as:
|
|
291
|
+
|
|
292
|
+
```
|
|
293
|
+
<cross_session_message from="/run/user/1000/qwen-socks/40011.sock" name="project-3f">
|
|
294
|
+
build finished, 0 failures
|
|
295
|
+
</cross_session_message>
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
followed by a notice stating the sender's authority. `origin="own-process"`
|
|
299
|
+
or `origin="controller" controller="<label>"` is added by the receiver
|
|
300
|
+
from what the connection presented, never from the frame; a controller's
|
|
301
|
+
label comes from the grant the user minted, not from `fromName`. Tags
|
|
302
|
+
that look like the envelope are defanged inside `content`.
|
|
303
|
+
|
|
304
|
+
## 7. Compatibility
|
|
305
|
+
|
|
306
|
+
- A reader ignores fields it does not know. Adding a field to a record or
|
|
307
|
+
a frame is not a breaking change.
|
|
308
|
+
- `schemaVersion` and `msgV` are bumped only for a change to the shape of
|
|
309
|
+
existing fields. A reader drops a frame or skips a record with a
|
|
310
|
+
version above what it knows, and never deletes such a record.
|
|
311
|
+
- New `status` values may appear; treat an unknown one as "no transition"
|
|
312
|
+
and keep waiting. The same goes for a `kind` you do not recognize:
|
|
313
|
+
show it, do not correct it.
|
|
314
|
+
- Constants that may change without notice: the burst and rate figures,
|
|
315
|
+
the hold ceiling and expiry choices, the 1 MiB line cap, the 30-second
|
|
316
|
+
line deadline, the 64-connection cap.
|
|
317
|
+
|
|
318
|
+
## 8. Not settled yet
|
|
319
|
+
|
|
320
|
+
- **Name yielding.** Two sessions in one directory can register the same
|
|
321
|
+
`name`; today they are told apart only by `ref`. A registration that
|
|
322
|
+
yields to a live name, and a control frame that tells peers a session
|
|
323
|
+
renamed itself, are both still to come.
|
|
324
|
+
- **Same-name reporting.** `qwen sessions ps` and `list_agents` do not
|
|
325
|
+
flag records that still collide.
|
|
326
|
+
- **Inbound messages to ACP-driven sessions.** A session a program
|
|
327
|
+
drives over ACP — daemon-spawned or not — registers and can send, but
|
|
328
|
+
answers `refused` to anything sent to it: a hold is a question put to
|
|
329
|
+
a person, and nobody is watching a hold list on its behalf. Where a
|
|
330
|
+
held message should surface for those sessions — its client, or the
|
|
331
|
+
daemon's own API — is still open.
|
|
332
|
+
- **Sessions behind one inbox are one sender to every peer.** A process
|
|
333
|
+
hosting several sessions sends with one `from` address, so a
|
|
334
|
+
receiver's per-sender budget and duplicate window (§6) are shared by
|
|
335
|
+
all of that process's sessions at once: a busy sibling can spend
|
|
336
|
+
another's allowance, and a body just sent to one cannot be repeated
|
|
337
|
+
to its sibling inside the window. Per-session accounting would have
|
|
338
|
+
to trust a frame-asserted field, which §3's trust model rules out.
|
|
@@ -18,9 +18,13 @@ Creating, editing, or resuming a Goal requires a trusted workspace (`/trust`). H
|
|
|
18
18
|
|
|
19
19
|
Once a Goal has billed a turn, the footer pill and every status card show what it has spent against the window it is allowed, as `1.2k/30.0m`. The figure counts the model calls the Goal makes in its own turns; subagents and the verifier's own checks are not included. The window is set by [`model.goalTokenBudget`](../configuration/settings.md); resuming a Goal that has spent its window grants another one on top of what it has already spent, so the figure reads `30.0m/60.0m` rather than starting over. A Goal with no budget shows only what it has spent. A Goal that has not billed a turn yet shows no figures at all.
|
|
20
20
|
|
|
21
|
+
Two more windows are available and off by default: [`model.goalMaxTurns`](../configuration/settings.md) caps how many turns a Goal may finish, including user-driven Goal turns, and [`model.goalMaxActiveMinutes`](../configuration/settings.md) caps wall time while it remains active in a running process, including waits and idle time between turns. Time while the Goal is paused, blocked or stopped does not count against the second one, nor does downtime across a restart; a process that is merely suspended is still charged. Whichever window runs out first, the Goal gets the same single wind-down turn to hand off and then stops until you resume it, and resuming authorizes another window on top of what has already been used. Only the window that ran out moves; the others stay where they were, and the `-1` opt-out likewise only takes a ceiling off a Goal that has already spent it. The time window is read between turns rather than enforced by a timer, so a Goal can run well past it before it stops: a turn already running is never interrupted, and a window that runs out while no turn is running is not noticed until the next turn ends. Active time is counted between recorded transitions, so time in a turn a restart interrupted is not charged. Changes to either setting take effect after restart. Both windows arm only on a Goal created after the change, so bounding a Goal already on the record means replacing it with `/goal set` -- a new Goal at revision 1, with its turn, token and active-time meters reset and its evidence window starting at the replacement, so evidence the old Goal recorded is no longer citable -- or clearing it and starting again. A resume or an edit never adds a ceiling that was not armed at creation.
|
|
22
|
+
|
|
21
23
|
Each turn the session takes on its own reports what the Goal has spent so far, how many turns are behind it, and — unless the Goal runs unbounded — the window it is allowed. Every such turn except the final wind-down hand-off also carries standing instructions to re-check the workspace rather than trust earlier turns' reports, to work toward the end state the objective asks for, to do something different when the previous turn changed nothing (from the second turn on, once there is a previous turn to judge), and to check every requirement against citable evidence before proposing that the Goal is done.
|
|
22
24
|
|
|
23
|
-
A long Goal periodically compresses the evidence it has recorded into checkpoint claims with a side model
|
|
25
|
+
A long Goal periodically compresses the evidence it has recorded into checkpoint claims with a side model check, so later turns and the verifier still have it to cite. The check is bounded by [`model.goalCheckpointTimeoutSeconds`](../configuration/settings.md), 180 seconds by default. A reply wrapped in a markdown fence is read without the fence. If its claims overrun the aggregate byte budget, include a claim over the per-claim character limit, number more than one checkpoint may hold, cite an id that was not in the request, or change the proof kind of a source they cite, it makes one corrective model call that names what was wrong, and both calls share that ceiling. A reply that is not a JSON object holding a non-empty `claims` array gets no corrective call, and neither does one with any malformed claim, even beside usable ones: an extra key at either level, an unrecognised `proofKind`, an empty claim, or a `sourceRefs` list that is empty, holds a non-string or empty id, repeats an id, or holds more than 32 ids. A check that does not finish in time is abandoned as inconclusive; it counts toward the checkpoint stall limit only when the evidence window has overflowed, while a non-overflowing check preserves the streak and retries on a later turn. The calls are streamed, so the per-request transport timeout bounds only connect and first response, and the ceiling itself stops at the stream guards' 15-minute lifetime cap because past that the guard, not the setting, ends the check. That 15-minute limit on the setting is fixed, and raising the stream guard's own cap does not lift it.
|
|
26
|
+
|
|
27
|
+
A failing checkpoint shows up before it stops the Goal. While an active Goal's stall streak runs, the footer pill switches to `checkpoint N/3 stalled` on its own; once the Goal pauses or stops, the pill shows that status instead. The web shell's Goal status strip shows the count whatever the status. Whenever a terminal Goal status card is rendered, for example by `/goal` or by a pause, resume or verifier card, it shows how many consecutive checks have stalled out of the three the Goal allows, together with the last failure while one is recorded; the web shell's Goals dialog and headless `/goal` text output show the same line, while the web shell's transcript cards for Goal events show only the stop reason, and the model sees both fields when it reads the Goal. A check that fails while the window still has room is shown too, without spending a stall, but only while the Goal is active, or when that failure is itself what stopped the Goal, as with a checkpoint request too large to send. A checkpoint stop for any other reason clears the failure and keeps the streak, and a completed Goal shows no checkpoint line. The failure is kept as a single line with control characters removed. A Goal stopped by three stalled checkpoints names what the last one ran into. A check that could not fit the window within the checkpoint claim bounds, whether a full claim list that still left evidence behind or claims over the claim count or size budget, means the objective produces more evidence than one window holds, so narrow it. An answer that could not be folded into claims means the checkpoint model is not returning the structured output it is asked for, and narrowing the objective does not fix that. A check that never answered can mean an unreachable or rate-limited provider, a check that did not finish within `model.goalCheckpointTimeoutSeconds`, or an error in the check itself; the recorded failure says which. Resuming after any of the three starts a fresh evidence window.
|
|
24
28
|
|
|
25
29
|
## Interrupting a Goal
|
|
26
30
|
|
|
@@ -45,25 +49,25 @@ So the objective has to make the agent produce evidence: run the named check and
|
|
|
45
49
|
|
|
46
50
|
Put these into the objective, in this order:
|
|
47
51
|
|
|
48
|
-
| Part | What to write
|
|
49
|
-
| ------------ |
|
|
50
|
-
| `Outcome:` | One sentence: what is true when this is done.
|
|
51
|
-
| `Done when:` | Numbered, binary checks. At least one names a command and its expected exit code or output line, and asks for that line to be pasted.
|
|
52
|
-
| `Must not:` | Files not to touch, tests or thresholds not to weaken, irreversible actions (push, delete, publish) not to take.
|
|
53
|
-
| `Budget:` |
|
|
54
|
-
| `On block:` | What to report when stuck, and which decision a human must make.
|
|
55
|
-
| `Context:` | Only facts the agent cannot find in the workspace: branch, environment, earlier decisions.
|
|
52
|
+
| Part | What to write |
|
|
53
|
+
| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
54
|
+
| `Outcome:` | One sentence: what is true when this is done. |
|
|
55
|
+
| `Done when:` | Numbered, binary checks. At least one names a command and its expected exit code or output line, and asks for that line to be pasted. |
|
|
56
|
+
| `Must not:` | Files not to touch, tests or thresholds not to weaken, irreversible actions (push, delete, publish) not to take. |
|
|
57
|
+
| `Budget:` | Advisory model instruction for when to give up, such as "stop as blocked after 20 turns". To enforce one, set `model.goalMaxTurns` or `model.goalMaxActiveMinutes` in settings, not here. |
|
|
58
|
+
| `On block:` | What to report when stuck, and which decision a human must make. |
|
|
59
|
+
| `Context:` | Only facts the agent cannot find in the workspace: branch, environment, earlier decisions. |
|
|
56
60
|
|
|
57
61
|
Keep it to one objective. `/goal set` and `/goal edit` accept any length, but stay roughly under 1,200 characters: the objective is re-sent on every Goal turn. An objective the model proposes through `propose_goal` is capped at 1,500 characters. Both commands collapse newlines to spaces, so number the items rather than relying on line breaks.
|
|
58
62
|
|
|
59
|
-
`Budget` is an instruction to the model about when to stop and report a blocker.
|
|
63
|
+
`Budget` is an instruction to the model about when to stop and report a blocker; the model may or may not honour it. To make the runtime itself stop at a turn count or a duration, set [`model.goalMaxTurns`](../configuration/settings.md) or [`model.goalMaxActiveMinutes`](../configuration/settings.md). Writing either into the objective does not configure those, and does not change the Goal's token budget.
|
|
60
64
|
|
|
61
|
-
| Weak | Why it fails | Stronger
|
|
62
|
-
| -------------------------- | ----------------------------------------------------------- |
|
|
63
|
-
| make checkout faster | No threshold, no check. | `Outcome: checkout p95 is below 250 ms. Done when: 1) npm run bench:checkout exits 0 and prints p95 < 250 (paste the line); 2) npm test exits 0. Must not: change the benchmark or skip tests. Budget: stop as blocked after 20 turns.` |
|
|
64
|
-
| clean up the auth module | "Clean" has no evidence. | Ask what would be observable: zero lint warnings in `src/auth`, a coverage threshold, a file count.
|
|
65
|
-
| ship the release | Irreversible, and needs a human decision. | Narrow to a checkable pre-release state (tag exists, `npm run release:dry-run` exits 0) and put "do not publish" in `Must not`.
|
|
66
|
-
| after I confirm the design | The verifier cannot see a confirmation that never happened. | Move it to `On block:` as the decision a human must make.
|
|
65
|
+
| Weak | Why it fails | Stronger |
|
|
66
|
+
| -------------------------- | ----------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
67
|
+
| make checkout faster | No threshold, no check. | `Outcome: checkout p95 is below 250 ms. Done when: 1) npm run bench:checkout exits 0 and prints p95 < 250 (paste the line); 2) npm test exits 0. Must not: change the benchmark or skip tests. Budget: as model guidance, stop as blocked after 20 turns. On block: report the measured p95 and what blocks it.` |
|
|
68
|
+
| clean up the auth module | "Clean" has no evidence. | Ask what would be observable: zero lint warnings in `src/auth`, a coverage threshold, a file count. |
|
|
69
|
+
| ship the release | Irreversible, and needs a human decision. | Narrow to a checkable pre-release state (tag exists, `npm run release:dry-run` exits 0) and put "do not publish" in `Must not`. |
|
|
70
|
+
| after I confirm the design | The verifier cannot see a confirmation that never happened. | Move it to `On block:` as the decision a human must make. |
|
|
67
71
|
|
|
68
72
|
## Let `/goal-draft` write it
|
|
69
73
|
|
|
@@ -73,13 +77,13 @@ For an audit, completion means covering the agreed scenarios and reporting evide
|
|
|
73
77
|
|
|
74
78
|
If a success criterion, command, input path, or essential decision cannot be established, the skill returns a draft marked "Needs clarification" with `<TODO: …>` items. It does not offer that draft for approval or print a runnable `/goal set` or `/goal edit` command. Nonessential defaults are marked `[ASSUMPTION]`; they do not stand in for missing success criteria.
|
|
75
79
|
|
|
76
|
-
Once the objective is ready, an interactive terminal session can show the `propose_goal` approval dialog described below.
|
|
80
|
+
Once the objective is ready, an interactive terminal or Web Shell session can show the `propose_goal` approval dialog described below. Clients without Goal proposal support, headless runs, sessions with the tool disabled, and sessions with an active Goal receive a command to run manually instead. The hand-off says that the draft has not been applied. The skill never starts the work itself, and nothing is set without your approval.
|
|
77
81
|
|
|
78
82
|
Pass an existing objective to tighten it: `/goal-draft all tests pass and the lint is clean`. For an active Goal, an explicit request to tighten it produces `/goal edit`; a replacement uses `/goal set`. If the intended operation is unclear, the skill includes that choice in its single round of questions.
|
|
79
83
|
|
|
80
84
|
### Approve a Goal the model proposes
|
|
81
85
|
|
|
82
|
-
In an interactive terminal
|
|
86
|
+
In an interactive terminal or a Web Shell turn with an attached client, the model has a `propose_goal` tool. When `/goal-draft` finishes, or when you ask for an outcome that spans several turns, it can propose the objective instead of printing a `/goal set …` line for you to copy. The proposal appears as an approval dialog showing the full objective. Approving it sets the Goal exactly as `/goal set` would, the moment the current turn ends (the model acknowledges and stops; the first Goal turn then starts on its own), and declining sets nothing — the model sees only that the tool call was not allowed, and its instructions tell it not to ask why and not to propose the same objective again. The approval is bound to the turn that asked for it: if that turn is cancelled or otherwise never reaches its end, the approval is dropped rather than applied under a later message or an automated turn. No permission rule or approval mode (including YOLO) skips this dialog, and the tool refuses while another Goal is active, in plan mode, and in untrusted folders; subagents are never offered it. Web Shell uses its existing Allow/Reject permission panel. A stopped Goal can be replaced only if it still matches the version shown for approval; changing it invalidates the proposal. Headless runs, Web Shell channel deliveries and automatic turns, and ACP clients without the required approval and turn-lifecycle support retain the printed `/goal set` hand-off.
|
|
83
87
|
|
|
84
88
|
Turn it off with `goals.modelProposed: "disabled"` in your user settings. Because the setting decides whether the model may ask you to start an autonomous loop, it is honored only from user and system scope; a workspace `.qwen/settings.json` value is ignored with a warning.
|
|
85
89
|
|