@qwen-code/qwen-code 0.25.4-preview.0 → 0.25.4-preview.1
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/browser-use/runtime/native-host.js +0 -0
- package/bundled/browser-use/runtime/node_modules/playwright-core/bin/reinstall_chrome_beta_linux.sh +0 -0
- package/bundled/browser-use/runtime/node_modules/playwright-core/bin/reinstall_chrome_beta_mac.sh +0 -0
- package/bundled/browser-use/runtime/node_modules/playwright-core/bin/reinstall_chrome_stable_linux.sh +0 -0
- package/bundled/browser-use/runtime/node_modules/playwright-core/bin/reinstall_chrome_stable_mac.sh +0 -0
- package/bundled/browser-use/runtime/node_modules/playwright-core/bin/reinstall_msedge_beta_linux.sh +0 -0
- package/bundled/browser-use/runtime/node_modules/playwright-core/bin/reinstall_msedge_beta_mac.sh +0 -0
- package/bundled/browser-use/runtime/node_modules/playwright-core/bin/reinstall_msedge_dev_linux.sh +0 -0
- package/bundled/browser-use/runtime/node_modules/playwright-core/bin/reinstall_msedge_dev_mac.sh +0 -0
- package/bundled/browser-use/runtime/node_modules/playwright-core/bin/reinstall_msedge_stable_linux.sh +0 -0
- package/bundled/browser-use/runtime/node_modules/playwright-core/bin/reinstall_msedge_stable_mac.sh +0 -0
- package/bundled/browser-use/runtime/node_modules/playwright-core/cli.js +0 -0
- package/bundled/browser-use/runtime/node_modules/playwright-core/lib/webp_codec.wasm +0 -0
- package/bundled/browser-use/runtime/node_modules/playwright-core/lib/xdg-open +0 -0
- package/bundled/browser-use/runtime/scripts/native-host-setup.js +0 -0
- package/chunks/{MaxSizedBox-M27H235V.js → MaxSizedBox-E4RKSA7W.js} +1 -1
- package/chunks/{StandaloneSessionPicker-LWWDDYOW.js → StandaloneSessionPicker-2D3UKLVS.js} +1 -1
- package/chunks/{acp-subagent-executor-NUV52JVS.js → acp-subagent-executor-UQYUN6AB.js} +1 -1
- package/chunks/{acpAgent-IUJDXLZM.js → acpAgent-P7WGK2BP.js} +3 -3
- package/chunks/{advisor-MSOUBMJ6.js → advisor-GCH2MBXT.js} +1 -1
- package/chunks/{agent-H7XIWYWQ.js → agent-57T4YAYP.js} +1 -1
- package/chunks/{agent-headless-XDN3D3S3.js → agent-headless-IBON3A7N.js} +1 -1
- package/chunks/{agent-host-client-AZP3PZXS.js → agent-host-client-LE7P72FR.js} +1 -1
- package/chunks/{agent-host-connections-JRVX7I6I.js → agent-host-connections-4DM57L26.js} +1 -1
- package/chunks/{anthropicContentGenerator-N7TV53LD.js → anthropicContentGenerator-C4TPFXUK.js} +1 -1
- package/chunks/{batch-MKSJFJUH.js → batch-YJJGMJWO.js} +1 -1
- package/chunks/{bridge-GNMKKHQ4.js → bridge-FIO2ENBG.js} +1 -1
- package/chunks/{channel-settings-store-Y4YCS7JX.js → channel-settings-store-TEBCLK2B.js} +1 -1
- package/chunks/{chunk-GPOUP5OK.js → chunk-27MTSS3T.js} +1 -1
- package/chunks/{chunk-C4ANA47H.js → chunk-2MGCRPM3.js} +1 -1
- package/chunks/{chunk-6DQNNRRC.js → chunk-2WBKWPSO.js} +1 -1
- package/chunks/{chunk-CATL2PQS.js → chunk-34WLYVDK.js} +5 -5
- package/chunks/{chunk-B7CXPNCV.js → chunk-3J2YNEHG.js} +1 -1
- package/chunks/{chunk-VTNHPXNL.js → chunk-3TBFTELA.js} +1 -1
- package/chunks/{chunk-7JT34VGK.js → chunk-46I6JBVL.js} +1 -1
- package/chunks/{chunk-FEMWELCV.js → chunk-4ZKFLOEH.js} +1 -1
- package/chunks/{chunk-7AYXAVTZ.js → chunk-5DUJIOOX.js} +3 -3
- package/chunks/{chunk-6QLHJSVW.js → chunk-6PWOLWTH.js} +1 -1
- package/chunks/{chunk-OW4QBRSR.js → chunk-6UZ65Z2P.js} +1 -1
- package/chunks/{chunk-V2JZO5MS.js → chunk-7DSJE3CL.js} +1 -1
- package/chunks/{chunk-TJMHIEYI.js → chunk-7LCY7GGX.js} +1 -1
- package/chunks/{chunk-TLJHBK3A.js → chunk-7RNTXEWH.js} +1 -1
- package/chunks/{chunk-YZ7OO4AQ.js → chunk-A3IF6IOB.js} +1 -1
- package/chunks/{chunk-VTF6AVZB.js → chunk-A6OQSOUO.js} +1 -1
- package/chunks/{chunk-Y7YDHCON.js → chunk-AJ6JUUP7.js} +1 -1
- package/chunks/{chunk-QTMHQGWQ.js → chunk-AOMEBVFW.js} +1 -1
- package/chunks/{chunk-KVTG2ZNH.js → chunk-AUNAS7AS.js} +1 -1
- package/chunks/{chunk-BOFD4CN3.js → chunk-AVIDPC5K.js} +1 -1
- package/chunks/{chunk-ETYTRKB2.js → chunk-BOLPBPWC.js} +1 -1
- package/chunks/{chunk-OAPA66DR.js → chunk-BQQBFDBY.js} +1 -1
- package/chunks/{chunk-NOS2CNOI.js → chunk-CN22ATWU.js} +1 -1
- package/chunks/{chunk-XYBEQRSZ.js → chunk-DIHJELGW.js} +1 -1
- package/chunks/{chunk-XCEL3EDX.js → chunk-DJFCI7TU.js} +1 -1
- package/chunks/{chunk-VKEL2XTM.js → chunk-DQPDMFS3.js} +1 -1
- package/chunks/{chunk-DJRFEZBY.js → chunk-DSYKB77N.js} +1 -1
- package/chunks/{chunk-UEW7Q26E.js → chunk-EDNOGHMN.js} +2 -2
- package/chunks/{chunk-RXNGYG64.js → chunk-EE36D2EV.js} +1 -1
- package/chunks/{chunk-NZKX7HYL.js → chunk-EGQDN3FJ.js} +1 -1
- package/chunks/{chunk-DFRSQK5Q.js → chunk-FHFBCG6N.js} +1 -1
- package/chunks/{chunk-PECV2VVZ.js → chunk-GI6T3RBV.js} +1 -1
- package/chunks/{chunk-37BNHIUB.js → chunk-GOLT5JXA.js} +1 -1
- package/chunks/{chunk-KITFF4GL.js → chunk-IDGXHMNL.js} +1 -1
- package/chunks/{chunk-6HIOSLUM.js → chunk-IIZWK7ZP.js} +1 -1
- package/chunks/{chunk-MPGEAX4K.js → chunk-IJC6ZH2S.js} +1 -1
- package/chunks/{chunk-TLYJVB5H.js → chunk-IO6LSEPV.js} +1 -1
- package/chunks/{chunk-QIJKEZZR.js → chunk-IYVNCBMS.js} +1 -1
- package/chunks/{chunk-S4GOHFRN.js → chunk-JHGOWK7M.js} +1 -1
- package/chunks/{chunk-GHRD2MMC.js → chunk-JRJY343T.js} +1 -1
- package/chunks/{chunk-WCYZSCG7.js → chunk-JVUXQU3W.js} +1 -1
- package/chunks/{chunk-DMCTJUIJ.js → chunk-K2K2YYWO.js} +1 -1
- package/chunks/{chunk-37OHWQHB.js → chunk-KF6HU732.js} +2 -2
- package/chunks/{chunk-5LSV73BG.js → chunk-KVWUOBH7.js} +1 -1
- package/chunks/{chunk-7V4BAHFT.js → chunk-LBWBGFHD.js} +1 -1
- package/chunks/{chunk-RKPHDO42.js → chunk-LDXZT3SG.js} +5 -5
- package/chunks/{chunk-BGFA2SAQ.js → chunk-LFOZ6AIH.js} +1 -1
- package/chunks/{chunk-4322TZID.js → chunk-LGQHT42X.js} +2 -2
- package/chunks/{chunk-PDXZ2CUO.js → chunk-M3O2XDHA.js} +1 -1
- package/chunks/{chunk-47K2NMP6.js → chunk-M3UC46LS.js} +1 -1
- package/chunks/{chunk-UFRY7WND.js → chunk-M7JLPTQI.js} +1 -1
- package/chunks/{chunk-SATEKHQP.js → chunk-MBUXP3IS.js} +1 -1
- package/chunks/{chunk-RN6JS263.js → chunk-MEZA3VVH.js} +1 -1
- package/chunks/{chunk-OBFKP7RI.js → chunk-MWN6TR36.js} +1 -1
- package/chunks/{chunk-VHJ43ZYJ.js → chunk-O7XRQWCG.js} +1 -1
- package/chunks/{chunk-H224LNV3.js → chunk-OYFRLT5E.js} +1 -1
- package/chunks/{chunk-3NWFV2YF.js → chunk-PMBGV76N.js} +1 -1
- package/chunks/{chunk-YFAPACDE.js → chunk-PVM4IVFL.js} +6 -6
- package/chunks/{chunk-7WS2EYMQ.js → chunk-PWHD4NK3.js} +1 -1
- package/chunks/{chunk-JZIQSEFO.js → chunk-Q54NROBX.js} +1 -1
- package/chunks/{chunk-FCLAPJ22.js → chunk-QE7R4DPT.js} +1 -1
- package/chunks/{chunk-J6TW7GNF.js → chunk-QIUTQICH.js} +1 -1
- package/chunks/{chunk-TWDCN5H2.js → chunk-QK63EULE.js} +1 -1
- package/chunks/{chunk-HZZT75LI.js → chunk-QTAC4W7J.js} +1 -1
- package/chunks/{chunk-P7DIAJNX.js → chunk-R7HBR4QQ.js} +1 -1
- package/chunks/{chunk-U2FJSKS3.js → chunk-RHEMFKMX.js} +1 -1
- package/chunks/{chunk-TRRY3QMM.js → chunk-RL57IU47.js} +1 -1
- package/chunks/{chunk-SPWDYRDH.js → chunk-S2OOQRLJ.js} +1 -1
- package/chunks/{chunk-QBRADQ7L.js → chunk-SWTMWNTZ.js} +1 -1
- package/chunks/{chunk-AZUDF52L.js → chunk-SXTKQHFZ.js} +1 -1
- package/chunks/{chunk-5RQRSPPD.js → chunk-T5S3MJIK.js} +1 -1
- package/chunks/{chunk-I3ORWQ2U.js → chunk-UDGDEIBB.js} +1 -1
- package/chunks/{chunk-EMDEBV33.js → chunk-UIFBF3E7.js} +1 -1
- package/chunks/{chunk-BGEMWNES.js → chunk-UQDPWI7D.js} +1 -1
- package/chunks/{chunk-I5LKOTZT.js → chunk-VON4MVIM.js} +1 -1
- package/chunks/{chunk-HJPO6MEW.js → chunk-W5D2T2JK.js} +1 -1
- package/chunks/{chunk-F6YYDRMH.js → chunk-WNGYYU67.js} +1 -1
- package/chunks/{chunk-S2GKUZZZ.js → chunk-WO3F62ZD.js} +1 -1
- package/chunks/{chunk-K7KW3ZJQ.js → chunk-WVY5Q6YY.js} +1 -1
- package/chunks/{chunk-GH6DPLWU.js → chunk-Y4Q667BW.js} +1 -1
- package/chunks/{chunk-FH74N7Y7.js → chunk-YJLMFUCS.js} +2 -2
- package/chunks/{chunk-C3Y2S5AM.js → chunk-YKHRCSKP.js} +1 -1
- package/chunks/{chunk-P4UJ7CXJ.js → chunk-YLIS36QA.js} +1 -1
- package/chunks/{chunk-4QIFOIBS.js → chunk-YVZ4XZRB.js} +1 -1
- package/chunks/{chunk-KGRD6G5J.js → chunk-Z27JJPKN.js} +1 -1
- package/chunks/{chunk-KOHHDB2L.js → chunk-ZCIS6MJZ.js} +1 -1
- package/chunks/{chunk-QNNDZYVW.js → chunk-ZHLQ222N.js} +1 -1
- package/chunks/{chunk-KWRZ3WJO.js → chunk-ZP7MTWMR.js} +1 -1
- package/chunks/{codex-subagent-executor-H44VDB5E.js → codex-subagent-executor-6OJVGF2S.js} +1 -1
- package/chunks/{config-utils-4X4SV4RL.js → config-utils-FI3A4QAN.js} +1 -1
- package/chunks/{contextCommand-4KVOHTAJ.js → contextCommand-YEBZQHG4.js} +1 -1
- package/chunks/{core-runtime-4RARI4NX.js → core-runtime-CFMHUAS7.js} +1 -1
- package/chunks/{create-sub-session-CNSRJFYG.js → create-sub-session-G26337FT.js} +1 -1
- package/chunks/{daemon-git-worktree-guard-6XQQPP2H.js → daemon-git-worktree-guard-ITU6NQIV.js} +1 -1
- package/chunks/{daemon-status-provider-PRTEQT5T.js → daemon-status-provider-CSWRGMRX.js} +1 -1
- package/chunks/{daemon-trust-policy-GXKJVZDU.js → daemon-trust-policy-IYD7NOGK.js} +1 -1
- package/chunks/{daemon-trust-policy-monitor-L2ORKHMM.js → daemon-trust-policy-monitor-OWUP5SYB.js} +1 -1
- package/chunks/{deferred-core-runtime-RZQFUSPX.js → deferred-core-runtime-CVCQU7O4.js} +1 -1
- package/chunks/{edit-W44XQCIS.js → edit-7YBQLILC.js} +1 -1
- package/chunks/{enterPlanMode-B456A2XO.js → enterPlanMode-L3PVSD2P.js} +1 -1
- package/chunks/{environment-DSGQSQFS.js → environment-BVEOYQHO.js} +1 -1
- package/chunks/{errors-KL725247.js → errors-VQWBGR6D.js} +1 -1
- package/chunks/{execution-tool-KT3EBWHG.js → execution-tool-P7CBXSGZ.js} +1 -1
- package/chunks/{execution-worker-LPQ4HMN4.js → execution-worker-RZXNYK4B.js} +1 -1
- package/chunks/{exitPlanMode-JLKS76IA.js → exitPlanMode-MBUTM3NW.js} +1 -1
- package/chunks/{fast-path-5UD52IHH.js → fast-path-T2FDUSHV.js} +1 -1
- package/chunks/{glob-LYA2H6X3.js → glob-RH7XXSYE.js} +1 -1
- package/chunks/{goal-tools-SHSIDLZX.js → goal-tools-K6XBCE5E.js} +1 -1
- package/chunks/{handleAutoUpdate-T4RE6CZN.js → handleAutoUpdate-PG7R3KPH.js} +1 -1
- package/chunks/{i18n-5DK327WA.js → i18n-EGTBMA3N.js} +1 -1
- package/chunks/{initializer-TJGE4OJA.js → initializer-RIKH4PCP.js} +1 -1
- package/chunks/{installationInfo-MZ62GDIC.js → installationInfo-BBADHZLD.js} +1 -1
- package/chunks/{interactive-mod-session-YCUBQ6RM.js → interactive-mod-session-7RDKAHZ4.js} +1 -1
- package/chunks/{list-4L3LYDQM.js → list-YEGWEHJX.js} +1 -1
- package/chunks/{llm-3JQWBZXV.js → llm-D3LHPY27.js} +4 -4
- package/chunks/{llm-content-generator-6UPJWPOM.js → llm-content-generator-BLTBMV66.js} +1 -1
- package/chunks/{loadedSettingsAdapter-STPKAFJG.js → loadedSettingsAdapter-PLGMKMFO.js} +1 -1
- package/chunks/{local-execution-environment-IE5BOI7Y.js → local-execution-environment-4LDKFNC4.js} +1 -1
- package/chunks/{loggingContentGenerator-4KKWPZJA.js → loggingContentGenerator-376R7DRI.js} +1 -1
- package/chunks/{manage-memory-CRV5SXZZ.js → manage-memory-2ZTIVKNU.js} +1 -1
- package/chunks/{managed-execution-engine-FHLEWVND.js → managed-execution-engine-5LOM3MXG.js} +1 -1
- package/chunks/{managed-npm-update-BRHPOKDU.js → managed-npm-update-2C5JYEXW.js} +1 -1
- package/chunks/{managed-runtime-attestation-worker-GIQKZ5BH.js → managed-runtime-attestation-worker-R2FECMZK.js} +1 -1
- package/chunks/{managed-runtime-bootstrap-P72BT46H.js → managed-runtime-bootstrap-KPLGH4UE.js} +1 -1
- package/chunks/{managed-runtime-session-worker-IYCJDB5K.js → managed-runtime-session-worker-EVKNPK3V.js} +1 -1
- package/chunks/{managed-runtime-ssh-worker-ONT4V5ZG.js → managed-runtime-ssh-worker-IA4HZ3PD.js} +1 -1
- package/chunks/{mcp-NXCQVE2Y.js → mcp-S67IJLI6.js} +1 -1
- package/chunks/{model-call-collection-3DNL45M5.js → model-call-collection-6OGPDTPG.js} +1 -1
- package/chunks/{model-configuration-6HRNYBWV.js → model-configuration-6RWVBOQS.js} +1 -1
- package/chunks/{modelConfigUtils-SKBN64ZW.js → modelConfigUtils-M3TVVYAO.js} +1 -1
- package/chunks/{monitor-7I7Q73UR.js → monitor-ZHOFTN7N.js} +1 -1
- package/chunks/{nonInteractiveCli-YLYRJUBE.js → nonInteractiveCli-6SUGPTJ4.js} +1 -1
- package/chunks/{nonInteractiveToolExecutor-U2ASWT63.js → nonInteractiveToolExecutor-SAHBGO3A.js} +1 -1
- package/chunks/{notebook-edit-WAD7IQCF.js → notebook-edit-ETUOQH6G.js} +1 -1
- package/chunks/{omni-POUUDVU3.js → omni-HV2UBGMZ.js} +1 -1
- package/chunks/{openaiContentGenerator-L7X6IVPL.js → openaiContentGenerator-RZCG7E4M.js} +1 -1
- package/chunks/{openaiResponsesContentGenerator-7XCMFI6P.js → openaiResponsesContentGenerator-X23L5JV3.js} +1 -1
- package/chunks/{pidfile-MQQT2ZDA.js → pidfile-26WXQCHG.js} +1 -1
- package/chunks/{processUtils-OZLF72NC.js → processUtils-WXLFGNBT.js} +1 -1
- package/chunks/{prompt-terminal-ledger-IYUF6SUU.js → prompt-terminal-ledger-EIZZHF4A.js} +1 -1
- package/chunks/{qwenContentGenerator-DKH3ILUO.js → qwenContentGenerator-GOY7Y6KH.js} +1 -1
- package/chunks/{reactive-degrade-KSNGHMBN.js → reactive-degrade-MNMTTHO5.js} +1 -1
- package/chunks/{read-file-VEELW4OQ.js → read-file-OJNGPNTQ.js} +1 -1
- package/chunks/{resumeHistoryUtils-4SFDTBXU.js → resumeHistoryUtils-QWOWF4VY.js} +1 -1
- package/chunks/{review-QA6HRLVU.js → review-5S24HP2V.js} +1 -1
- package/chunks/{ripGrep-4J6ASSE3.js → ripGrep-Y4PY2MQF.js} +1 -1
- package/chunks/{run-qwen-serve-EJ67LA5O.js → run-qwen-serve-EOUUDZUK.js} +2 -2
- package/chunks/{runtime-6E2FSB5U.js → runtime-ZBPOQX6E.js} +1 -1
- package/chunks/{sandboxConfig-4VE4LNRI.js → sandboxConfig-R7KDS3P5.js} +1 -1
- package/chunks/{scheduled-tasks-GM5EJMK7.js → scheduled-tasks-Q6V7D6K6.js} +1 -1
- package/chunks/{scheduler-HOSVIIOE.js → scheduler-EBQY6BOK.js} +1 -1
- package/chunks/{search-memory-HEAQCHIK.js → search-memory-HX6E23JC.js} +1 -1
- package/chunks/{send-message-FAQ7XEZ5.js → send-message-OZCCCH2F.js} +1 -1
- package/chunks/{serve-VNKPOWSW.js → serve-CMGCI4BK.js} +1 -1
- package/chunks/{server-U2XBJLOV.js → server-7LOAKPDN.js} +3 -3
- package/chunks/{session-AZGROSFX.js → session-LVQYZSJE.js} +1 -1
- package/chunks/{session-attachments-root-6M2ECUNK.js → session-attachments-root-NWG7JOMN.js} +1 -1
- package/chunks/{session-execution-engine-selector-PYDVOSJF.js → session-execution-engine-selector-PHH47ZMA.js} +1 -1
- package/chunks/{session-pr-refresh-3IS7DLEV.js → session-pr-refresh-5IACZPCY.js} +1 -1
- package/chunks/{sessionService-3FWNA4ZB.js → sessionService-7PFAWLHC.js} +1 -1
- package/chunks/{settings-VHKT7JJC.js → settings-CPZBOHN5.js} +1 -1
- package/chunks/{shell-TYOPVB7H.js → shell-A7NLPS2W.js} +1 -1
- package/chunks/{skill-GJQIE5AX.js → skill-VGANGVOD.js} +1 -1
- package/chunks/{skill-settings-76NI6SF3.js → skill-settings-TSZO3X6N.js} +1 -1
- package/chunks/{spawnChannel-FMSYLDKB.js → spawnChannel-2JQYNQKT.js} +1 -1
- package/chunks/{standalone-update-BPZQDQHD.js → standalone-update-QXC3RM6I.js} +1 -1
- package/chunks/{start-opentui-ui-X7XYV5N3.js → start-opentui-ui-BKJ4JHVK.js} +1 -1
- package/chunks/{startInteractiveUI-UZDF4JUB.js → startInteractiveUI-4QIPR7ZY.js} +1 -1
- package/chunks/{team-create-RFZNEF76.js → team-create-5MU6BGXX.js} +1 -1
- package/chunks/{team-plan-approval-MGW3JGSC.js → team-plan-approval-NZUJ6FSA.js} +1 -1
- package/chunks/{terminal-image-renderer-3UED5GZV.js → terminal-image-renderer-CTMJULJ2.js} +1 -1
- package/chunks/{theme-manager-SF6FSSZW.js → theme-manager-6H7GA6QR.js} +1 -1
- package/chunks/{tool-call-W2CJR74U.js → tool-call-XG4CAD5X.js} +1 -1
- package/chunks/{tool-result-media-XSFON2ZQ.js → tool-result-media-RJ5ONO7R.js} +1 -1
- package/chunks/{tool-search-7GY5YTOU.js → tool-search-KBINGEWV.js} +1 -1
- package/chunks/{total-session-admission-OATGW6M5.js → total-session-admission-XNWYCO7G.js} +1 -1
- package/chunks/{trustedFolders-AM4PSGUB.js → trustedFolders-JT5MOB3A.js} +1 -1
- package/chunks/{update-relaunch-YKY52XUT.js → update-relaunch-HXMQI3HO.js} +1 -1
- package/chunks/{updateCheck-RKQ5CPZM.js → updateCheck-XWE3TWL5.js} +1 -1
- package/chunks/{upload-config-CBT7ARZY.js → upload-config-ET7NRHU7.js} +1 -1
- package/chunks/{useAutoAcceptIndicator-Z3YWPUNO.js → useAutoAcceptIndicator-TPMYKNJX.js} +1 -1
- package/chunks/{validateNonInterActiveAuth-7CQHU2RF.js → validateNonInterActiveAuth-U52KMEDS.js} +1 -1
- package/chunks/{version-N2OB6KWP.js → version-CW4RTJ3H.js} +1 -1
- package/chunks/{web-fetch-L5XCBCBA.js → web-fetch-UPMJ3XIZ.js} +1 -1
- package/chunks/{web-search-4EHUA3LJ.js → web-search-PXABWQVC.js} +1 -1
- package/chunks/{workflow-FGAUAYIP.js → workflow-UQ4V3NBZ.js} +1 -1
- package/chunks/{workflow-ancestor-trust-F7RRN6I3.js → workflow-ancestor-trust-QII5KTUJ.js} +1 -1
- package/chunks/{workspace-agents-QW4TKC52.js → workspace-agents-Q3KKMDX2.js} +1 -1
- package/chunks/{workspace-providers-status-MFSZT3YA.js → workspace-providers-status-3ASB64FB.js} +1 -1
- package/chunks/{workspace-registration-store-WQRDSIEI.js → workspace-registration-store-2NPD6U3B.js} +1 -1
- package/chunks/{workspace-registry-FXZFRSCH.js → workspace-registry-6QJKRCDR.js} +1 -1
- package/chunks/{workspace-runtime-coordinator-LJ5YAT3A.js → workspace-runtime-coordinator-ZXUWDQIB.js} +1 -1
- package/chunks/{workspace-service-U632SUWU.js → workspace-service-YPYTYYUN.js} +1 -1
- package/chunks/{workspace-skills-status-M7YXM3LF.js → workspace-skills-status-VTFHQ6R7.js} +1 -1
- package/chunks/{workspace-trust-reconciler-NLJGGI4K.js → workspace-trust-reconciler-52CZVPKH.js} +1 -1
- package/chunks/{write-file-BJCKSXX7.js → write-file-FDBR76G5.js} +1 -1
- package/chunks/{zoom-image-TLJPD4DB.js → zoom-image-MYKWCCXO.js} +1 -1
- package/cli.js +2 -2
- package/execution-worker.js +1 -1
- package/export-transcript-document.js +1 -1
- package/package.json +4 -4
- package/vendor/landlock-run/arm64-linux/qwen-landlock-run +0 -0
- package/vendor/landlock-run/x64-linux/qwen-landlock-run +0 -0
- package/vendor/ripgrep/arm64-darwin/rg +0 -0
- package/vendor/ripgrep/arm64-linux/rg +0 -0
- package/vendor/ripgrep/x64-darwin/rg +0 -0
- package/vendor/ripgrep/x64-linux/rg +0 -0
- package/vendor/tree-sitter/tree-sitter-bash.wasm +0 -0
- package/vendor/tree-sitter/tree-sitter.wasm +0 -0
- package/web-shell/assets/{PierreFilePreview-D9tbdFw8.js → PierreFilePreview-DGTp45Z4.js} +1 -1
- package/web-shell/assets/{SpreadsheetPreview-CeFAk2s-.js → SpreadsheetPreview-DVC_YVei.js} +1 -1
- package/web-shell/assets/{WorkspaceFileBrowser-iaURw8SR.js → WorkspaceFileBrowser-DaQNpS06.js} +1 -1
- package/web-shell/assets/{abnfDiagram-VCTEODGH-Z4CT1NCF.js → abnfDiagram-VCTEODGH-wJbiOoPK.js} +1 -1
- package/web-shell/assets/{agents-route-B7o2Rq-a.js → agents-route-DUhhA1KI.js} +1 -1
- package/web-shell/assets/{arc-DcHBdUJQ.js → arc-CvpNMy1d.js} +1 -1
- package/web-shell/assets/{architectureDiagram-5GKGNRK7-DRDhEC81.js → architectureDiagram-5GKGNRK7-DIhi3dIz.js} +1 -1
- package/web-shell/assets/{blockDiagram-NRAW4CY4-CYRE6WIc.js → blockDiagram-NRAW4CY4-CoeyTlVJ.js} +1 -1
- package/web-shell/assets/{c4Diagram-UCG6FXSJ-CIM8N_Sj.js → c4Diagram-UCG6FXSJ-BYoK_I9M.js} +1 -1
- package/web-shell/assets/channel-DvtGOCg6.js +1 -0
- package/web-shell/assets/{chunk-2Q5K7J3B-Bbfka9Fe.js → chunk-2Q5K7J3B-BeD4GwPg.js} +1 -1
- package/web-shell/assets/{chunk-5VM5RSS4-C02zF3RY.js → chunk-5VM5RSS4-BpkJsB_y.js} +1 -1
- package/web-shell/assets/{chunk-F27PBJKO-Dn0wRD2F.js → chunk-F27PBJKO-BROEWQ1J.js} +1 -1
- package/web-shell/assets/{chunk-G27WJ6UU-Dwpl3l0W.js → chunk-G27WJ6UU-DA8Wtppt.js} +1 -1
- package/web-shell/assets/{chunk-JWPE2WC7-sQbzSoTR.js → chunk-JWPE2WC7-GqB-QFh5.js} +1 -1
- package/web-shell/assets/{chunk-LCL6LL3I-DNlNDtfr.js → chunk-LCL6LL3I-DIPUwYsX.js} +1 -1
- package/web-shell/assets/{chunk-POPQ4Y6H-BOgf1Dl3.js → chunk-POPQ4Y6H-DbnU-jxX.js} +1 -1
- package/web-shell/assets/{chunk-SVP7TREG-DOofWP00.js → chunk-SVP7TREG-DvH7bQ-w.js} +1 -1
- package/web-shell/assets/{chunk-XXDRQBXY-Bj9FxhWU.js → chunk-XXDRQBXY-DdVWVo3U.js} +1 -1
- package/web-shell/assets/classDiagram-DTDB5LWJ-9NR5W1rE.js +1 -0
- package/web-shell/assets/classDiagram-v2-JRS7N3AN-9NR5W1rE.js +1 -0
- package/web-shell/assets/{cose-bilkent-JH36ORCC-CUlPjyww.js → cose-bilkent-JH36ORCC-JgMKxP9H.js} +1 -1
- package/web-shell/assets/{cynefin-OW5HDTMX-5noArzI7.js → cynefin-OW5HDTMX-BVUpNgVm.js} +1 -1
- package/web-shell/assets/{cynefinDiagram-5FMLGOSQ-DELvTqmf.js → cynefinDiagram-5FMLGOSQ-CxAdk-iS.js} +1 -1
- package/web-shell/assets/{dagre-3AP2YEHR-CAL6Z3hL.js → dagre-3AP2YEHR-CvXWkM86.js} +1 -1
- package/web-shell/assets/{diagram-S7CK7UJ4-DQC2gaIi.js → diagram-S7CK7UJ4-DD_PS4nm.js} +1 -1
- package/web-shell/assets/{diagram-UQ7AKVKN-CkU6M-3R.js → diagram-UQ7AKVKN-EVZkTODD.js} +1 -1
- package/web-shell/assets/{diagram-VSXAHHWV-CvHpHwVx.js → diagram-VSXAHHWV-CGZc1pZU.js} +1 -1
- package/web-shell/assets/{diagram-VX7I27RA-D9l5F9iB.js → diagram-VX7I27RA-DjNql499.js} +1 -1
- package/web-shell/assets/{diagram-Z3DM3KII-DW-VFvYx.js → diagram-Z3DM3KII-CCa0WtmR.js} +1 -1
- package/web-shell/assets/{docx-preview-8MQfOGQh.js → docx-preview-DpVElxvj.js} +1 -1
- package/web-shell/assets/{ebnfDiagram-PWID7BFC-C0Q71wC_.js → ebnfDiagram-PWID7BFC-W2hoOJZF.js} +1 -1
- package/web-shell/assets/{erDiagram-SSCWMZ5O-DWDLRh1S.js → erDiagram-SSCWMZ5O-Dz5NxxEb.js} +1 -1
- package/web-shell/assets/{flowDiagram-A5DVABFB-CVzJnl1P.js → flowDiagram-A5DVABFB-BTMAn8b5.js} +1 -1
- package/web-shell/assets/{ganttDiagram-EL5Y4UJY-B320pcgR.js → ganttDiagram-EL5Y4UJY-BaFrd5ZY.js} +1 -1
- package/web-shell/assets/{gitGraphDiagram-WWUBYQGX-Di4uZh-J.js → gitGraphDiagram-WWUBYQGX-IlmdUqRk.js} +1 -1
- package/web-shell/assets/{index-Csr8Hx_O.js → index-C2ez0ZjE.js} +1 -1
- package/web-shell/assets/{index-C9BecA_H.js → index-Cs-XBNmB.js} +101 -101
- package/web-shell/assets/{infoDiagram-RXCK75RN-CbafhxET.js → infoDiagram-RXCK75RN-BHs9kpar.js} +1 -1
- package/web-shell/assets/{ishikawaDiagram-5VMMS53U-DrQuIDeR.js → ishikawaDiagram-5VMMS53U-DWCEQ85v.js} +1 -1
- package/web-shell/assets/{journeyDiagram-EYS64GPL-BschmjBj.js → journeyDiagram-EYS64GPL-RTDAw9yc.js} +1 -1
- package/web-shell/assets/{kanban-definition-3QL26DDD-B7x9BU9N.js → kanban-definition-3QL26DDD-B7Nl9bq6.js} +1 -1
- package/web-shell/assets/{layout-BewPaOyO.js → layout-BabjFEb1.js} +1 -1
- package/web-shell/assets/{linear-CnLILCVp.js → linear-CZuGjuQd.js} +1 -1
- package/web-shell/assets/{mermaid.core-Csj9KPfJ.js → mermaid.core-CK78bIGt.js} +6 -6
- package/web-shell/assets/{mindmap-definition-FBJOCRG2-CIGTi5gg.js → mindmap-definition-FBJOCRG2-BbcCi_jP.js} +1 -1
- package/web-shell/assets/{pegDiagram-XKGWAZYB-CuWBRQzb.js → pegDiagram-XKGWAZYB-DpLQ7u8i.js} +1 -1
- package/web-shell/assets/{pieDiagram-E7YTZNPT-Co5ukXCE.js → pieDiagram-E7YTZNPT-BpWFVtM0.js} +1 -1
- package/web-shell/assets/{quadrantDiagram-AXDQQJYC-B0hzjh6o.js → quadrantDiagram-AXDQQJYC-CGzYlaN1.js} +1 -1
- package/web-shell/assets/{railroadDiagram-O6MQD6OU-nhkJB0xD.js → railroadDiagram-O6MQD6OU-BNQYW-Zi.js} +1 -1
- package/web-shell/assets/{requirementDiagram-EFPCY7ZU-C7NpxjVR.js → requirementDiagram-EFPCY7ZU-C4fCdIDW.js} +1 -1
- package/web-shell/assets/{sankeyDiagram-P5KCCOFB-CUWlnhZC.js → sankeyDiagram-P5KCCOFB-BvbbAnMA.js} +1 -1
- package/web-shell/assets/{sequenceDiagram-WJ2MYXX4-BoykH0_J.js → sequenceDiagram-WJ2MYXX4-DGXNc6E1.js} +1 -1
- package/web-shell/assets/{sizeCapture-X5ZJPWSS-aF-PkSe5.js → sizeCapture-X5ZJPWSS-C4W45Xf5.js} +1 -1
- package/web-shell/assets/{stateDiagram-HBIQ2CUA-g5q0b922.js → stateDiagram-HBIQ2CUA-D3q0fen-.js} +1 -1
- package/web-shell/assets/stateDiagram-v2-4QOOHH4V-XKoYIi05.js +1 -0
- package/web-shell/assets/{swimlanes-XN3QIQJK-BbASszfe.js → swimlanes-XN3QIQJK-D8n-ResR.js} +1 -1
- package/web-shell/assets/swimlanesDiagram-VK2B7HYN-C7qJMSzs.js +8 -0
- package/web-shell/assets/{timeline-definition-24CTP7MA-AXIV0TJJ.js → timeline-definition-24CTP7MA-Cio4y1mM.js} +1 -1
- package/web-shell/assets/{vennDiagram-4TSXK5OY-B-E0rj1h.js → vennDiagram-4TSXK5OY-DVlg0xnc.js} +1 -1
- package/web-shell/assets/{wardleyDiagram-VM6X3IG4-DiOOYJ2D.js → wardleyDiagram-VM6X3IG4-CgeIsimQ.js} +1 -1
- package/web-shell/assets/{xychartDiagram-S5SC5T6Z-De_z7HkS.js → xychartDiagram-S5SC5T6Z-UXjyTLnU.js} +1 -1
- package/web-shell/index.html +1 -1
- package/web-shell/sw.js +1 -1
- package/web-shell/assets/channel-Bwr9aS_E.js +0 -1
- package/web-shell/assets/classDiagram-DTDB5LWJ-BmY8Mmyo.js +0 -1
- package/web-shell/assets/classDiagram-v2-JRS7N3AN-BmY8Mmyo.js +0 -1
- package/web-shell/assets/stateDiagram-v2-4QOOHH4V-CTOjUMow.js +0 -1
- package/web-shell/assets/swimlanesDiagram-VK2B7HYN-Bz6ia3oL.js +0 -8
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Force strict mode and setup for ESM
|
|
2
2
|
"use strict";
|
|
3
|
-
import{multiSessionCompatibilityError,parseMessageRoutingConfig,parseSessionRotationConfig}from"./chunk-CZGETTFA.js";import{UNSAFE_OBJECT_KEYS,getPlugin}from"./chunk-PCBYZYVK.js";import{CHANNEL_OUTPUT_MODE_FIELD,parseChannelOutputMode}from"./chunk-YUORVHMI.js";import{loadSettings,saveSettings}from"./chunk-DFRSQK5Q.js";import{init_esbuild_shims}from"./chunk-VKDAXTCZ.js";import{__name}from"./chunk-KBWJGX7I.js";init_esbuild_shims();import{createHash}from"node:crypto";import{isDeepStrictEqual}from"node:util";var ChannelSettingsError=class extends Error{constructor(code,message){super(message);this.code=code;this.name="ChannelSettingsError"}static{__name(this,"ChannelSettingsError")}};function revisionOf(channels,startupNames){return createHash("sha256").update(JSON.stringify({channels,startupNames})).digest("hex")}__name(revisionOf,"revisionOf");function applySecretUpdate(current,update){validateSecretUpdate(update);if(update.operation==="preserve")return current;if(update.operation==="clear")return void 0;if(typeof update.value!=="string"||update.value.length===0){throw invalidSecret("Secret replacements must be non-empty strings.")}return update.value}__name(applySecretUpdate,"applySecretUpdate");function invalidSecret(message){return new ChannelSettingsError("channel_settings_invalid_secret",message)}__name(invalidSecret,"invalidSecret");function invalidConfig(message){return new ChannelSettingsError("channel_settings_invalid_config",message)}__name(invalidConfig,"invalidConfig");function assertSafeChannelName(name){if(UNSAFE_OBJECT_KEYS.has(name)){throw new ChannelSettingsError("channel_settings_invalid_name",`Channel name ${JSON.stringify(name)} is not allowed.`)}}__name(assertSafeChannelName,"assertSafeChannelName");function assertUpsertChannelName(name){assertSafeChannelName(name);if(isAllStartupName(name)){throw new ChannelSettingsError("channel_settings_invalid_name",`Channel name ${JSON.stringify(name)} is reserved for startup selection.`)}}__name(assertUpsertChannelName,"assertUpsertChannelName");function isAllStartupName(name){return name.trim()==="all"}__name(isAllStartupName,"isAllStartupName");function isRecord(value){return value!==null&&typeof value==="object"&&!Array.isArray(value)}__name(isRecord,"isRecord");function isEnvironmentReference(value){return/^\$[A-Za-z_][A-Za-z0-9_]*$/.test(value)}__name(isEnvironmentReference,"isEnvironmentReference");function assertStringRecord(key,value,allowedKeys){if(!isRecord(value)){throw invalidConfig(`Channel field "${key}" must be an object.`)}for(const[nestedKey,nestedValue]of Object.entries(value)){if(!allowedKeys.has(nestedKey)||typeof nestedValue!=="string"){throw invalidConfig(`Channel field "${key}.${nestedKey}" is invalid.`)}}}__name(assertStringRecord,"assertStringRecord");function assertSharedField(key,value,previous){if(key==="messageRoutes"||key==="defaultMessageRoute"){return true}if(key==="multiSession"){if(typeof value!=="boolean"){throw invalidConfig(`Channel field "${key}" must be a boolean.`)}return true}if(key==="sessionRotation"){try{parseSessionRotationConfig("settings",value)}catch(error){throw invalidConfig(error instanceof Error?error.message:String(error))}return true}if(key==="groupSenderPolicy"||key==="allowedGroupUsers"){throw invalidConfig(`Channel field "${key}" moved to groups["*"].${key==="groupSenderPolicy"?"senders":"allowedUsers"}.`)}const enumValues={privatePolicy:new Set(["disabled","allowlist","pairing","open"]),senderPolicy:new Set(["allowlist","pairing","open"]),dmPolicy:new Set(["open","disabled"]),groupPolicy:new Set(["disabled","allowlist","pairing","open"]),sessionScope:new Set(["user","thread","chat_thread","single"]),dispatchMode:new Set(["steer","followup","collect"])};if(Object.hasOwn(enumValues,key)){if(typeof value!=="string"||!enumValues[key].has(value)){throw invalidConfig(`Channel field "${key}" has an invalid value.`)}return true}if(["model","cwd","approvalMode","instructions"].includes(key)){if(typeof value!=="string"){throw invalidConfig(`Channel field "${key}" must be a string.`)}return true}if(key==="allowedUsers"||key==="operators"){if(!Array.isArray(value)||value.some(item=>typeof item!=="string")){throw invalidConfig(`Channel field "${key}" must be a string array.`)}return true}if(key==="groups"){if(!isRecord(value)){if(containsUnsafeObjectKey(value)||!isDeepStrictEqual(previous,value)){throw invalidConfig(`Channel field "${key}" must be an object.`)}return true}const previousGroups=isRecord(previous)?previous:{};for(const[groupId,groupConfig]of Object.entries(value)){if(UNSAFE_OBJECT_KEYS.has(groupId)||!isRecord(groupConfig)){throw invalidConfig(`Channel field "${key}.${groupId}" is invalid.`)}const previousGroup=isRecord(previousGroups[groupId])?previousGroups[groupId]:{};for(const[nestedKey,nestedValue]of Object.entries(groupConfig)){const known=["requireMention","dispatchMode","groupHistoryLimit","senders","allowedUsers"].includes(nestedKey);const valid=nestedKey==="requireMention"&&typeof nestedValue==="boolean"||nestedKey==="dispatchMode"&&typeof nestedValue==="string"&&["collect","steer","followup"].includes(nestedValue)||nestedKey==="groupHistoryLimit"&&typeof nestedValue==="number"&&Number.isFinite(nestedValue)||nestedKey==="senders"&&typeof nestedValue==="string"&&["open","allowlist"].includes(nestedValue)||nestedKey==="allowedUsers"&&Array.isArray(nestedValue)&&nestedValue.every(item=>typeof item==="string");if(known&&!valid&&!(nestedKey!=="senders"&&Object.hasOwn(previousGroup,nestedKey)&&isDeepStrictEqual(previousGroup[nestedKey],nestedValue)&&!containsUnsafeObjectKey(nestedValue))){throw invalidConfig(`Channel field "${key}.${groupId}.${nestedKey}" is invalid.`)}if(!known){assertPreservedUnknownField(`${key}.${groupId}`,nestedKey,nestedValue,previousGroup)}}}return true}if(key==="groupHistoryLimit"){if(typeof value!=="number"||!Number.isFinite(value)){throw invalidConfig(`Channel field "${key}" must be a number.`)}return true}if(key==="identity"){assertStringRecord(key,value,new Set(["id","displayName","description"]));return true}if(key==="memoryScope"){if(!isRecord(value)){throw invalidConfig(`Channel field "${key}" must be an object.`)}for(const[nestedKey,nestedValue]of Object.entries(value)){const valid=nestedKey==="namespace"&&typeof nestedValue==="string"||nestedKey==="mode"&&nestedValue==="metadata-only";if(!valid){throw invalidConfig(`Channel field "${key}.${nestedKey}" is invalid.`)}}return true}return false}__name(assertSharedField,"assertSharedField");function containsUnsafeObjectKey(value){if(Array.isArray(value)){return value.some(item=>containsUnsafeObjectKey(item))}if(!isRecord(value))return false;return Object.entries(value).some(([key,nested])=>UNSAFE_OBJECT_KEYS.has(key)||containsUnsafeObjectKey(nested))}__name(containsUnsafeObjectKey,"containsUnsafeObjectKey");function assertDescriptorValue(field,value,path=field.key,previous){if(field.kind==="object"){if(isDeepStrictEqual(previous,value)&&!containsUnsafeObjectKey(value)){return}if(!isRecord(value)){throw invalidConfig(`Channel field "${path}" has an invalid value.`)}const previousRecord=isRecord(previous)?previous:{};const properties=new Map(field.properties.map(property=>[property.key,property]));for(const[key,nestedValue]of Object.entries(value)){const property=properties.get(key);if(!property){assertPreservedUnknownField(path,key,nestedValue,previousRecord);continue}assertDescriptorValue(property,nestedValue,`${path}.${key}`,Object.hasOwn(previousRecord,key)?previousRecord[key]:void 0)}assertRequiredFields(field.properties,value,path);return}const invalidEnvironment=typeof value==="string"&&isEnvironmentReference(value)&&!field.envResolvable;if(invalidEnvironment){throw invalidConfig(`Channel field "${path}" does not support environment references.`)}const valid=(field.kind==="string"||field.kind==="secret")&&typeof value==="string"&&value.length>0||field.kind==="boolean"&&typeof value==="boolean"||field.kind==="number"&&typeof value==="number"&&Number.isFinite(value)&&(field.exclusiveMinimum===void 0||value>field.exclusiveMinimum)||field.kind==="enum"&&typeof value==="string"&&field.options?.some(option=>option.value===value)===true||field.kind==="string-list"&&Array.isArray(value)&&value.every(item=>typeof item==="string")||field.kind==="record"&&isRecord(value)&&Object.values(value).every(v=>typeof v==="string")&&!containsUnsafeObjectKey(value);if(!valid){throw invalidConfig(`Channel field "${path}" has an invalid value.`)}}__name(assertDescriptorValue,"assertDescriptorValue");function assertRequiredFields(fields,values,path){for(const field of fields){if(!field.required)continue;const value=Object.hasOwn(values,field.key)?values[field.key]:void 0;if(value===void 0||value===null||value===""){const fieldPath=path?`${path}.${field.key}`:field.key;throw invalidConfig(`Channel field "${fieldPath}" is required.`)}}}__name(assertRequiredFields,"assertRequiredFields");function assertPreservedUnknownField(path,key,value,previous){const fieldPath=path?`${path}.${key}`:key;if(UNSAFE_OBJECT_KEYS.has(key)){throw invalidConfig(`Channel field "${fieldPath}" is not manageable.`)}if(containsUnsafeObjectKey(value)){throw invalidConfig(`Channel field "${fieldPath}" cannot use a reserved key.`)}if(Object.hasOwn(previous,key)&&isDeepStrictEqual(previous[key],value)){return}throw invalidConfig(`Channel field "${fieldPath}" is not manageable.`)}__name(assertPreservedUnknownField,"assertPreservedUnknownField");function assertManagedConfig(config,previous,fields){const descriptorFields=new Map(fields.map(field=>[field.key,field]));for(const[key,value]of Object.entries(config)){if(key==="type")continue;const field=descriptorFields.get(key);if(field){assertDescriptorValue(field,value,field.key,Object.hasOwn(previous,key)?previous[key]:void 0);continue}if(assertSharedField(key,value,Object.hasOwn(previous,key)?previous[key]:void 0)){continue}assertPreservedUnknownField(void 0,key,value,previous)}assertRequiredFields(fields,config)}__name(assertManagedConfig,"assertManagedConfig");function validateSecretUpdate(update){if(!isRecord(update)){throw invalidSecret("Secret updates must be objects.")}const operation=update["operation"];const keys=Object.keys(update).sort();const valid=(operation==="preserve"||operation==="clear")&&keys.length===1&&keys[0]==="operation"||operation==="replace"&&keys.length===2&&keys[0]==="operation"&&keys[1]==="value"&&typeof update["value"]==="string"&&update["value"].length>0;if(!valid){throw invalidSecret("Secret updates contain an invalid operation.")}}__name(validateSecretUpdate,"validateSecretUpdate");function assertValidChannelSecretUpdates(updates){if(!isRecord(updates)){throw invalidSecret("Secret updates must be objects.")}for(const[key,update]of Object.entries(updates)){if(UNSAFE_OBJECT_KEYS.has(key)){throw invalidSecret(`Secret update ${JSON.stringify(key)} is invalid.`)}validateSecretUpdate(update)}}__name(assertValidChannelSecretUpdates,"assertValidChannelSecretUpdates");function channelSettingsScope(workspaceCwd){const loaded=loadSettings(workspaceCwd,{skipLoadEnvironment:true});return loaded.workspaceSettingsActive?loaded.workspace:loaded.user}__name(channelSettingsScope,"channelSettingsScope");function channelRecordMap(value){const rawChannels=isRecord(value)?value:{};const channels={};for(const[name,config]of Object.entries(rawChannels)){if(UNSAFE_OBJECT_KEYS.has(name))continue;if(isRecord(config))channels[name]=config}return channels}__name(channelRecordMap,"channelRecordMap");function snapshotFrom(values){return{revision:revisionOf(values.channels,values.startupNames),channels:{...values.channels},startupNames:[...values.startupNames]}}__name(snapshotFrom,"snapshotFrom");function workspaceValues(workspaceCwd){const scope=channelSettingsScope(workspaceCwd);const settings=scope.settings;const startupNames=Array.isArray(settings.serve?.channels)?settings.serve.channels.filter(name=>typeof name==="string"):[];return{channels:channelRecordMap(settings.channels),storedChannels:channelRecordMap(scope.originalSettings.channels),startupNames}}__name(workspaceValues,"workspaceValues");var WorkspaceChannelSettingsStore=class{constructor(workspaceCwd){this.workspaceCwd=workspaceCwd}static{__name(this,"WorkspaceChannelSettingsStore")}snapshot(){return snapshotFrom(workspaceValues(this.workspaceCwd))}async upsert(name,options){assertUpsertChannelName(name);const secretUpdates=options.secrets===void 0?{}:options.secrets;assertValidChannelSecretUpdates(secretUpdates);const plugin=await getPlugin(options.config.type);if(!plugin?.management){throw new ChannelSettingsError("channel_settings_unmanageable",`Channel type "${options.config.type}" does not provide safe management metadata.`)}const secretKeys=new Set(plugin.management.fields.filter(field=>field.kind==="secret").map(field=>field.key));const envResolvableKeys=new Set(plugin.management.fields.filter(field=>field.envResolvable).map(field=>field.key));for(const key of Object.keys(secretUpdates)){if(!secretKeys.has(key)){throw invalidSecret(`Channel type "${options.config.type}" does not declare "${key}" as a secret.`)}}for(const key of secretKeys){if(Object.hasOwn(options.config,key)){throw invalidSecret(`Secret "${key}" must use an explicit preserve, replace, or clear operation.`)}}const{current,storedChannels}=this.assertRevision(options.expectedRevision);const storedPrevious=current.channels[name]??{};const hasPreviousOfType=storedPrevious["type"]===options.config.type;const previous=hasPreviousOfType?storedPrevious:{};const storedOnDisk=storedChannels[name]??{};const previousOnDisk=hasPreviousOfType?storedOnDisk:{};const nextConfig={...options.config};const storedReferences={};for(const key of secretKeys){const update=secretUpdates[key]??{operation:"preserve"};const value=applySecretUpdate(previous[key],update);if(value!==void 0)nextConfig[key]=value;if(update.operation==="preserve"&&previousOnDisk[key]!==void 0&&envResolvableKeys.has(key)){storedReferences[key]=previousOnDisk[key]}}for(const field of plugin.management.fields){const key=field.key;if(!field.envResolvable||secretKeys.has(key))continue;const onDisk=previousOnDisk[key];if(typeof onDisk!=="string"||!isEnvironmentReference(onDisk)){continue}if(nextConfig[key]!==previous[key])continue;storedReferences[key]=onDisk}try{parseChannelOutputMode(name,nextConfig["outputMode"],plugin.supportsOutputMode===true)}catch(error){throw invalidConfig(error instanceof Error?error.message:String(error))}assertManagedConfig(nextConfig,previous,plugin.supportsOutputMode===true?[...plugin.management.fields,CHANNEL_OUTPUT_MODE_FIELD]:plugin.management.fields);const multiSessionError=multiSessionCompatibilityError(name,{multiSession:nextConfig["multiSession"]===true,sessionRotation:parseSessionRotationConfig(name,nextConfig["sessionRotation"]),sessionScope:nextConfig["sessionScope"]??plugin.defaultSessionScope??"user",groupHistoryLimit:nextConfig["groupHistoryLimit"],groups:isRecord(nextConfig["groups"])?nextConfig["groups"]:{},webhooks:nextConfig["webhooks"]});if(multiSessionError)throw invalidConfig(multiSessionError);try{const routing=parseMessageRoutingConfig(name,nextConfig);if(routing.messageRoutes!==void 0)nextConfig["messageRoutes"]=routing.messageRoutes;if(routing.defaultMessageRoute!==void 0)nextConfig["defaultMessageRoute"]=routing.defaultMessageRoute}catch(error){throw invalidConfig(error instanceof Error?error.message:String(error))}let crossFieldError;try{crossFieldError=plugin.management.validateConfig?.(nextConfig);if(crossFieldError instanceof Promise){void crossFieldError.catch(()=>{})}}catch(error){throw invalidConfig(`Channel validateConfig failed: ${error instanceof Error?error.message:String(error)}`)}if(crossFieldError!==void 0){throw invalidConfig(typeof crossFieldError==="string"?crossFieldError:"Channel validateConfig must return a string error message.")}const channels={...storedChannels,[name]:{...nextConfig,...storedReferences}};saveSettings(channelSettingsScope(this.workspaceCwd),{channels},["channels"],{throwOnWriteFailure:true});return this.snapshot()}async remove(name,options){assertSafeChannelName(name);const{current,storedChannels}=this.assertRevision(options.expectedRevision);const configured=Object.hasOwn(current.channels,name);if(!configured){if(!current.startupNames.includes(name))return current;saveSettings(channelSettingsScope(this.workspaceCwd),{serve:{channels:current.startupNames.filter(startupName=>startupName!==name)}},["serve","channels"],{throwOnWriteFailure:true});return this.snapshot()}const channels={...storedChannels};delete channels[name];const hasAllSentinel=current.startupNames.some(isAllStartupName);const startupNames=hasAllSentinel?Object.keys(channels).some(channelName=>!isAllStartupName(channelName))?["all"]:[]:current.startupNames.filter(startupName=>startupName!==name);saveSettings(channelSettingsScope(this.workspaceCwd),{channels,serve:{channels:startupNames}},["channels"],{throwOnWriteFailure:true});return this.snapshot()}async setStartupNames(names,options){for(const name of names){assertSafeChannelName(name)}this.assertRevision(options.expectedRevision);saveSettings(channelSettingsScope(this.workspaceCwd),{serve:{channels:[...names]}},["serve","channels"],{throwOnWriteFailure:true});return this.snapshot()}assertRevision(expectedRevision){const values=workspaceValues(this.workspaceCwd);const current=snapshotFrom(values);if(current.revision!==expectedRevision){throw new ChannelSettingsError("channel_settings_conflict","Channel settings changed; reload before trying again.")}return{current,storedChannels:values.storedChannels}}};export{ChannelSettingsError,assertValidChannelSecretUpdates,WorkspaceChannelSettingsStore};
|
|
3
|
+
import{multiSessionCompatibilityError,parseMessageRoutingConfig,parseSessionRotationConfig}from"./chunk-CZGETTFA.js";import{UNSAFE_OBJECT_KEYS,getPlugin}from"./chunk-PCBYZYVK.js";import{CHANNEL_OUTPUT_MODE_FIELD,parseChannelOutputMode}from"./chunk-YUORVHMI.js";import{loadSettings,saveSettings}from"./chunk-FHFBCG6N.js";import{init_esbuild_shims}from"./chunk-VKDAXTCZ.js";import{__name}from"./chunk-KBWJGX7I.js";init_esbuild_shims();import{createHash}from"node:crypto";import{isDeepStrictEqual}from"node:util";var ChannelSettingsError=class extends Error{constructor(code,message){super(message);this.code=code;this.name="ChannelSettingsError"}static{__name(this,"ChannelSettingsError")}};function revisionOf(channels,startupNames){return createHash("sha256").update(JSON.stringify({channels,startupNames})).digest("hex")}__name(revisionOf,"revisionOf");function applySecretUpdate(current,update){validateSecretUpdate(update);if(update.operation==="preserve")return current;if(update.operation==="clear")return void 0;if(typeof update.value!=="string"||update.value.length===0){throw invalidSecret("Secret replacements must be non-empty strings.")}return update.value}__name(applySecretUpdate,"applySecretUpdate");function invalidSecret(message){return new ChannelSettingsError("channel_settings_invalid_secret",message)}__name(invalidSecret,"invalidSecret");function invalidConfig(message){return new ChannelSettingsError("channel_settings_invalid_config",message)}__name(invalidConfig,"invalidConfig");function assertSafeChannelName(name){if(UNSAFE_OBJECT_KEYS.has(name)){throw new ChannelSettingsError("channel_settings_invalid_name",`Channel name ${JSON.stringify(name)} is not allowed.`)}}__name(assertSafeChannelName,"assertSafeChannelName");function assertUpsertChannelName(name){assertSafeChannelName(name);if(isAllStartupName(name)){throw new ChannelSettingsError("channel_settings_invalid_name",`Channel name ${JSON.stringify(name)} is reserved for startup selection.`)}}__name(assertUpsertChannelName,"assertUpsertChannelName");function isAllStartupName(name){return name.trim()==="all"}__name(isAllStartupName,"isAllStartupName");function isRecord(value){return value!==null&&typeof value==="object"&&!Array.isArray(value)}__name(isRecord,"isRecord");function isEnvironmentReference(value){return/^\$[A-Za-z_][A-Za-z0-9_]*$/.test(value)}__name(isEnvironmentReference,"isEnvironmentReference");function assertStringRecord(key,value,allowedKeys){if(!isRecord(value)){throw invalidConfig(`Channel field "${key}" must be an object.`)}for(const[nestedKey,nestedValue]of Object.entries(value)){if(!allowedKeys.has(nestedKey)||typeof nestedValue!=="string"){throw invalidConfig(`Channel field "${key}.${nestedKey}" is invalid.`)}}}__name(assertStringRecord,"assertStringRecord");function assertSharedField(key,value,previous){if(key==="messageRoutes"||key==="defaultMessageRoute"){return true}if(key==="multiSession"){if(typeof value!=="boolean"){throw invalidConfig(`Channel field "${key}" must be a boolean.`)}return true}if(key==="sessionRotation"){try{parseSessionRotationConfig("settings",value)}catch(error){throw invalidConfig(error instanceof Error?error.message:String(error))}return true}if(key==="groupSenderPolicy"||key==="allowedGroupUsers"){throw invalidConfig(`Channel field "${key}" moved to groups["*"].${key==="groupSenderPolicy"?"senders":"allowedUsers"}.`)}const enumValues={privatePolicy:new Set(["disabled","allowlist","pairing","open"]),senderPolicy:new Set(["allowlist","pairing","open"]),dmPolicy:new Set(["open","disabled"]),groupPolicy:new Set(["disabled","allowlist","pairing","open"]),sessionScope:new Set(["user","thread","chat_thread","single"]),dispatchMode:new Set(["steer","followup","collect"])};if(Object.hasOwn(enumValues,key)){if(typeof value!=="string"||!enumValues[key].has(value)){throw invalidConfig(`Channel field "${key}" has an invalid value.`)}return true}if(["model","cwd","approvalMode","instructions"].includes(key)){if(typeof value!=="string"){throw invalidConfig(`Channel field "${key}" must be a string.`)}return true}if(key==="allowedUsers"||key==="operators"){if(!Array.isArray(value)||value.some(item=>typeof item!=="string")){throw invalidConfig(`Channel field "${key}" must be a string array.`)}return true}if(key==="groups"){if(!isRecord(value)){if(containsUnsafeObjectKey(value)||!isDeepStrictEqual(previous,value)){throw invalidConfig(`Channel field "${key}" must be an object.`)}return true}const previousGroups=isRecord(previous)?previous:{};for(const[groupId,groupConfig]of Object.entries(value)){if(UNSAFE_OBJECT_KEYS.has(groupId)||!isRecord(groupConfig)){throw invalidConfig(`Channel field "${key}.${groupId}" is invalid.`)}const previousGroup=isRecord(previousGroups[groupId])?previousGroups[groupId]:{};for(const[nestedKey,nestedValue]of Object.entries(groupConfig)){const known=["requireMention","dispatchMode","groupHistoryLimit","senders","allowedUsers"].includes(nestedKey);const valid=nestedKey==="requireMention"&&typeof nestedValue==="boolean"||nestedKey==="dispatchMode"&&typeof nestedValue==="string"&&["collect","steer","followup"].includes(nestedValue)||nestedKey==="groupHistoryLimit"&&typeof nestedValue==="number"&&Number.isFinite(nestedValue)||nestedKey==="senders"&&typeof nestedValue==="string"&&["open","allowlist"].includes(nestedValue)||nestedKey==="allowedUsers"&&Array.isArray(nestedValue)&&nestedValue.every(item=>typeof item==="string");if(known&&!valid&&!(nestedKey!=="senders"&&Object.hasOwn(previousGroup,nestedKey)&&isDeepStrictEqual(previousGroup[nestedKey],nestedValue)&&!containsUnsafeObjectKey(nestedValue))){throw invalidConfig(`Channel field "${key}.${groupId}.${nestedKey}" is invalid.`)}if(!known){assertPreservedUnknownField(`${key}.${groupId}`,nestedKey,nestedValue,previousGroup)}}}return true}if(key==="groupHistoryLimit"){if(typeof value!=="number"||!Number.isFinite(value)){throw invalidConfig(`Channel field "${key}" must be a number.`)}return true}if(key==="identity"){assertStringRecord(key,value,new Set(["id","displayName","description"]));return true}if(key==="memoryScope"){if(!isRecord(value)){throw invalidConfig(`Channel field "${key}" must be an object.`)}for(const[nestedKey,nestedValue]of Object.entries(value)){const valid=nestedKey==="namespace"&&typeof nestedValue==="string"||nestedKey==="mode"&&nestedValue==="metadata-only";if(!valid){throw invalidConfig(`Channel field "${key}.${nestedKey}" is invalid.`)}}return true}return false}__name(assertSharedField,"assertSharedField");function containsUnsafeObjectKey(value){if(Array.isArray(value)){return value.some(item=>containsUnsafeObjectKey(item))}if(!isRecord(value))return false;return Object.entries(value).some(([key,nested])=>UNSAFE_OBJECT_KEYS.has(key)||containsUnsafeObjectKey(nested))}__name(containsUnsafeObjectKey,"containsUnsafeObjectKey");function assertDescriptorValue(field,value,path=field.key,previous){if(field.kind==="object"){if(isDeepStrictEqual(previous,value)&&!containsUnsafeObjectKey(value)){return}if(!isRecord(value)){throw invalidConfig(`Channel field "${path}" has an invalid value.`)}const previousRecord=isRecord(previous)?previous:{};const properties=new Map(field.properties.map(property=>[property.key,property]));for(const[key,nestedValue]of Object.entries(value)){const property=properties.get(key);if(!property){assertPreservedUnknownField(path,key,nestedValue,previousRecord);continue}assertDescriptorValue(property,nestedValue,`${path}.${key}`,Object.hasOwn(previousRecord,key)?previousRecord[key]:void 0)}assertRequiredFields(field.properties,value,path);return}const invalidEnvironment=typeof value==="string"&&isEnvironmentReference(value)&&!field.envResolvable;if(invalidEnvironment){throw invalidConfig(`Channel field "${path}" does not support environment references.`)}const valid=(field.kind==="string"||field.kind==="secret")&&typeof value==="string"&&value.length>0||field.kind==="boolean"&&typeof value==="boolean"||field.kind==="number"&&typeof value==="number"&&Number.isFinite(value)&&(field.exclusiveMinimum===void 0||value>field.exclusiveMinimum)||field.kind==="enum"&&typeof value==="string"&&field.options?.some(option=>option.value===value)===true||field.kind==="string-list"&&Array.isArray(value)&&value.every(item=>typeof item==="string")||field.kind==="record"&&isRecord(value)&&Object.values(value).every(v=>typeof v==="string")&&!containsUnsafeObjectKey(value);if(!valid){throw invalidConfig(`Channel field "${path}" has an invalid value.`)}}__name(assertDescriptorValue,"assertDescriptorValue");function assertRequiredFields(fields,values,path){for(const field of fields){if(!field.required)continue;const value=Object.hasOwn(values,field.key)?values[field.key]:void 0;if(value===void 0||value===null||value===""){const fieldPath=path?`${path}.${field.key}`:field.key;throw invalidConfig(`Channel field "${fieldPath}" is required.`)}}}__name(assertRequiredFields,"assertRequiredFields");function assertPreservedUnknownField(path,key,value,previous){const fieldPath=path?`${path}.${key}`:key;if(UNSAFE_OBJECT_KEYS.has(key)){throw invalidConfig(`Channel field "${fieldPath}" is not manageable.`)}if(containsUnsafeObjectKey(value)){throw invalidConfig(`Channel field "${fieldPath}" cannot use a reserved key.`)}if(Object.hasOwn(previous,key)&&isDeepStrictEqual(previous[key],value)){return}throw invalidConfig(`Channel field "${fieldPath}" is not manageable.`)}__name(assertPreservedUnknownField,"assertPreservedUnknownField");function assertManagedConfig(config,previous,fields){const descriptorFields=new Map(fields.map(field=>[field.key,field]));for(const[key,value]of Object.entries(config)){if(key==="type")continue;const field=descriptorFields.get(key);if(field){assertDescriptorValue(field,value,field.key,Object.hasOwn(previous,key)?previous[key]:void 0);continue}if(assertSharedField(key,value,Object.hasOwn(previous,key)?previous[key]:void 0)){continue}assertPreservedUnknownField(void 0,key,value,previous)}assertRequiredFields(fields,config)}__name(assertManagedConfig,"assertManagedConfig");function validateSecretUpdate(update){if(!isRecord(update)){throw invalidSecret("Secret updates must be objects.")}const operation=update["operation"];const keys=Object.keys(update).sort();const valid=(operation==="preserve"||operation==="clear")&&keys.length===1&&keys[0]==="operation"||operation==="replace"&&keys.length===2&&keys[0]==="operation"&&keys[1]==="value"&&typeof update["value"]==="string"&&update["value"].length>0;if(!valid){throw invalidSecret("Secret updates contain an invalid operation.")}}__name(validateSecretUpdate,"validateSecretUpdate");function assertValidChannelSecretUpdates(updates){if(!isRecord(updates)){throw invalidSecret("Secret updates must be objects.")}for(const[key,update]of Object.entries(updates)){if(UNSAFE_OBJECT_KEYS.has(key)){throw invalidSecret(`Secret update ${JSON.stringify(key)} is invalid.`)}validateSecretUpdate(update)}}__name(assertValidChannelSecretUpdates,"assertValidChannelSecretUpdates");function channelSettingsScope(workspaceCwd){const loaded=loadSettings(workspaceCwd,{skipLoadEnvironment:true});return loaded.workspaceSettingsActive?loaded.workspace:loaded.user}__name(channelSettingsScope,"channelSettingsScope");function channelRecordMap(value){const rawChannels=isRecord(value)?value:{};const channels={};for(const[name,config]of Object.entries(rawChannels)){if(UNSAFE_OBJECT_KEYS.has(name))continue;if(isRecord(config))channels[name]=config}return channels}__name(channelRecordMap,"channelRecordMap");function snapshotFrom(values){return{revision:revisionOf(values.channels,values.startupNames),channels:{...values.channels},startupNames:[...values.startupNames]}}__name(snapshotFrom,"snapshotFrom");function workspaceValues(workspaceCwd){const scope=channelSettingsScope(workspaceCwd);const settings=scope.settings;const startupNames=Array.isArray(settings.serve?.channels)?settings.serve.channels.filter(name=>typeof name==="string"):[];return{channels:channelRecordMap(settings.channels),storedChannels:channelRecordMap(scope.originalSettings.channels),startupNames}}__name(workspaceValues,"workspaceValues");var WorkspaceChannelSettingsStore=class{constructor(workspaceCwd){this.workspaceCwd=workspaceCwd}static{__name(this,"WorkspaceChannelSettingsStore")}snapshot(){return snapshotFrom(workspaceValues(this.workspaceCwd))}async upsert(name,options){assertUpsertChannelName(name);const secretUpdates=options.secrets===void 0?{}:options.secrets;assertValidChannelSecretUpdates(secretUpdates);const plugin=await getPlugin(options.config.type);if(!plugin?.management){throw new ChannelSettingsError("channel_settings_unmanageable",`Channel type "${options.config.type}" does not provide safe management metadata.`)}const secretKeys=new Set(plugin.management.fields.filter(field=>field.kind==="secret").map(field=>field.key));const envResolvableKeys=new Set(plugin.management.fields.filter(field=>field.envResolvable).map(field=>field.key));for(const key of Object.keys(secretUpdates)){if(!secretKeys.has(key)){throw invalidSecret(`Channel type "${options.config.type}" does not declare "${key}" as a secret.`)}}for(const key of secretKeys){if(Object.hasOwn(options.config,key)){throw invalidSecret(`Secret "${key}" must use an explicit preserve, replace, or clear operation.`)}}const{current,storedChannels}=this.assertRevision(options.expectedRevision);const storedPrevious=current.channels[name]??{};const hasPreviousOfType=storedPrevious["type"]===options.config.type;const previous=hasPreviousOfType?storedPrevious:{};const storedOnDisk=storedChannels[name]??{};const previousOnDisk=hasPreviousOfType?storedOnDisk:{};const nextConfig={...options.config};const storedReferences={};for(const key of secretKeys){const update=secretUpdates[key]??{operation:"preserve"};const value=applySecretUpdate(previous[key],update);if(value!==void 0)nextConfig[key]=value;if(update.operation==="preserve"&&previousOnDisk[key]!==void 0&&envResolvableKeys.has(key)){storedReferences[key]=previousOnDisk[key]}}for(const field of plugin.management.fields){const key=field.key;if(!field.envResolvable||secretKeys.has(key))continue;const onDisk=previousOnDisk[key];if(typeof onDisk!=="string"||!isEnvironmentReference(onDisk)){continue}if(nextConfig[key]!==previous[key])continue;storedReferences[key]=onDisk}try{parseChannelOutputMode(name,nextConfig["outputMode"],plugin.supportsOutputMode===true)}catch(error){throw invalidConfig(error instanceof Error?error.message:String(error))}assertManagedConfig(nextConfig,previous,plugin.supportsOutputMode===true?[...plugin.management.fields,CHANNEL_OUTPUT_MODE_FIELD]:plugin.management.fields);const multiSessionError=multiSessionCompatibilityError(name,{multiSession:nextConfig["multiSession"]===true,sessionRotation:parseSessionRotationConfig(name,nextConfig["sessionRotation"]),sessionScope:nextConfig["sessionScope"]??plugin.defaultSessionScope??"user",groupHistoryLimit:nextConfig["groupHistoryLimit"],groups:isRecord(nextConfig["groups"])?nextConfig["groups"]:{},webhooks:nextConfig["webhooks"]});if(multiSessionError)throw invalidConfig(multiSessionError);try{const routing=parseMessageRoutingConfig(name,nextConfig);if(routing.messageRoutes!==void 0)nextConfig["messageRoutes"]=routing.messageRoutes;if(routing.defaultMessageRoute!==void 0)nextConfig["defaultMessageRoute"]=routing.defaultMessageRoute}catch(error){throw invalidConfig(error instanceof Error?error.message:String(error))}let crossFieldError;try{crossFieldError=plugin.management.validateConfig?.(nextConfig);if(crossFieldError instanceof Promise){void crossFieldError.catch(()=>{})}}catch(error){throw invalidConfig(`Channel validateConfig failed: ${error instanceof Error?error.message:String(error)}`)}if(crossFieldError!==void 0){throw invalidConfig(typeof crossFieldError==="string"?crossFieldError:"Channel validateConfig must return a string error message.")}const channels={...storedChannels,[name]:{...nextConfig,...storedReferences}};saveSettings(channelSettingsScope(this.workspaceCwd),{channels},["channels"],{throwOnWriteFailure:true});return this.snapshot()}async remove(name,options){assertSafeChannelName(name);const{current,storedChannels}=this.assertRevision(options.expectedRevision);const configured=Object.hasOwn(current.channels,name);if(!configured){if(!current.startupNames.includes(name))return current;saveSettings(channelSettingsScope(this.workspaceCwd),{serve:{channels:current.startupNames.filter(startupName=>startupName!==name)}},["serve","channels"],{throwOnWriteFailure:true});return this.snapshot()}const channels={...storedChannels};delete channels[name];const hasAllSentinel=current.startupNames.some(isAllStartupName);const startupNames=hasAllSentinel?Object.keys(channels).some(channelName=>!isAllStartupName(channelName))?["all"]:[]:current.startupNames.filter(startupName=>startupName!==name);saveSettings(channelSettingsScope(this.workspaceCwd),{channels,serve:{channels:startupNames}},["channels"],{throwOnWriteFailure:true});return this.snapshot()}async setStartupNames(names,options){for(const name of names){assertSafeChannelName(name)}this.assertRevision(options.expectedRevision);saveSettings(channelSettingsScope(this.workspaceCwd),{serve:{channels:[...names]}},["serve","channels"],{throwOnWriteFailure:true});return this.snapshot()}assertRevision(expectedRevision){const values=workspaceValues(this.workspaceCwd);const current=snapshotFrom(values);if(current.revision!==expectedRevision){throw new ChannelSettingsError("channel_settings_conflict","Channel settings changed; reload before trying again.")}return{current,storedChannels:values.storedChannels}}};export{ChannelSettingsError,assertValidChannelSecretUpdates,WorkspaceChannelSettingsStore};
|
|
4
4
|
/**
|
|
5
5
|
* @license
|
|
6
6
|
* Copyright 2025 Qwen Team
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Force strict mode and setup for ESM
|
|
2
2
|
"use strict";
|
|
3
|
-
import{buildScheduledTaskRunPrompt,parseChannelDelivery,scheduledTaskRunSessionName,scheduledTaskRunSourceId}from"./chunk-7JT34VGK.js";import{createSessionOrganizationService}from"./chunk-SPWDYRDH.js";import{requireTrustedWorkspaceRuntime,resolveWorkspaceRuntimeWithLiveCompatibilityFromParam,sendConversationRuntimeUnavailable,sendGenerationClosedError}from"./chunk-I5LKOTZT.js";import{parseCallerSuppliedSessionId}from"./chunk-LGFF5PJA.js";import{SCHEDULED_TASK_RUN_SOURCE_TYPE}from"./chunk-4QIFOIBS.js";import{SessionNotFoundError}from"./chunk-VTZZXEWA.js";import{isChannelDeliveryError}from"./chunk-O6ZQAVRG.js";import{SessionService}from"./chunk-RKPHDO42.js";import{stripTerminalControlSequences}from"./chunk-R2EHHA2C.js";import{MAX_JOBS,nextDurableFireMs}from"./chunk-57RLZJ6C.js";import{nextFireTime,parseCron}from"./chunk-EOMQENJY.js";import{MAX_CRON_TASK_ROUTING_ID_LENGTH,annotateCronRunSession,appendCronRun,cronTaskSessionDeletionId,generateCronTaskId,getCronFilePath,isValidCronTaskRoutingId,readCronTasks,taskHasLegacyCondition,updateCronTasks}from"./chunk-VMQO3VPA.js";import{writeStderrLine}from"./chunk-SLPJ4OII.js";import{Storage}from"./chunk-EPODBRBP.js";import{init_esbuild_shims}from"./chunk-VKDAXTCZ.js";import{__name}from"./chunk-KBWJGX7I.js";init_esbuild_shims();import{isDeepStrictEqual}from"node:util";import{access}from"node:fs/promises";var MAX_SCHEDULED_TASKS=MAX_JOBS;var MAX_PROMPT_LENGTH=1e5;var MAX_NAME_LENGTH=200;var MAX_CRON_LENGTH=200;var MAX_ROUTING_ID_LENGTH=MAX_CRON_TASK_ROUTING_ID_LENGTH;var MAX_SESSION_NAME_LENGTH=60;function scheduledTaskSessionName(label){const cleaned=stripTerminalControlSequences(label).replace(/[\u061c\u200e\u200f\u202a-\u202e\u2066-\u2069]/g,"").trim().replace(/\s+/g," ");let short=cleaned;if(cleaned.length>MAX_SESSION_NAME_LENGTH){let cut=MAX_SESSION_NAME_LENGTH-1;const boundary=cleaned.charCodeAt(cut-1);if(boundary>=55296&&boundary<=56319)cut-=1;short=`${cleaned.slice(0,cut)}\u2026`}return short}__name(scheduledTaskSessionName,"scheduledTaskSessionName");var ExistingSessionScheduledTaskCreateError=class extends Error{constructor(status,code,message){super(message);this.status=status;this.code=code;this.name="ExistingSessionScheduledTaskCreateError"}static{__name(this,"ExistingSessionScheduledTaskCreateError")}};function assertReusableScheduledTaskSession(target,sessionId,allowActivePrompt,assertCallerPromptActive){const{bridge,workspaceCwd}=target;if(!bridge){throw new ExistingSessionScheduledTaskCreateError(409,"session_binding_unavailable","Session management is not available for this workspace")}assertCallerPromptActive?.();let owner;try{owner=target.resolveLiveSessionOwner?.(sessionId)}catch(error){writeStderrLine(`qwen serve: failed to resolve scheduled-task session owner '${sessionId}': ${error instanceof Error?error.message:String(error)}`);throw new ExistingSessionScheduledTaskCreateError(500,"scheduled_tasks_session_failed","Failed to look up the requested session")}if(owner?.kind==="unavailable"){throw new ExistingSessionScheduledTaskCreateError(503,"workspace_runtime_unavailable","The workspace runtime is unavailable")}if(owner?.kind==="ambiguous"){throw new ExistingSessionScheduledTaskCreateError(500,"ambiguous_session_owner",`Session owner is ambiguous for "${sessionId}"`)}if(owner?.kind==="found"&&owner.runtime.workspaceCwd!==workspaceCwd){throw new ExistingSessionScheduledTaskCreateError(400,"session_workspace_mismatch","The requested session belongs to a different workspace; use that workspace's scheduled-task endpoint")}let summary;try{summary=bridge.getSessionSummary(sessionId)}catch(error){if(error instanceof SessionNotFoundError){throw new ExistingSessionScheduledTaskCreateError(404,"session_not_found",`Session '${sessionId}' was not found`)}writeStderrLine(`qwen serve: failed to look up scheduled-task session '${sessionId}': ${error instanceof Error?error.message:String(error)}`);throw new ExistingSessionScheduledTaskCreateError(500,"scheduled_tasks_session_failed","Failed to look up the requested session")}if(summary.workspaceCwd!==workspaceCwd){throw new ExistingSessionScheduledTaskCreateError(400,"session_workspace_mismatch","The requested session belongs to a different workspace; use that workspace's scheduled-task endpoint")}if(!allowActivePrompt&&summary.hasActivePrompt||(summary.pendingInteractionCount??0)>0){throw new ExistingSessionScheduledTaskCreateError(409,"session_busy",allowActivePrompt?"The caller session has a pending interaction; resolve it before binding the session to a task":"The requested session is busy; wait for its active prompt or pending interaction to finish before binding it to a task")}if(summary.sourceType==="scheduled_task"){throw new ExistingSessionScheduledTaskCreateError(409,"session_already_bound","The requested session is already reserved for a scheduled task")}if(summary.parentSessionId!==void 0||summary.sourceId!==void 0||summary.sourceType!==void 0&&summary.sourceType!=="default"){throw new ExistingSessionScheduledTaskCreateError(409,"session_source_ineligible","The requested session source cannot own a scheduled task")}}__name(assertReusableScheduledTaskSession,"assertReusableScheduledTaskSession");async function createScheduledTaskWithExistingSession(target,input,options){if(input.cron.length===0||input.cron.length>MAX_CRON_LENGTH||validateCron(input.cron)!==null){throw new ExistingSessionScheduledTaskCreateError(400,"invalid_cron","The scheduled-task cron expression is invalid")}const prompt=input.prompt.trim();if(prompt.length===0||prompt.length>MAX_PROMPT_LENGTH){throw new ExistingSessionScheduledTaskCreateError(400,"invalid_prompt","The scheduled-task prompt is invalid")}const allowActivePrompt=options.source==="cron-tool";const assertCallerPromptActive=options.source==="cron-tool"?options.assertCallerPromptActive:void 0;assertReusableScheduledTaskSession(target,input.sessionId,allowActivePrompt,assertCallerPromptActive);target.assertGenerationOpen?.();if(options.source==="rest"){const ensurePersisted=target.bridge?.ensureDefaultSessionPersisted;if(!ensurePersisted){throw new ExistingSessionScheduledTaskCreateError(409,"session_binding_unavailable","Session persistence is not available for this workspace")}try{await ensurePersisted.call(target.bridge,input.sessionId)}catch(error){target.assertGenerationOpen?.();if(error instanceof SessionNotFoundError){throw new ExistingSessionScheduledTaskCreateError(404,"session_not_found",`Session '${input.sessionId}' was not found`)}writeStderrLine(`qwen serve: failed to persist scheduled-task session '${input.sessionId}': ${error instanceof Error?error.message:String(error)}`);throw new ExistingSessionScheduledTaskCreateError(500,"session_persistence_failed","Failed to persist the requested session")}target.assertGenerationOpen?.()}const now=Date.now();const task={id:generateCronTaskId(),cron:input.cron,prompt,recurring:input.recurring,createdAt:now,lastFiredAt:now-now%6e4,enabled:input.enabled!==false,sessionId:input.sessionId,sessionOwnedByTask:false,sessionMode:input.sessionMode==="per_run"?"per_run":"persistent",...input.sessionMode==="per_run"&&input.modelServiceId!==void 0?{modelServiceId:input.modelServiceId}:{},...input.sessionMode==="per_run"&&input.groupId!==void 0?{groupId:input.groupId}:{},...input.delivery!==void 0?{delivery:input.delivery}:{},...input.name!==void 0?{name:input.name}:{}};let before;let after;await runWithScheduledTaskTarget(target,()=>updateCronTasks(target.workspaceCwd,tasks=>{assertReusableScheduledTaskSession(target,input.sessionId,allowActivePrompt,assertCallerPromptActive);if(tasks.some(candidate=>candidate.sessionId===input.sessionId)){throw new ExistingSessionScheduledTaskCreateError(409,"session_already_bound","The requested session is already bound to another scheduled task")}if(tasks.length>=MAX_SCHEDULED_TASKS){throw new ExistingSessionScheduledTaskCreateError(409,"max_tasks_reached",`Maximum number of scheduled tasks (${MAX_SCHEDULED_TASKS}) reached`)}before=tasks;after=[...tasks,task];return after},{assertCanCommit:target.assertGenerationOpen}));try{target.assertGenerationOpen?.()}catch(error){await rollbackCronMutation(target,before,after,"scheduled-task create");throw error}return task}__name(createScheduledTaskWithExistingSession,"createScheduledTaskWithExistingSession");function requireOpenGeneration(target,res){try{target.assertGenerationOpen?.();return true}catch(error){if(sendGenerationClosedError(res,error))return false;throw error}}__name(requireOpenGeneration,"requireOpenGeneration");async function rollbackCronMutation(target,before,after,route){if(!before||!after)return;await runWithScheduledTaskTarget(target,()=>updateCronTasks(target.workspaceCwd,tasks=>isDeepStrictEqual(tasks,after)?before:tasks)).catch(error=>{writeStderrLine(`qwen serve: ${route} failed to roll back a stale task mutation: ${error instanceof Error?error.message:String(error)}`)})}__name(rollbackCronMutation,"rollbackCronMutation");async function restoreConsumedOneShot(target,before,failedTask,removalGenerations,route){const id=failedTask.id;const index=before?.findIndex(t=>t.id===id)??-1;const original=index===-1?void 0:before[index];if(!original||!removalGenerations)return;let restoreGenerations;await runWithScheduledTaskTarget(target,()=>updateCronTasks(target.workspaceCwd,tasks=>{if([...removalGenerations].some(([key,generation])=>restoreGenerations?.get(key)!==generation))return tasks;if(tasks.some(t=>t.id===id))return tasks;const restored=[...tasks];restored.splice(Math.min(index,restored.length),0,{...failedTask,enabled:false});return restored},{observeDeletionIds:[...removalGenerations.keys()],onDeletionGenerations:__name(generations=>{restoreGenerations=generations},"onDeletionGenerations")})).catch(error=>{writeStderrLine(`qwen serve: ${route} failed to restore the consumed one-shot task: ${error instanceof Error?error.message:String(error)}`)})}__name(restoreConsumedOneShot,"restoreConsumedOneShot");async function teardownBoundSession(target,sessionId){if(target.cleanupSession){await target.cleanupSession(sessionId).catch(()=>{})}else if(target.bridge){await target.bridge.closeSession(sessionId).catch(()=>{});const removed=await new SessionService(target.workspaceCwd,{runtimeBaseDir:target.runtimeBaseDir}).removeSession(sessionId).catch(()=>false);if(removed)target.bridge.markSessionCatalogChanged?.()}}__name(teardownBoundSession,"teardownBoundSession");async function dispatchTaskToFreshSession(target,task){const{bridge}=target;const sendPrompt=bridge?.sendPrompt?.bind(bridge);if(!bridge||!sendPrompt||!task.sessionId){throw new Error("Fresh-session dispatch is unavailable for this task")}const triggeredAt=task.lastFiredAt??Date.now();const child=await runWithScheduledTaskTarget(target,()=>bridge.spawnOrAttach({workspaceCwd:target.workspaceCwd,...task.modelServiceId?{modelServiceId:task.modelServiceId}:{},sessionScope:"thread",parentSessionId:task.sessionId,sourceType:SCHEDULED_TASK_RUN_SOURCE_TYPE,sourceId:scheduledTaskRunSourceId(task.id)}));try{if(task.modelServiceId&&child.modelApplied===false){throw new Error(`Scheduled task model selection failed: ${task.modelServiceId}`)}try{bridge.updateSessionMetadata(child.sessionId,{displayName:scheduledTaskRunSessionName(task.name??task.prompt,triggeredAt),titleSource:"auto"})}catch{}let markPromptAdmitted;const promptAdmitted=new Promise(resolve=>{markPromptAdmitted=resolve});const turn=sendPrompt(child.sessionId,{sessionId:child.sessionId,prompt:[{type:"text",text:buildScheduledTaskRunPrompt({id:task.id,name:task.name,cron:task.cron,prompt:task.prompt,triggeredAt,trigger:"manual"})}]},void 0,{onPromptAdmitted:markPromptAdmitted});void turn.catch(error=>{writeStderrLine(`qwen serve: scheduled-task session ${child.sessionId} prompt failed: ${error instanceof Error?error.message:String(error)}`)});await Promise.race([promptAdmitted,turn.then(()=>void 0,error=>Promise.reject(error))]);if(task.groupId){try{await runWithScheduledTaskTarget(target,()=>createSessionOrganizationService(target.workspaceCwd).updateSessionOrganization(child.sessionId,{groupId:task.groupId,color:null}));bridge.markSessionCatalogChanged?.()}catch(error){writeStderrLine(`qwen serve: scheduled-task session ${child.sessionId} could not be assigned to group ${task.groupId}: ${error instanceof Error?error.message:String(error)}`)}}}catch(error){await teardownBoundSession(target,child.sessionId);throw error}return child.sessionId}__name(dispatchTaskToFreshSession,"dispatchTaskToFreshSession");async function runWithScheduledTaskTarget(target,fn){const result=target.runtimeBaseDir===void 0?fn():Storage.runWithResolvedRuntimeBaseDir(target.runtimeBaseDir,fn);return await result}__name(runWithScheduledTaskTarget,"runWithScheduledTaskTarget");function sendActivityGateError(res,error){if(!error||typeof error!=="object"||error.code!=="daemon_draining"){return false}res.status(503).json({error:"The daemon is draining and no longer accepts work.",code:"daemon_draining"});return true}__name(sendActivityGateError,"sendActivityGateError");function computeNextRunAt(task){if(task.enabled===false)return null;return nextDurableFireMs(task)}__name(computeNextRunAt,"computeNextRunAt");function toView(task){return{id:task.id,name:typeof task.name==="string"&&task.name.length>0?task.name:null,cron:task.cron,prompt:task.prompt,recurring:task.recurring,enabled:task.enabled!==false&&!taskHasLegacyCondition(task),createdAt:task.createdAt,lastFiredAt:task.lastFiredAt,nextRunAt:taskHasLegacyCondition(task)?null:computeNextRunAt(task),sessionId:typeof task.sessionId==="string"&&task.sessionId.length>0?task.sessionId:null,sessionMode:task.sessionMode==="per_run"?"per_run":"persistent",modelServiceId:task.modelServiceId??null,groupId:task.groupId??null,runs:Array.isArray(task.runs)?task.runs:[],...task.delivery!==void 0?{delivery:task.delivery}:{}}}__name(toView,"toView");function validateCron(cron){try{parseCron(cron);nextFireTime(cron,new Date);return null}catch(err){return err instanceof Error?err.message:String(err)}}__name(validateCron,"validateCron");function canonicalCron(cron){try{const f=parseCron(cron);const s=__name(set=>[...set].sort((a,b)=>a-b).join(","),"s");return[s(f.minute),s(f.hour),s(f.dayOfMonth),s(f.month),s(f.dayOfWeek),f.domIsWild?"W":"",f.dowIsWild?"W":""].join("|")}catch{return null}}__name(canonicalCron,"canonicalCron");function registerScheduledTaskCrudRoutes(app,deps){const{prefix,resolveTarget,mutate,safeBody,channelDeliveryAuthorizations}=deps;const base=`${prefix}/scheduled-tasks`;const withTarget=__name(handler=>async(req,res)=>{const target=resolveTarget(req,res);if(!target)return;const operation=__name(async()=>{if(!requireOpenGeneration(target,res))return;await handler(req,res,target)},"operation");try{if(target.activity){await target.activity.run(operation)}else{await operation()}}catch(error){if(sendActivityGateError(res,error))return;throw error}},"withTarget");app.get(base,withTarget(async(_req,res,target)=>{try{const tasks=await runWithScheduledTaskTarget(target,()=>readCronTasks(target.workspaceCwd));if(!requireOpenGeneration(target,res))return;res.status(200).json({v:1,tasks:tasks.map(toView)})}catch(err){if(sendActivityGateError(res,err))return;writeStderrLine(`qwen serve: GET ${base} failed: ${err instanceof Error?err.message:String(err)}`);res.status(500).json({error:"Failed to read scheduled tasks (the tasks file may be corrupt)",code:"scheduled_tasks_read_failed"})}}));app.post(base,mutate(),withTarget(async(req,res,target)=>{const{workspaceCwd,bridge}=target;const body=safeBody(req);const cron=typeof body["cron"]==="string"?body["cron"].trim():"";if(cron.length===0){res.status(400).json({error:"`cron` is required and must be a non-empty string",code:"invalid_cron"});return}if(cron.length>MAX_CRON_LENGTH){res.status(400).json({error:`\`cron\` exceeds ${MAX_CRON_LENGTH}-character limit`,code:"invalid_cron"});return}const cronError=validateCron(cron);if(cronError){res.status(400).json({error:cronError,code:"invalid_cron"});return}const prompt=typeof body["prompt"]==="string"?body["prompt"].trim():"";if(prompt.length===0){res.status(400).json({error:"`prompt` is required and must be a non-empty string",code:"invalid_prompt"});return}if(prompt.length>MAX_PROMPT_LENGTH){res.status(400).json({error:`\`prompt\` exceeds ${MAX_PROMPT_LENGTH}-character limit`,code:"invalid_prompt"});return}const nameResult=parseNameField(body["name"]);if(nameResult.error){res.status(400).json({error:nameResult.error,code:"invalid_name"});return}if(body["recurring"]!==void 0&&typeof body["recurring"]!=="boolean"){res.status(400).json({error:"`recurring` must be a boolean",code:"invalid_recurring"});return}if(body["enabled"]!==void 0&&typeof body["enabled"]!=="boolean"){res.status(400).json({error:"`enabled` must be a boolean",code:"invalid_enabled"});return}const sessionMode=body["sessionMode"]===void 0?"persistent":body["sessionMode"];if(sessionMode!=="persistent"&&sessionMode!=="per_run"){res.status(400).json({error:'`sessionMode` must be "persistent" or "per_run"',code:"invalid_session_mode"});return}const modelServiceId=body["modelServiceId"];if(modelServiceId!==void 0&&!isValidCronTaskRoutingId(modelServiceId)){res.status(400).json({error:`\`modelServiceId\` must be a non-empty string of at most ${MAX_ROUTING_ID_LENGTH} characters without control characters`,code:"invalid_model_service_id"});return}const groupId=body["groupId"];if(groupId!==void 0&&!isValidCronTaskRoutingId(groupId)){res.status(400).json({error:`\`groupId\` must be a non-empty string of at most ${MAX_ROUTING_ID_LENGTH} characters without control characters`,code:"invalid_group_id"});return}if(sessionMode!=="per_run"&&(modelServiceId!==void 0||groupId!==void 0)){res.status(400).json({error:'`modelServiceId` and `groupId` are only supported when `sessionMode` is "per_run"',code:"session_routing_requires_per_run"});return}if(typeof groupId==="string"){const groups=await runWithScheduledTaskTarget(target,()=>createSessionOrganizationService(workspaceCwd).listGroups());if(!groups.groups.some(group=>group.id===groupId)){res.status(400).json({error:`Group not found: ${groupId}`,code:"group_not_found"});return}}const parsedSessionId=parseCallerSuppliedSessionId(body["sessionId"]);if(parsedSessionId.kind==="invalid"){res.status(400).json({error:'`sessionId` must be an RFC UUID v1-v5 (e.g. "550e8400-e29b-41d4-a716-446655440000")',code:"invalid_session_id"});return}const providedSessionId=parsedSessionId.kind==="valid"?parsedSessionId.sessionId:void 0;let delivery;if(body["delivery"]!==void 0){try{delivery=parseChannelDelivery(body["delivery"])}catch(err){if(!isChannelDeliveryError(err))throw err;res.status(400).json({error:err.message,code:err.code});return}}if(sessionMode==="per_run"&&delivery!==void 0){res.status(400).json({error:"Per-run sessions do not support channel delivery",code:"session_mode_delivery_unsupported"});return}const removedField=findRemovedTaskField(body);if(removedField){res.status(400).json(removedFieldError(removedField));return}const recurring=body["recurring"]!==false;const enabled=body["enabled"]!==false;const taskId=generateCronTaskId();if(sessionMode==="per_run"&&(!bridge||!bridge.sendPrompt)){res.status(409).json({error:"Fresh-session dispatch is not available for this workspace",code:"session_mode_unavailable"});return}if(providedSessionId!==void 0){try{const task2=await createScheduledTaskWithExistingSession(target,{sessionId:providedSessionId,cron,prompt,recurring,enabled,sessionMode,...typeof modelServiceId==="string"?{modelServiceId}:{},...typeof groupId==="string"?{groupId}:{},...delivery!==void 0?{delivery}:{},...nameResult.value!==void 0?{name:nameResult.value}:{}},{source:"rest"});if(task2.delivery&&task2.sessionId){channelDeliveryAuthorizations?.registerScheduledTask(workspaceCwd,{sessionId:task2.sessionId,taskId:task2.id,target:task2.delivery.target,recurring:task2.recurring,lastFiredAt:task2.lastFiredAt??void 0})}res.status(201).json(toView(task2))}catch(error){if(error instanceof ExistingSessionScheduledTaskCreateError){if(error.code==="workspace_runtime_unavailable"){res.set("Retry-After","1")}res.status(error.status).json({error:error.message,code:error.code});return}if(sendActivityGateError(res,error))return;if(sendGenerationClosedError(res,error))return;writeStderrLine(`qwen serve: POST ${base} failed to create a task for session '${providedSessionId}': ${error instanceof Error?error.message:String(error)}`);res.status(500).json({error:"Failed to create scheduled task",code:"scheduled_tasks_write_failed"})}return}let boundSessionId;let sessionMintedHere=false;if(bridge){try{const tasks=await runWithScheduledTaskTarget(target,()=>readCronTasks(workspaceCwd));if(tasks.length>=MAX_SCHEDULED_TASKS){res.status(409).json({error:`Maximum number of scheduled tasks (${MAX_SCHEDULED_TASKS}) reached`,code:"max_tasks_reached"});return}}catch{}if(!requireOpenGeneration(target,res))return;try{const session=await runWithScheduledTaskTarget(target,()=>bridge.spawnOrAttach({workspaceCwd,sessionScope:"thread",sourceType:"scheduled_task",sourceId:taskId}));boundSessionId=session.sessionId;sessionMintedHere=true;if(!requireOpenGeneration(target,res)){await teardownBoundSession(target,boundSessionId);return}try{await runWithScheduledTaskTarget(target,async()=>bridge.updateSessionMetadata(boundSessionId,{displayName:scheduledTaskSessionName(nameResult.value??prompt),titleSource:"auto"}))}catch{}}catch(err){if(sendActivityGateError(res,err))return;if(sendGenerationClosedError(res,err))return;writeStderrLine(`qwen serve: POST ${base} failed to create the task's session: ${err instanceof Error?err.message:String(err)}`);res.status(500).json({error:"Failed to create the task's session",code:"scheduled_tasks_session_failed"});return}}const now=Date.now();const task={id:taskId,cron,prompt,recurring,createdAt:now,lastFiredAt:now-now%6e4,enabled,sessionMode,...typeof modelServiceId==="string"?{modelServiceId}:{},...typeof groupId==="string"?{groupId}:{},...delivery!==void 0?{delivery}:{},...boundSessionId!==void 0?{sessionId:boundSessionId}:{},...nameResult.value!==void 0?{name:nameResult.value}:{}};const rollbackSession=__name(async()=>{if(boundSessionId!==void 0&&sessionMintedHere){await teardownBoundSession(target,boundSessionId)}},"rollbackSession");let overCap=false;let rollbackBefore;let rollbackAfter;try{await runWithScheduledTaskTarget(target,()=>updateCronTasks(workspaceCwd,tasks=>{if(tasks.length>=MAX_SCHEDULED_TASKS){overCap=true;return tasks}rollbackBefore=tasks;rollbackAfter=[...tasks,task];return rollbackAfter},{assertCanCommit:target.assertGenerationOpen}))}catch(err){await rollbackSession();if(sendActivityGateError(res,err))return;if(sendGenerationClosedError(res,err))return;writeStderrLine(`qwen serve: POST ${base} failed: ${err instanceof Error?err.message:String(err)}`);res.status(500).json({error:"Failed to create scheduled task",code:"scheduled_tasks_write_failed"});return}if(rollbackBefore&&rollbackAfter){try{target.assertGenerationOpen?.()}catch(error){await rollbackCronMutation(target,rollbackBefore,rollbackAfter,`POST ${base}`);await rollbackSession();if(sendGenerationClosedError(res,error))return;throw error}}if(overCap){await rollbackSession();res.status(409).json({error:`Maximum number of scheduled tasks (${MAX_SCHEDULED_TASKS}) reached`,code:"max_tasks_reached"});return}if(task.delivery&&task.sessionId){channelDeliveryAuthorizations?.registerScheduledTask(workspaceCwd,{sessionId:task.sessionId,taskId:task.id,target:task.delivery.target,recurring:task.recurring,lastFiredAt:task.lastFiredAt??void 0})}res.status(201).json(toView(task))}));app.patch(`${base}/:id`,mutate(),withTarget(async(req,res,target)=>{const{workspaceCwd,bridge}=target;const id=typeof req.params["id"]==="string"?req.params["id"]:"";if(id.length===0){res.status(400).json({error:"Task id is required",code:"invalid_id"});return}const body=safeBody(req);const patch={};let clearName=false;let clearDelivery=false;let clearModelServiceId=false;let clearGroupId=false;let missingGroupId;const removedPatchField=findRemovedTaskField(body);if(removedPatchField){res.status(400).json(removedFieldError(removedPatchField));return}if("cron"in body){const cron=typeof body["cron"]==="string"?body["cron"].trim():"";if(cron.length===0||cron.length>MAX_CRON_LENGTH){res.status(400).json({error:"`cron` must be a non-empty string within the length limit",code:"invalid_cron"});return}const cronError=validateCron(cron);if(cronError){res.status(400).json({error:cronError,code:"invalid_cron"});return}patch.cron=cron}if("prompt"in body){const prompt=typeof body["prompt"]==="string"?body["prompt"].trim():"";if(prompt.length===0||prompt.length>MAX_PROMPT_LENGTH){res.status(400).json({error:"`prompt` must be a non-empty string within the length limit",code:"invalid_prompt"});return}patch.prompt=prompt}if("name"in body){const nameResult=parseNameField(body["name"]);if(nameResult.error){res.status(400).json({error:nameResult.error,code:"invalid_name"});return}if(nameResult.value===void 0){clearName=true}else{patch.name=nameResult.value}}if("recurring"in body){if(typeof body["recurring"]!=="boolean"){res.status(400).json({error:"`recurring` must be a boolean",code:"invalid_recurring"});return}patch.recurring=body["recurring"]}if("enabled"in body){if(typeof body["enabled"]!=="boolean"){res.status(400).json({error:"`enabled` must be a boolean",code:"invalid_enabled"});return}patch.enabled=body["enabled"]}if("sessionMode"in body){if(body["sessionMode"]!=="persistent"&&body["sessionMode"]!=="per_run"){res.status(400).json({error:'`sessionMode` must be "persistent" or "per_run"',code:"invalid_session_mode"});return}patch.sessionMode=body["sessionMode"]}if("modelServiceId"in body){const value=body["modelServiceId"];if(value===null||value===""){clearModelServiceId=true}else if(!isValidCronTaskRoutingId(value)){res.status(400).json({error:`\`modelServiceId\` must be null or a non-empty string of at most ${MAX_ROUTING_ID_LENGTH} characters without control characters`,code:"invalid_model_service_id"});return}else{patch.modelServiceId=value}}if("groupId"in body){const value=body["groupId"];if(value===null||value===""){clearGroupId=true}else if(!isValidCronTaskRoutingId(value)){res.status(400).json({error:`\`groupId\` must be null or a non-empty string of at most ${MAX_ROUTING_ID_LENGTH} characters without control characters`,code:"invalid_group_id"});return}else{const groups=await runWithScheduledTaskTarget(target,()=>createSessionOrganizationService(workspaceCwd).listGroups());if(!groups.groups.some(group=>group.id===value)){missingGroupId=value}patch.groupId=value}}if("delivery"in body){if(body["delivery"]===null){clearDelivery=true}else{try{patch.delivery=parseChannelDelivery(body["delivery"])}catch(err){if(!isChannelDeliveryError(err))throw err;res.status(400).json({error:err.message,code:err.code});return}}}if(Object.keys(patch).length===0&&!clearName&&!clearDelivery&&!clearModelServiceId&&!clearGroupId){res.status(400).json({error:"No updatable fields provided",code:"empty_patch"});return}let found=false;let updated;let blockedByArchive=false;let blockedLegacy=false;let blockedSessionModeDelivery=false;let blockedSessionModeUnavailable=false;let blockedSessionModeUnbound=false;let blockedGroupNotFound=false;let rollbackBefore;let rollbackAfter;try{await runWithScheduledTaskTarget(target,()=>updateCronTasks(workspaceCwd,tasks=>{const idx=tasks.findIndex(t=>t.id===id);if(idx===-1)return tasks;found=true;const current=tasks[idx];if(missingGroupId!==void 0&¤t.groupId!==missingGroupId){blockedGroupNotFound=true;return tasks}const convertingToPerRun=patch.sessionMode==="per_run"&¤t.sessionMode!=="per_run";if(convertingToPerRun&&(!bridge||!bridge.sendPrompt)){blockedSessionModeUnavailable=true;return tasks}if(convertingToPerRun&&!current.sessionId){blockedSessionModeUnbound=true;return tasks}if(patch.enabled===true&&taskHasLegacyCondition(current)){blockedLegacy=true;return tasks}if(patch.enabled===true&¤t.disabledByArchive===true){blockedByArchive=true;return tasks}const next={...current,...patch};if(clearName)delete next.name;if(clearDelivery)delete next.delivery;if(clearModelServiceId)delete next.modelServiceId;if(clearGroupId)delete next.groupId;if(next.sessionMode!=="per_run"){delete next.modelServiceId;delete next.groupId}if(next.sessionMode==="per_run"&&next.delivery){blockedSessionModeDelivery=true;return tasks}const justReEnabled=current.enabled===false&&patch.enabled===true;const cronChanged=patch.cron!==void 0&&canonicalCron(patch.cron)!==canonicalCron(current.cron);const becameRecurring=patch.recurring===true&¤t.recurring!==true;const becameOneShot=patch.recurring===false&¤t.recurring!==false;const retryFailedOneShot=!next.recurring&&justReEnabled&&!cronChanged&&!becameOneShot&¤t.runs?.at(-1)?.sessionDispatchFailed===true;{const now=Date.now();const minute=now-now%6e4;if(next.recurring&&(justReEnabled||cronChanged||becameRecurring)){next.lastFiredAt=minute}else if(!next.recurring&&!retryFailedOneShot&&(justReEnabled||cronChanged||becameOneShot)){next.createdAt=now;next.lastFiredAt=minute}}updated=next;rollbackBefore=tasks;rollbackAfter=tasks.map((t,i)=>i===idx?next:t);return rollbackAfter},{assertCanCommit:target.assertGenerationOpen}))}catch(err){if(sendActivityGateError(res,err))return;if(sendGenerationClosedError(res,err))return;writeStderrLine(`qwen serve: PATCH ${base}/${id} failed: ${err instanceof Error?err.message:String(err)}`);res.status(500).json({error:"Failed to update scheduled task",code:"scheduled_tasks_write_failed"});return}if(rollbackBefore&&rollbackAfter){try{target.assertGenerationOpen?.()}catch(error){await rollbackCronMutation(target,rollbackBefore,rollbackAfter,`PATCH ${base}/${id}`);if(sendGenerationClosedError(res,error))return;throw error}}if(!found){res.status(404).json({error:"Task not found",code:"task_not_found"});return}if(missingGroupId!==void 0&&blockedGroupNotFound){res.status(400).json({error:`Group not found: ${missingGroupId}`,code:"group_not_found"});return}if(blockedLegacy){res.status(409).json({error:"This task uses the removed isolated run mode with a precondition and can no longer be enabled or run. Recreate it (and call the `create_sub_session` tool from the prompt if you need per-run isolation).",code:"task_legacy_unsupported"});return}if(blockedByArchive){res.status(409).json({error:"This task was disabled by archiving its session; unarchive the session to re-enable it.",code:"task_session_archived"});return}if(blockedSessionModeUnavailable){res.status(409).json({error:"Fresh-session dispatch is not available for this workspace",code:"session_mode_unavailable"});return}if(blockedSessionModeUnbound){res.status(409).json({error:"This task is not bound to a session yet, so it cannot run in a new session every run. Try again once it has run or been opened at least once.",code:"session_mode_requires_bound_session"});return}if(blockedSessionModeDelivery){res.status(409).json({error:"Per-run sessions do not support channel delivery",code:"session_mode_delivery_unsupported"});return}if(!updated){res.status(404).json({error:"Task not found",code:"task_not_found"});return}const effectiveLabelChanged=patch.name!==void 0||clearName||patch.prompt!==void 0&&updated.name===void 0;if(bridge&&updated.sessionId&&updated.sessionOwnedByTask!==false&&effectiveLabelChanged){try{bridge.updateSessionMetadata(updated.sessionId,{displayName:scheduledTaskSessionName(updated.name??updated.prompt),titleSource:"auto"})}catch{}}if(updated.delivery&&updated.sessionId){channelDeliveryAuthorizations?.registerScheduledTask(workspaceCwd,{sessionId:updated.sessionId,taskId:updated.id,target:updated.delivery.target,recurring:updated.recurring,lastFiredAt:updated.lastFiredAt??void 0})}if(clearDelivery&&updated.sessionId){channelDeliveryAuthorizations?.revokeScheduledTask(workspaceCwd,updated.sessionId,updated.id)}res.status(200).json(toView(updated))}));app.delete(`${base}/:id`,mutate(),withTarget(async(req,res,target)=>{const{workspaceCwd,bridge}=target;const id=typeof req.params["id"]==="string"?req.params["id"]:"";if(id.length===0){res.status(400).json({error:"Task id is required",code:"invalid_id"});return}let boundSessionId;let sessionOwnedByTask=true;let removed=false;let rollbackBefore;let rollbackAfter;try{await runWithScheduledTaskTarget(target,async()=>{try{await access(getCronFilePath(workspaceCwd))}catch(error){if(error.code==="ENOENT")return;throw error}await updateCronTasks(workspaceCwd,tasks=>{const idx=tasks.findIndex(t=>t.id===id);if(idx===-1)return tasks;const match=tasks[idx].sessionId;if(typeof match==="string"&&match.length>0){boundSessionId=match;sessionOwnedByTask=tasks[idx].sessionOwnedByTask!==false}removed=true;rollbackBefore=tasks;rollbackAfter=tasks.filter((_,i)=>i!==idx);return rollbackAfter},{assertCanCommit:target.assertGenerationOpen,deletionIds:[id]})})}catch(err){if(sendActivityGateError(res,err))return;if(sendGenerationClosedError(res,err))return;writeStderrLine(`qwen serve: DELETE ${base}/${id} failed: ${err instanceof Error?err.message:String(err)}`);res.status(500).json({error:"Failed to delete scheduled task",code:"scheduled_tasks_write_failed"});return}if(rollbackBefore&&rollbackAfter){try{target.assertGenerationOpen?.()}catch(error){await rollbackCronMutation(target,rollbackBefore,rollbackAfter,`DELETE ${base}/${id}`);if(sendGenerationClosedError(res,error))return;throw error}}if(!removed){res.status(404).json({error:"Task not found",code:"task_not_found"});return}if(boundSessionId&&sessionOwnedByTask&&bridge){try{await runWithScheduledTaskTarget(target,()=>bridge.closeSession(boundSessionId,void 0,{closeIfUnheld:true,reason:"scheduled_task_deleted"}))}catch(error){if(sendActivityGateError(res,error))return}}if(boundSessionId){channelDeliveryAuthorizations?.revokeScheduledTask(workspaceCwd,boundSessionId,id)}res.status(200).json({deleted:true,id})}));app.post(`${base}/:id/run`,mutate(),withTarget(async(req,res,target)=>{const{workspaceCwd}=target;const id=typeof req.params["id"]==="string"?req.params["id"]:"";if(id.length===0){res.status(400).json({error:"Task id is required",code:"invalid_id"});return}const now=Date.now();let found=false;let blockedDisabled=false;let blockedLegacy=false;let updated;let rollbackBefore;let rollbackAfter;let removalGenerations;try{await runWithScheduledTaskTarget(target,()=>updateCronTasks(workspaceCwd,tasks=>{const idx=tasks.findIndex(t=>t.id===id);if(idx===-1)return tasks;found=true;const current=tasks[idx];if(taskHasLegacyCondition(current)){blockedLegacy=true;return tasks}if(current.enabled===false){blockedDisabled=true;return tasks}const next={...current,lastFiredAt:now,runs:appendCronRun(current.runs,{at:now,kind:"manual",...current.sessionMode!=="per_run"&¤t.sessionId?{sessionId:current.sessionId}:{}})};updated=next;rollbackBefore=tasks;const nextTasks=!current.recurring?tasks.filter((_,i)=>i!==idx):tasks.map((t,i)=>i===idx?next:t);rollbackAfter=nextTasks;return nextTasks},{assertCanCommit:target.assertGenerationOpen,observeDeletionIds:__name(tasks=>{const task=tasks.find(task2=>task2.id===id);return task?.sessionId?[id,cronTaskSessionDeletionId(task.sessionId)]:[id]},"observeDeletionIds"),onDeletionGenerations:__name(generations=>{removalGenerations=generations},"onDeletionGenerations")}))}catch(err){if(sendActivityGateError(res,err))return;if(sendGenerationClosedError(res,err))return;writeStderrLine(`qwen serve: POST ${base}/${id}/run failed: ${err instanceof Error?err.message:String(err)}`);res.status(500).json({error:"Failed to record scheduled task run",code:"scheduled_tasks_write_failed"});return}if(rollbackBefore&&rollbackAfter){try{target.assertGenerationOpen?.()}catch(error){await rollbackCronMutation(target,rollbackBefore,rollbackAfter,`POST ${base}/${id}/run`);if(sendGenerationClosedError(res,error))return;throw error}}if(blockedLegacy){res.status(409).json({error:"This task uses the removed isolated run mode with a precondition and can no longer run. Recreate it (and call the `create_sub_session` tool from the prompt if you need per-run isolation).",code:"task_legacy_unsupported"});return}if(blockedDisabled){res.status(409).json({error:"Cannot run a disabled task; enable it first (unarchive its session if it was archived).",code:"task_disabled"});return}if(!found||!updated){res.status(404).json({error:"Task not found",code:"task_not_found"});return}if(updated.sessionMode==="per_run"){const persistOutcome=__name(async outcome=>{if(!updated.recurring)return;await runWithScheduledTaskTarget(target,()=>updateCronTasks(workspaceCwd,tasks=>tasks.map(task=>task.id===id?annotateCronRunSession(task,now,outcome):task),{assertCanCommit:target.assertGenerationOpen}))},"persistOutcome");let childSessionId;try{childSessionId=await dispatchTaskToFreshSession(target,updated)}catch(error){updated=annotateCronRunSession(updated,now,{dispatchFailed:true});if(updated.recurring){await persistOutcome({dispatchFailed:true}).catch(persistError=>{writeStderrLine(`qwen serve: POST ${base}/${id}/run could not record the failed dispatch: ${persistError instanceof Error?persistError.message:String(persistError)}`)})}else{await restoreConsumedOneShot(target,rollbackBefore,updated,removalGenerations,`POST ${base}/${id}/run fresh-session dispatch`)}writeStderrLine(`qwen serve: POST ${base}/${id}/run could not create a fresh session: ${error instanceof Error?error.message:String(error)}`);res.status(500).json({error:"Failed to create a fresh session for the scheduled task",code:"scheduled_task_session_dispatch_failed"});return}updated=annotateCronRunSession(updated,now,{sessionId:childSessionId});await persistOutcome({sessionId:childSessionId}).catch(error=>{writeStderrLine(`qwen serve: POST ${base}/${id}/run could not attribute fresh session ${childSessionId}: ${error instanceof Error?error.message:String(error)}`)})}if(!updated.recurring&&updated.sessionId){channelDeliveryAuthorizations?.revokeScheduledTask(workspaceCwd,updated.sessionId,updated.id)}const view=toView(updated);if(!updated.recurring)view.nextRunAt=null;res.status(200).json(view)}))}__name(registerScheduledTaskCrudRoutes,"registerScheduledTaskCrudRoutes");function registerScheduledTasksRoutes(app,deps){const{boundWorkspace,mutate,safeBody,bridge,channelDeliveryAuthorizations}=deps;registerScheduledTaskCrudRoutes(app,{prefix:"",resolveTarget:__name((_req,res)=>{const runtime=deps.getRuntime?.();if(deps.getRuntime&&!runtime){res.set("Retry-After","1");res.status(503).json({error:"Workspace runtime is not active",code:"workspace_runtime_unavailable"});return null}if(runtime&&!requireTrustedWorkspaceRuntime(runtime,res))return null;return{workspaceCwd:boundWorkspace,...runtime?{runtimeBaseDir:runtime.sessionRuntimeBaseDir,...deps.cleanupSession?{cleanupSession:__name(sessionId=>deps.cleanupSession(runtime,sessionId),"cleanupSession")}:{}}:{},bridge:bridge===void 0?void 0:runtime?.bridge??bridge,...runtime?.generationGuard?{assertGenerationOpen:__name(()=>runtime.generationGuard?.assertOpen(),"assertGenerationOpen")}:{},...deps.workspaceRegistry?{resolveLiveSessionOwner:__name(sessionId=>deps.workspaceRegistry.resolveLiveSessionOwner(sessionId),"resolveLiveSessionOwner")}:{}}},"resolveTarget"),mutate,safeBody,channelDeliveryAuthorizations})}__name(registerScheduledTasksRoutes,"registerScheduledTasksRoutes");function registerWorkspaceQualifiedScheduledTasksRoutes(app,deps){const{workspaceRegistry,mutate,safeBody,manageScheduledTaskSessions,channelDeliveryAuthorizations,cleanupSession}=deps;registerScheduledTaskCrudRoutes(app,{prefix:"/workspaces/:workspace",resolveTarget:__name((req,res)=>{const runtime=resolveWorkspaceRuntimeWithLiveCompatibilityFromParam(workspaceRegistry,req,res);if(!runtime)return null;if(!requireTrustedWorkspaceRuntime(runtime,res))return null;if(runtime.provenance==="live-conversation"&&!deps.conversationRuntimeActivity){sendConversationRuntimeUnavailable(res);return null}if(runtime.provenance==="live-conversation"&&req.method==="POST"&&req.params["id"]===void 0&&parseCallerSuppliedSessionId(safeBody(req)["sessionId"]).kind==="absent"){res.status(400).json({error:"Generic scheduled tasks cannot create sessions in the Conversations workspace.",code:"live_session_creation_reserved"});return null}return{workspaceCwd:runtime.workspaceCwd,runtimeBaseDir:runtime.sessionRuntimeBaseDir,...runtime.provenance==="live-conversation"&&deps.conversationRuntimeActivity?{activity:deps.conversationRuntimeActivity}:{},...cleanupSession?{cleanupSession:__name(sessionId=>cleanupSession(runtime,sessionId),"cleanupSession")}:{},bridge:manageScheduledTaskSessions?runtime.bridge:void 0,...runtime.generationGuard?{assertGenerationOpen:__name(()=>runtime.generationGuard?.assertOpen(),"assertGenerationOpen")}:{},resolveLiveSessionOwner:__name(sessionId=>workspaceRegistry.resolveLiveSessionOwner(sessionId),"resolveLiveSessionOwner")}},"resolveTarget"),mutate,safeBody,channelDeliveryAuthorizations})}__name(registerWorkspaceQualifiedScheduledTasksRoutes,"registerWorkspaceQualifiedScheduledTasksRoutes");var REMOVED_TASK_FIELDS=["runMode","condition"];function findRemovedTaskField(body){return REMOVED_TASK_FIELDS.find(field=>field in body)}__name(findRemovedTaskField,"findRemovedTaskField");function removedFieldError(field){return{error:`\`${field}\` is no longer supported: the isolated scheduled-task run mode was removed. Every task now runs in its bound session; call the \`create_sub_session\` tool from the task prompt for per-run isolation.`,code:"unsupported_field"}}__name(removedFieldError,"removedFieldError");function parseNameField(raw){if(raw===void 0||raw===null)return{value:void 0};if(typeof raw!=="string"){return{error:"`name` must be a string"}}const trimmed=raw.trim();if(trimmed.length===0)return{value:void 0};if(trimmed.length>MAX_NAME_LENGTH){return{error:`\`name\` exceeds ${MAX_NAME_LENGTH}-character limit`}}return{value:trimmed}}__name(parseNameField,"parseNameField");export{scheduledTaskSessionName,ExistingSessionScheduledTaskCreateError,createScheduledTaskWithExistingSession,registerScheduledTasksRoutes,registerWorkspaceQualifiedScheduledTasksRoutes};
|
|
3
|
+
import{buildScheduledTaskRunPrompt,parseChannelDelivery,scheduledTaskRunSessionName,scheduledTaskRunSourceId}from"./chunk-46I6JBVL.js";import{createSessionOrganizationService}from"./chunk-S2OOQRLJ.js";import{requireTrustedWorkspaceRuntime,resolveWorkspaceRuntimeWithLiveCompatibilityFromParam,sendConversationRuntimeUnavailable,sendGenerationClosedError}from"./chunk-VON4MVIM.js";import{parseCallerSuppliedSessionId}from"./chunk-LGFF5PJA.js";import{SCHEDULED_TASK_RUN_SOURCE_TYPE}from"./chunk-YVZ4XZRB.js";import{SessionNotFoundError}from"./chunk-VTZZXEWA.js";import{isChannelDeliveryError}from"./chunk-O6ZQAVRG.js";import{SessionService}from"./chunk-LDXZT3SG.js";import{stripTerminalControlSequences}from"./chunk-R2EHHA2C.js";import{MAX_JOBS,nextDurableFireMs}from"./chunk-57RLZJ6C.js";import{nextFireTime,parseCron}from"./chunk-EOMQENJY.js";import{MAX_CRON_TASK_ROUTING_ID_LENGTH,annotateCronRunSession,appendCronRun,cronTaskSessionDeletionId,generateCronTaskId,getCronFilePath,isValidCronTaskRoutingId,readCronTasks,taskHasLegacyCondition,updateCronTasks}from"./chunk-VMQO3VPA.js";import{writeStderrLine}from"./chunk-SLPJ4OII.js";import{Storage}from"./chunk-EPODBRBP.js";import{init_esbuild_shims}from"./chunk-VKDAXTCZ.js";import{__name}from"./chunk-KBWJGX7I.js";init_esbuild_shims();import{isDeepStrictEqual}from"node:util";import{access}from"node:fs/promises";var MAX_SCHEDULED_TASKS=MAX_JOBS;var MAX_PROMPT_LENGTH=1e5;var MAX_NAME_LENGTH=200;var MAX_CRON_LENGTH=200;var MAX_ROUTING_ID_LENGTH=MAX_CRON_TASK_ROUTING_ID_LENGTH;var MAX_SESSION_NAME_LENGTH=60;function scheduledTaskSessionName(label){const cleaned=stripTerminalControlSequences(label).replace(/[\u061c\u200e\u200f\u202a-\u202e\u2066-\u2069]/g,"").trim().replace(/\s+/g," ");let short=cleaned;if(cleaned.length>MAX_SESSION_NAME_LENGTH){let cut=MAX_SESSION_NAME_LENGTH-1;const boundary=cleaned.charCodeAt(cut-1);if(boundary>=55296&&boundary<=56319)cut-=1;short=`${cleaned.slice(0,cut)}\u2026`}return short}__name(scheduledTaskSessionName,"scheduledTaskSessionName");var ExistingSessionScheduledTaskCreateError=class extends Error{constructor(status,code,message){super(message);this.status=status;this.code=code;this.name="ExistingSessionScheduledTaskCreateError"}static{__name(this,"ExistingSessionScheduledTaskCreateError")}};function assertReusableScheduledTaskSession(target,sessionId,allowActivePrompt,assertCallerPromptActive){const{bridge,workspaceCwd}=target;if(!bridge){throw new ExistingSessionScheduledTaskCreateError(409,"session_binding_unavailable","Session management is not available for this workspace")}assertCallerPromptActive?.();let owner;try{owner=target.resolveLiveSessionOwner?.(sessionId)}catch(error){writeStderrLine(`qwen serve: failed to resolve scheduled-task session owner '${sessionId}': ${error instanceof Error?error.message:String(error)}`);throw new ExistingSessionScheduledTaskCreateError(500,"scheduled_tasks_session_failed","Failed to look up the requested session")}if(owner?.kind==="unavailable"){throw new ExistingSessionScheduledTaskCreateError(503,"workspace_runtime_unavailable","The workspace runtime is unavailable")}if(owner?.kind==="ambiguous"){throw new ExistingSessionScheduledTaskCreateError(500,"ambiguous_session_owner",`Session owner is ambiguous for "${sessionId}"`)}if(owner?.kind==="found"&&owner.runtime.workspaceCwd!==workspaceCwd){throw new ExistingSessionScheduledTaskCreateError(400,"session_workspace_mismatch","The requested session belongs to a different workspace; use that workspace's scheduled-task endpoint")}let summary;try{summary=bridge.getSessionSummary(sessionId)}catch(error){if(error instanceof SessionNotFoundError){throw new ExistingSessionScheduledTaskCreateError(404,"session_not_found",`Session '${sessionId}' was not found`)}writeStderrLine(`qwen serve: failed to look up scheduled-task session '${sessionId}': ${error instanceof Error?error.message:String(error)}`);throw new ExistingSessionScheduledTaskCreateError(500,"scheduled_tasks_session_failed","Failed to look up the requested session")}if(summary.workspaceCwd!==workspaceCwd){throw new ExistingSessionScheduledTaskCreateError(400,"session_workspace_mismatch","The requested session belongs to a different workspace; use that workspace's scheduled-task endpoint")}if(!allowActivePrompt&&summary.hasActivePrompt||(summary.pendingInteractionCount??0)>0){throw new ExistingSessionScheduledTaskCreateError(409,"session_busy",allowActivePrompt?"The caller session has a pending interaction; resolve it before binding the session to a task":"The requested session is busy; wait for its active prompt or pending interaction to finish before binding it to a task")}if(summary.sourceType==="scheduled_task"){throw new ExistingSessionScheduledTaskCreateError(409,"session_already_bound","The requested session is already reserved for a scheduled task")}if(summary.parentSessionId!==void 0||summary.sourceId!==void 0||summary.sourceType!==void 0&&summary.sourceType!=="default"){throw new ExistingSessionScheduledTaskCreateError(409,"session_source_ineligible","The requested session source cannot own a scheduled task")}}__name(assertReusableScheduledTaskSession,"assertReusableScheduledTaskSession");async function createScheduledTaskWithExistingSession(target,input,options){if(input.cron.length===0||input.cron.length>MAX_CRON_LENGTH||validateCron(input.cron)!==null){throw new ExistingSessionScheduledTaskCreateError(400,"invalid_cron","The scheduled-task cron expression is invalid")}const prompt=input.prompt.trim();if(prompt.length===0||prompt.length>MAX_PROMPT_LENGTH){throw new ExistingSessionScheduledTaskCreateError(400,"invalid_prompt","The scheduled-task prompt is invalid")}const allowActivePrompt=options.source==="cron-tool";const assertCallerPromptActive=options.source==="cron-tool"?options.assertCallerPromptActive:void 0;assertReusableScheduledTaskSession(target,input.sessionId,allowActivePrompt,assertCallerPromptActive);target.assertGenerationOpen?.();if(options.source==="rest"){const ensurePersisted=target.bridge?.ensureDefaultSessionPersisted;if(!ensurePersisted){throw new ExistingSessionScheduledTaskCreateError(409,"session_binding_unavailable","Session persistence is not available for this workspace")}try{await ensurePersisted.call(target.bridge,input.sessionId)}catch(error){target.assertGenerationOpen?.();if(error instanceof SessionNotFoundError){throw new ExistingSessionScheduledTaskCreateError(404,"session_not_found",`Session '${input.sessionId}' was not found`)}writeStderrLine(`qwen serve: failed to persist scheduled-task session '${input.sessionId}': ${error instanceof Error?error.message:String(error)}`);throw new ExistingSessionScheduledTaskCreateError(500,"session_persistence_failed","Failed to persist the requested session")}target.assertGenerationOpen?.()}const now=Date.now();const task={id:generateCronTaskId(),cron:input.cron,prompt,recurring:input.recurring,createdAt:now,lastFiredAt:now-now%6e4,enabled:input.enabled!==false,sessionId:input.sessionId,sessionOwnedByTask:false,sessionMode:input.sessionMode==="per_run"?"per_run":"persistent",...input.sessionMode==="per_run"&&input.modelServiceId!==void 0?{modelServiceId:input.modelServiceId}:{},...input.sessionMode==="per_run"&&input.groupId!==void 0?{groupId:input.groupId}:{},...input.delivery!==void 0?{delivery:input.delivery}:{},...input.name!==void 0?{name:input.name}:{}};let before;let after;await runWithScheduledTaskTarget(target,()=>updateCronTasks(target.workspaceCwd,tasks=>{assertReusableScheduledTaskSession(target,input.sessionId,allowActivePrompt,assertCallerPromptActive);if(tasks.some(candidate=>candidate.sessionId===input.sessionId)){throw new ExistingSessionScheduledTaskCreateError(409,"session_already_bound","The requested session is already bound to another scheduled task")}if(tasks.length>=MAX_SCHEDULED_TASKS){throw new ExistingSessionScheduledTaskCreateError(409,"max_tasks_reached",`Maximum number of scheduled tasks (${MAX_SCHEDULED_TASKS}) reached`)}before=tasks;after=[...tasks,task];return after},{assertCanCommit:target.assertGenerationOpen}));try{target.assertGenerationOpen?.()}catch(error){await rollbackCronMutation(target,before,after,"scheduled-task create");throw error}return task}__name(createScheduledTaskWithExistingSession,"createScheduledTaskWithExistingSession");function requireOpenGeneration(target,res){try{target.assertGenerationOpen?.();return true}catch(error){if(sendGenerationClosedError(res,error))return false;throw error}}__name(requireOpenGeneration,"requireOpenGeneration");async function rollbackCronMutation(target,before,after,route){if(!before||!after)return;await runWithScheduledTaskTarget(target,()=>updateCronTasks(target.workspaceCwd,tasks=>isDeepStrictEqual(tasks,after)?before:tasks)).catch(error=>{writeStderrLine(`qwen serve: ${route} failed to roll back a stale task mutation: ${error instanceof Error?error.message:String(error)}`)})}__name(rollbackCronMutation,"rollbackCronMutation");async function restoreConsumedOneShot(target,before,failedTask,removalGenerations,route){const id=failedTask.id;const index=before?.findIndex(t=>t.id===id)??-1;const original=index===-1?void 0:before[index];if(!original||!removalGenerations)return;let restoreGenerations;await runWithScheduledTaskTarget(target,()=>updateCronTasks(target.workspaceCwd,tasks=>{if([...removalGenerations].some(([key,generation])=>restoreGenerations?.get(key)!==generation))return tasks;if(tasks.some(t=>t.id===id))return tasks;const restored=[...tasks];restored.splice(Math.min(index,restored.length),0,{...failedTask,enabled:false});return restored},{observeDeletionIds:[...removalGenerations.keys()],onDeletionGenerations:__name(generations=>{restoreGenerations=generations},"onDeletionGenerations")})).catch(error=>{writeStderrLine(`qwen serve: ${route} failed to restore the consumed one-shot task: ${error instanceof Error?error.message:String(error)}`)})}__name(restoreConsumedOneShot,"restoreConsumedOneShot");async function teardownBoundSession(target,sessionId){if(target.cleanupSession){await target.cleanupSession(sessionId).catch(()=>{})}else if(target.bridge){await target.bridge.closeSession(sessionId).catch(()=>{});const removed=await new SessionService(target.workspaceCwd,{runtimeBaseDir:target.runtimeBaseDir}).removeSession(sessionId).catch(()=>false);if(removed)target.bridge.markSessionCatalogChanged?.()}}__name(teardownBoundSession,"teardownBoundSession");async function dispatchTaskToFreshSession(target,task){const{bridge}=target;const sendPrompt=bridge?.sendPrompt?.bind(bridge);if(!bridge||!sendPrompt||!task.sessionId){throw new Error("Fresh-session dispatch is unavailable for this task")}const triggeredAt=task.lastFiredAt??Date.now();const child=await runWithScheduledTaskTarget(target,()=>bridge.spawnOrAttach({workspaceCwd:target.workspaceCwd,...task.modelServiceId?{modelServiceId:task.modelServiceId}:{},sessionScope:"thread",parentSessionId:task.sessionId,sourceType:SCHEDULED_TASK_RUN_SOURCE_TYPE,sourceId:scheduledTaskRunSourceId(task.id)}));try{if(task.modelServiceId&&child.modelApplied===false){throw new Error(`Scheduled task model selection failed: ${task.modelServiceId}`)}try{bridge.updateSessionMetadata(child.sessionId,{displayName:scheduledTaskRunSessionName(task.name??task.prompt,triggeredAt),titleSource:"auto"})}catch{}let markPromptAdmitted;const promptAdmitted=new Promise(resolve=>{markPromptAdmitted=resolve});const turn=sendPrompt(child.sessionId,{sessionId:child.sessionId,prompt:[{type:"text",text:buildScheduledTaskRunPrompt({id:task.id,name:task.name,cron:task.cron,prompt:task.prompt,triggeredAt,trigger:"manual"})}]},void 0,{onPromptAdmitted:markPromptAdmitted});void turn.catch(error=>{writeStderrLine(`qwen serve: scheduled-task session ${child.sessionId} prompt failed: ${error instanceof Error?error.message:String(error)}`)});await Promise.race([promptAdmitted,turn.then(()=>void 0,error=>Promise.reject(error))]);if(task.groupId){try{await runWithScheduledTaskTarget(target,()=>createSessionOrganizationService(target.workspaceCwd).updateSessionOrganization(child.sessionId,{groupId:task.groupId,color:null}));bridge.markSessionCatalogChanged?.()}catch(error){writeStderrLine(`qwen serve: scheduled-task session ${child.sessionId} could not be assigned to group ${task.groupId}: ${error instanceof Error?error.message:String(error)}`)}}}catch(error){await teardownBoundSession(target,child.sessionId);throw error}return child.sessionId}__name(dispatchTaskToFreshSession,"dispatchTaskToFreshSession");async function runWithScheduledTaskTarget(target,fn){const result=target.runtimeBaseDir===void 0?fn():Storage.runWithResolvedRuntimeBaseDir(target.runtimeBaseDir,fn);return await result}__name(runWithScheduledTaskTarget,"runWithScheduledTaskTarget");function sendActivityGateError(res,error){if(!error||typeof error!=="object"||error.code!=="daemon_draining"){return false}res.status(503).json({error:"The daemon is draining and no longer accepts work.",code:"daemon_draining"});return true}__name(sendActivityGateError,"sendActivityGateError");function computeNextRunAt(task){if(task.enabled===false)return null;return nextDurableFireMs(task)}__name(computeNextRunAt,"computeNextRunAt");function toView(task){return{id:task.id,name:typeof task.name==="string"&&task.name.length>0?task.name:null,cron:task.cron,prompt:task.prompt,recurring:task.recurring,enabled:task.enabled!==false&&!taskHasLegacyCondition(task),createdAt:task.createdAt,lastFiredAt:task.lastFiredAt,nextRunAt:taskHasLegacyCondition(task)?null:computeNextRunAt(task),sessionId:typeof task.sessionId==="string"&&task.sessionId.length>0?task.sessionId:null,sessionMode:task.sessionMode==="per_run"?"per_run":"persistent",modelServiceId:task.modelServiceId??null,groupId:task.groupId??null,runs:Array.isArray(task.runs)?task.runs:[],...task.delivery!==void 0?{delivery:task.delivery}:{}}}__name(toView,"toView");function validateCron(cron){try{parseCron(cron);nextFireTime(cron,new Date);return null}catch(err){return err instanceof Error?err.message:String(err)}}__name(validateCron,"validateCron");function canonicalCron(cron){try{const f=parseCron(cron);const s=__name(set=>[...set].sort((a,b)=>a-b).join(","),"s");return[s(f.minute),s(f.hour),s(f.dayOfMonth),s(f.month),s(f.dayOfWeek),f.domIsWild?"W":"",f.dowIsWild?"W":""].join("|")}catch{return null}}__name(canonicalCron,"canonicalCron");function registerScheduledTaskCrudRoutes(app,deps){const{prefix,resolveTarget,mutate,safeBody,channelDeliveryAuthorizations}=deps;const base=`${prefix}/scheduled-tasks`;const withTarget=__name(handler=>async(req,res)=>{const target=resolveTarget(req,res);if(!target)return;const operation=__name(async()=>{if(!requireOpenGeneration(target,res))return;await handler(req,res,target)},"operation");try{if(target.activity){await target.activity.run(operation)}else{await operation()}}catch(error){if(sendActivityGateError(res,error))return;throw error}},"withTarget");app.get(base,withTarget(async(_req,res,target)=>{try{const tasks=await runWithScheduledTaskTarget(target,()=>readCronTasks(target.workspaceCwd));if(!requireOpenGeneration(target,res))return;res.status(200).json({v:1,tasks:tasks.map(toView)})}catch(err){if(sendActivityGateError(res,err))return;writeStderrLine(`qwen serve: GET ${base} failed: ${err instanceof Error?err.message:String(err)}`);res.status(500).json({error:"Failed to read scheduled tasks (the tasks file may be corrupt)",code:"scheduled_tasks_read_failed"})}}));app.post(base,mutate(),withTarget(async(req,res,target)=>{const{workspaceCwd,bridge}=target;const body=safeBody(req);const cron=typeof body["cron"]==="string"?body["cron"].trim():"";if(cron.length===0){res.status(400).json({error:"`cron` is required and must be a non-empty string",code:"invalid_cron"});return}if(cron.length>MAX_CRON_LENGTH){res.status(400).json({error:`\`cron\` exceeds ${MAX_CRON_LENGTH}-character limit`,code:"invalid_cron"});return}const cronError=validateCron(cron);if(cronError){res.status(400).json({error:cronError,code:"invalid_cron"});return}const prompt=typeof body["prompt"]==="string"?body["prompt"].trim():"";if(prompt.length===0){res.status(400).json({error:"`prompt` is required and must be a non-empty string",code:"invalid_prompt"});return}if(prompt.length>MAX_PROMPT_LENGTH){res.status(400).json({error:`\`prompt\` exceeds ${MAX_PROMPT_LENGTH}-character limit`,code:"invalid_prompt"});return}const nameResult=parseNameField(body["name"]);if(nameResult.error){res.status(400).json({error:nameResult.error,code:"invalid_name"});return}if(body["recurring"]!==void 0&&typeof body["recurring"]!=="boolean"){res.status(400).json({error:"`recurring` must be a boolean",code:"invalid_recurring"});return}if(body["enabled"]!==void 0&&typeof body["enabled"]!=="boolean"){res.status(400).json({error:"`enabled` must be a boolean",code:"invalid_enabled"});return}const sessionMode=body["sessionMode"]===void 0?"persistent":body["sessionMode"];if(sessionMode!=="persistent"&&sessionMode!=="per_run"){res.status(400).json({error:'`sessionMode` must be "persistent" or "per_run"',code:"invalid_session_mode"});return}const modelServiceId=body["modelServiceId"];if(modelServiceId!==void 0&&!isValidCronTaskRoutingId(modelServiceId)){res.status(400).json({error:`\`modelServiceId\` must be a non-empty string of at most ${MAX_ROUTING_ID_LENGTH} characters without control characters`,code:"invalid_model_service_id"});return}const groupId=body["groupId"];if(groupId!==void 0&&!isValidCronTaskRoutingId(groupId)){res.status(400).json({error:`\`groupId\` must be a non-empty string of at most ${MAX_ROUTING_ID_LENGTH} characters without control characters`,code:"invalid_group_id"});return}if(sessionMode!=="per_run"&&(modelServiceId!==void 0||groupId!==void 0)){res.status(400).json({error:'`modelServiceId` and `groupId` are only supported when `sessionMode` is "per_run"',code:"session_routing_requires_per_run"});return}if(typeof groupId==="string"){const groups=await runWithScheduledTaskTarget(target,()=>createSessionOrganizationService(workspaceCwd).listGroups());if(!groups.groups.some(group=>group.id===groupId)){res.status(400).json({error:`Group not found: ${groupId}`,code:"group_not_found"});return}}const parsedSessionId=parseCallerSuppliedSessionId(body["sessionId"]);if(parsedSessionId.kind==="invalid"){res.status(400).json({error:'`sessionId` must be an RFC UUID v1-v5 (e.g. "550e8400-e29b-41d4-a716-446655440000")',code:"invalid_session_id"});return}const providedSessionId=parsedSessionId.kind==="valid"?parsedSessionId.sessionId:void 0;let delivery;if(body["delivery"]!==void 0){try{delivery=parseChannelDelivery(body["delivery"])}catch(err){if(!isChannelDeliveryError(err))throw err;res.status(400).json({error:err.message,code:err.code});return}}if(sessionMode==="per_run"&&delivery!==void 0){res.status(400).json({error:"Per-run sessions do not support channel delivery",code:"session_mode_delivery_unsupported"});return}const removedField=findRemovedTaskField(body);if(removedField){res.status(400).json(removedFieldError(removedField));return}const recurring=body["recurring"]!==false;const enabled=body["enabled"]!==false;const taskId=generateCronTaskId();if(sessionMode==="per_run"&&(!bridge||!bridge.sendPrompt)){res.status(409).json({error:"Fresh-session dispatch is not available for this workspace",code:"session_mode_unavailable"});return}if(providedSessionId!==void 0){try{const task2=await createScheduledTaskWithExistingSession(target,{sessionId:providedSessionId,cron,prompt,recurring,enabled,sessionMode,...typeof modelServiceId==="string"?{modelServiceId}:{},...typeof groupId==="string"?{groupId}:{},...delivery!==void 0?{delivery}:{},...nameResult.value!==void 0?{name:nameResult.value}:{}},{source:"rest"});if(task2.delivery&&task2.sessionId){channelDeliveryAuthorizations?.registerScheduledTask(workspaceCwd,{sessionId:task2.sessionId,taskId:task2.id,target:task2.delivery.target,recurring:task2.recurring,lastFiredAt:task2.lastFiredAt??void 0})}res.status(201).json(toView(task2))}catch(error){if(error instanceof ExistingSessionScheduledTaskCreateError){if(error.code==="workspace_runtime_unavailable"){res.set("Retry-After","1")}res.status(error.status).json({error:error.message,code:error.code});return}if(sendActivityGateError(res,error))return;if(sendGenerationClosedError(res,error))return;writeStderrLine(`qwen serve: POST ${base} failed to create a task for session '${providedSessionId}': ${error instanceof Error?error.message:String(error)}`);res.status(500).json({error:"Failed to create scheduled task",code:"scheduled_tasks_write_failed"})}return}let boundSessionId;let sessionMintedHere=false;if(bridge){try{const tasks=await runWithScheduledTaskTarget(target,()=>readCronTasks(workspaceCwd));if(tasks.length>=MAX_SCHEDULED_TASKS){res.status(409).json({error:`Maximum number of scheduled tasks (${MAX_SCHEDULED_TASKS}) reached`,code:"max_tasks_reached"});return}}catch{}if(!requireOpenGeneration(target,res))return;try{const session=await runWithScheduledTaskTarget(target,()=>bridge.spawnOrAttach({workspaceCwd,sessionScope:"thread",sourceType:"scheduled_task",sourceId:taskId}));boundSessionId=session.sessionId;sessionMintedHere=true;if(!requireOpenGeneration(target,res)){await teardownBoundSession(target,boundSessionId);return}try{await runWithScheduledTaskTarget(target,async()=>bridge.updateSessionMetadata(boundSessionId,{displayName:scheduledTaskSessionName(nameResult.value??prompt),titleSource:"auto"}))}catch{}}catch(err){if(sendActivityGateError(res,err))return;if(sendGenerationClosedError(res,err))return;writeStderrLine(`qwen serve: POST ${base} failed to create the task's session: ${err instanceof Error?err.message:String(err)}`);res.status(500).json({error:"Failed to create the task's session",code:"scheduled_tasks_session_failed"});return}}const now=Date.now();const task={id:taskId,cron,prompt,recurring,createdAt:now,lastFiredAt:now-now%6e4,enabled,sessionMode,...typeof modelServiceId==="string"?{modelServiceId}:{},...typeof groupId==="string"?{groupId}:{},...delivery!==void 0?{delivery}:{},...boundSessionId!==void 0?{sessionId:boundSessionId}:{},...nameResult.value!==void 0?{name:nameResult.value}:{}};const rollbackSession=__name(async()=>{if(boundSessionId!==void 0&&sessionMintedHere){await teardownBoundSession(target,boundSessionId)}},"rollbackSession");let overCap=false;let rollbackBefore;let rollbackAfter;try{await runWithScheduledTaskTarget(target,()=>updateCronTasks(workspaceCwd,tasks=>{if(tasks.length>=MAX_SCHEDULED_TASKS){overCap=true;return tasks}rollbackBefore=tasks;rollbackAfter=[...tasks,task];return rollbackAfter},{assertCanCommit:target.assertGenerationOpen}))}catch(err){await rollbackSession();if(sendActivityGateError(res,err))return;if(sendGenerationClosedError(res,err))return;writeStderrLine(`qwen serve: POST ${base} failed: ${err instanceof Error?err.message:String(err)}`);res.status(500).json({error:"Failed to create scheduled task",code:"scheduled_tasks_write_failed"});return}if(rollbackBefore&&rollbackAfter){try{target.assertGenerationOpen?.()}catch(error){await rollbackCronMutation(target,rollbackBefore,rollbackAfter,`POST ${base}`);await rollbackSession();if(sendGenerationClosedError(res,error))return;throw error}}if(overCap){await rollbackSession();res.status(409).json({error:`Maximum number of scheduled tasks (${MAX_SCHEDULED_TASKS}) reached`,code:"max_tasks_reached"});return}if(task.delivery&&task.sessionId){channelDeliveryAuthorizations?.registerScheduledTask(workspaceCwd,{sessionId:task.sessionId,taskId:task.id,target:task.delivery.target,recurring:task.recurring,lastFiredAt:task.lastFiredAt??void 0})}res.status(201).json(toView(task))}));app.patch(`${base}/:id`,mutate(),withTarget(async(req,res,target)=>{const{workspaceCwd,bridge}=target;const id=typeof req.params["id"]==="string"?req.params["id"]:"";if(id.length===0){res.status(400).json({error:"Task id is required",code:"invalid_id"});return}const body=safeBody(req);const patch={};let clearName=false;let clearDelivery=false;let clearModelServiceId=false;let clearGroupId=false;let missingGroupId;const removedPatchField=findRemovedTaskField(body);if(removedPatchField){res.status(400).json(removedFieldError(removedPatchField));return}if("cron"in body){const cron=typeof body["cron"]==="string"?body["cron"].trim():"";if(cron.length===0||cron.length>MAX_CRON_LENGTH){res.status(400).json({error:"`cron` must be a non-empty string within the length limit",code:"invalid_cron"});return}const cronError=validateCron(cron);if(cronError){res.status(400).json({error:cronError,code:"invalid_cron"});return}patch.cron=cron}if("prompt"in body){const prompt=typeof body["prompt"]==="string"?body["prompt"].trim():"";if(prompt.length===0||prompt.length>MAX_PROMPT_LENGTH){res.status(400).json({error:"`prompt` must be a non-empty string within the length limit",code:"invalid_prompt"});return}patch.prompt=prompt}if("name"in body){const nameResult=parseNameField(body["name"]);if(nameResult.error){res.status(400).json({error:nameResult.error,code:"invalid_name"});return}if(nameResult.value===void 0){clearName=true}else{patch.name=nameResult.value}}if("recurring"in body){if(typeof body["recurring"]!=="boolean"){res.status(400).json({error:"`recurring` must be a boolean",code:"invalid_recurring"});return}patch.recurring=body["recurring"]}if("enabled"in body){if(typeof body["enabled"]!=="boolean"){res.status(400).json({error:"`enabled` must be a boolean",code:"invalid_enabled"});return}patch.enabled=body["enabled"]}if("sessionMode"in body){if(body["sessionMode"]!=="persistent"&&body["sessionMode"]!=="per_run"){res.status(400).json({error:'`sessionMode` must be "persistent" or "per_run"',code:"invalid_session_mode"});return}patch.sessionMode=body["sessionMode"]}if("modelServiceId"in body){const value=body["modelServiceId"];if(value===null||value===""){clearModelServiceId=true}else if(!isValidCronTaskRoutingId(value)){res.status(400).json({error:`\`modelServiceId\` must be null or a non-empty string of at most ${MAX_ROUTING_ID_LENGTH} characters without control characters`,code:"invalid_model_service_id"});return}else{patch.modelServiceId=value}}if("groupId"in body){const value=body["groupId"];if(value===null||value===""){clearGroupId=true}else if(!isValidCronTaskRoutingId(value)){res.status(400).json({error:`\`groupId\` must be null or a non-empty string of at most ${MAX_ROUTING_ID_LENGTH} characters without control characters`,code:"invalid_group_id"});return}else{const groups=await runWithScheduledTaskTarget(target,()=>createSessionOrganizationService(workspaceCwd).listGroups());if(!groups.groups.some(group=>group.id===value)){missingGroupId=value}patch.groupId=value}}if("delivery"in body){if(body["delivery"]===null){clearDelivery=true}else{try{patch.delivery=parseChannelDelivery(body["delivery"])}catch(err){if(!isChannelDeliveryError(err))throw err;res.status(400).json({error:err.message,code:err.code});return}}}if(Object.keys(patch).length===0&&!clearName&&!clearDelivery&&!clearModelServiceId&&!clearGroupId){res.status(400).json({error:"No updatable fields provided",code:"empty_patch"});return}let found=false;let updated;let blockedByArchive=false;let blockedLegacy=false;let blockedSessionModeDelivery=false;let blockedSessionModeUnavailable=false;let blockedSessionModeUnbound=false;let blockedGroupNotFound=false;let rollbackBefore;let rollbackAfter;try{await runWithScheduledTaskTarget(target,()=>updateCronTasks(workspaceCwd,tasks=>{const idx=tasks.findIndex(t=>t.id===id);if(idx===-1)return tasks;found=true;const current=tasks[idx];if(missingGroupId!==void 0&¤t.groupId!==missingGroupId){blockedGroupNotFound=true;return tasks}const convertingToPerRun=patch.sessionMode==="per_run"&¤t.sessionMode!=="per_run";if(convertingToPerRun&&(!bridge||!bridge.sendPrompt)){blockedSessionModeUnavailable=true;return tasks}if(convertingToPerRun&&!current.sessionId){blockedSessionModeUnbound=true;return tasks}if(patch.enabled===true&&taskHasLegacyCondition(current)){blockedLegacy=true;return tasks}if(patch.enabled===true&¤t.disabledByArchive===true){blockedByArchive=true;return tasks}const next={...current,...patch};if(clearName)delete next.name;if(clearDelivery)delete next.delivery;if(clearModelServiceId)delete next.modelServiceId;if(clearGroupId)delete next.groupId;if(next.sessionMode!=="per_run"){delete next.modelServiceId;delete next.groupId}if(next.sessionMode==="per_run"&&next.delivery){blockedSessionModeDelivery=true;return tasks}const justReEnabled=current.enabled===false&&patch.enabled===true;const cronChanged=patch.cron!==void 0&&canonicalCron(patch.cron)!==canonicalCron(current.cron);const becameRecurring=patch.recurring===true&¤t.recurring!==true;const becameOneShot=patch.recurring===false&¤t.recurring!==false;const retryFailedOneShot=!next.recurring&&justReEnabled&&!cronChanged&&!becameOneShot&¤t.runs?.at(-1)?.sessionDispatchFailed===true;{const now=Date.now();const minute=now-now%6e4;if(next.recurring&&(justReEnabled||cronChanged||becameRecurring)){next.lastFiredAt=minute}else if(!next.recurring&&!retryFailedOneShot&&(justReEnabled||cronChanged||becameOneShot)){next.createdAt=now;next.lastFiredAt=minute}}updated=next;rollbackBefore=tasks;rollbackAfter=tasks.map((t,i)=>i===idx?next:t);return rollbackAfter},{assertCanCommit:target.assertGenerationOpen}))}catch(err){if(sendActivityGateError(res,err))return;if(sendGenerationClosedError(res,err))return;writeStderrLine(`qwen serve: PATCH ${base}/${id} failed: ${err instanceof Error?err.message:String(err)}`);res.status(500).json({error:"Failed to update scheduled task",code:"scheduled_tasks_write_failed"});return}if(rollbackBefore&&rollbackAfter){try{target.assertGenerationOpen?.()}catch(error){await rollbackCronMutation(target,rollbackBefore,rollbackAfter,`PATCH ${base}/${id}`);if(sendGenerationClosedError(res,error))return;throw error}}if(!found){res.status(404).json({error:"Task not found",code:"task_not_found"});return}if(missingGroupId!==void 0&&blockedGroupNotFound){res.status(400).json({error:`Group not found: ${missingGroupId}`,code:"group_not_found"});return}if(blockedLegacy){res.status(409).json({error:"This task uses the removed isolated run mode with a precondition and can no longer be enabled or run. Recreate it (and call the `create_sub_session` tool from the prompt if you need per-run isolation).",code:"task_legacy_unsupported"});return}if(blockedByArchive){res.status(409).json({error:"This task was disabled by archiving its session; unarchive the session to re-enable it.",code:"task_session_archived"});return}if(blockedSessionModeUnavailable){res.status(409).json({error:"Fresh-session dispatch is not available for this workspace",code:"session_mode_unavailable"});return}if(blockedSessionModeUnbound){res.status(409).json({error:"This task is not bound to a session yet, so it cannot run in a new session every run. Try again once it has run or been opened at least once.",code:"session_mode_requires_bound_session"});return}if(blockedSessionModeDelivery){res.status(409).json({error:"Per-run sessions do not support channel delivery",code:"session_mode_delivery_unsupported"});return}if(!updated){res.status(404).json({error:"Task not found",code:"task_not_found"});return}const effectiveLabelChanged=patch.name!==void 0||clearName||patch.prompt!==void 0&&updated.name===void 0;if(bridge&&updated.sessionId&&updated.sessionOwnedByTask!==false&&effectiveLabelChanged){try{bridge.updateSessionMetadata(updated.sessionId,{displayName:scheduledTaskSessionName(updated.name??updated.prompt),titleSource:"auto"})}catch{}}if(updated.delivery&&updated.sessionId){channelDeliveryAuthorizations?.registerScheduledTask(workspaceCwd,{sessionId:updated.sessionId,taskId:updated.id,target:updated.delivery.target,recurring:updated.recurring,lastFiredAt:updated.lastFiredAt??void 0})}if(clearDelivery&&updated.sessionId){channelDeliveryAuthorizations?.revokeScheduledTask(workspaceCwd,updated.sessionId,updated.id)}res.status(200).json(toView(updated))}));app.delete(`${base}/:id`,mutate(),withTarget(async(req,res,target)=>{const{workspaceCwd,bridge}=target;const id=typeof req.params["id"]==="string"?req.params["id"]:"";if(id.length===0){res.status(400).json({error:"Task id is required",code:"invalid_id"});return}let boundSessionId;let sessionOwnedByTask=true;let removed=false;let rollbackBefore;let rollbackAfter;try{await runWithScheduledTaskTarget(target,async()=>{try{await access(getCronFilePath(workspaceCwd))}catch(error){if(error.code==="ENOENT")return;throw error}await updateCronTasks(workspaceCwd,tasks=>{const idx=tasks.findIndex(t=>t.id===id);if(idx===-1)return tasks;const match=tasks[idx].sessionId;if(typeof match==="string"&&match.length>0){boundSessionId=match;sessionOwnedByTask=tasks[idx].sessionOwnedByTask!==false}removed=true;rollbackBefore=tasks;rollbackAfter=tasks.filter((_,i)=>i!==idx);return rollbackAfter},{assertCanCommit:target.assertGenerationOpen,deletionIds:[id]})})}catch(err){if(sendActivityGateError(res,err))return;if(sendGenerationClosedError(res,err))return;writeStderrLine(`qwen serve: DELETE ${base}/${id} failed: ${err instanceof Error?err.message:String(err)}`);res.status(500).json({error:"Failed to delete scheduled task",code:"scheduled_tasks_write_failed"});return}if(rollbackBefore&&rollbackAfter){try{target.assertGenerationOpen?.()}catch(error){await rollbackCronMutation(target,rollbackBefore,rollbackAfter,`DELETE ${base}/${id}`);if(sendGenerationClosedError(res,error))return;throw error}}if(!removed){res.status(404).json({error:"Task not found",code:"task_not_found"});return}if(boundSessionId&&sessionOwnedByTask&&bridge){try{await runWithScheduledTaskTarget(target,()=>bridge.closeSession(boundSessionId,void 0,{closeIfUnheld:true,reason:"scheduled_task_deleted"}))}catch(error){if(sendActivityGateError(res,error))return}}if(boundSessionId){channelDeliveryAuthorizations?.revokeScheduledTask(workspaceCwd,boundSessionId,id)}res.status(200).json({deleted:true,id})}));app.post(`${base}/:id/run`,mutate(),withTarget(async(req,res,target)=>{const{workspaceCwd}=target;const id=typeof req.params["id"]==="string"?req.params["id"]:"";if(id.length===0){res.status(400).json({error:"Task id is required",code:"invalid_id"});return}const now=Date.now();let found=false;let blockedDisabled=false;let blockedLegacy=false;let updated;let rollbackBefore;let rollbackAfter;let removalGenerations;try{await runWithScheduledTaskTarget(target,()=>updateCronTasks(workspaceCwd,tasks=>{const idx=tasks.findIndex(t=>t.id===id);if(idx===-1)return tasks;found=true;const current=tasks[idx];if(taskHasLegacyCondition(current)){blockedLegacy=true;return tasks}if(current.enabled===false){blockedDisabled=true;return tasks}const next={...current,lastFiredAt:now,runs:appendCronRun(current.runs,{at:now,kind:"manual",...current.sessionMode!=="per_run"&¤t.sessionId?{sessionId:current.sessionId}:{}})};updated=next;rollbackBefore=tasks;const nextTasks=!current.recurring?tasks.filter((_,i)=>i!==idx):tasks.map((t,i)=>i===idx?next:t);rollbackAfter=nextTasks;return nextTasks},{assertCanCommit:target.assertGenerationOpen,observeDeletionIds:__name(tasks=>{const task=tasks.find(task2=>task2.id===id);return task?.sessionId?[id,cronTaskSessionDeletionId(task.sessionId)]:[id]},"observeDeletionIds"),onDeletionGenerations:__name(generations=>{removalGenerations=generations},"onDeletionGenerations")}))}catch(err){if(sendActivityGateError(res,err))return;if(sendGenerationClosedError(res,err))return;writeStderrLine(`qwen serve: POST ${base}/${id}/run failed: ${err instanceof Error?err.message:String(err)}`);res.status(500).json({error:"Failed to record scheduled task run",code:"scheduled_tasks_write_failed"});return}if(rollbackBefore&&rollbackAfter){try{target.assertGenerationOpen?.()}catch(error){await rollbackCronMutation(target,rollbackBefore,rollbackAfter,`POST ${base}/${id}/run`);if(sendGenerationClosedError(res,error))return;throw error}}if(blockedLegacy){res.status(409).json({error:"This task uses the removed isolated run mode with a precondition and can no longer run. Recreate it (and call the `create_sub_session` tool from the prompt if you need per-run isolation).",code:"task_legacy_unsupported"});return}if(blockedDisabled){res.status(409).json({error:"Cannot run a disabled task; enable it first (unarchive its session if it was archived).",code:"task_disabled"});return}if(!found||!updated){res.status(404).json({error:"Task not found",code:"task_not_found"});return}if(updated.sessionMode==="per_run"){const persistOutcome=__name(async outcome=>{if(!updated.recurring)return;await runWithScheduledTaskTarget(target,()=>updateCronTasks(workspaceCwd,tasks=>tasks.map(task=>task.id===id?annotateCronRunSession(task,now,outcome):task),{assertCanCommit:target.assertGenerationOpen}))},"persistOutcome");let childSessionId;try{childSessionId=await dispatchTaskToFreshSession(target,updated)}catch(error){updated=annotateCronRunSession(updated,now,{dispatchFailed:true});if(updated.recurring){await persistOutcome({dispatchFailed:true}).catch(persistError=>{writeStderrLine(`qwen serve: POST ${base}/${id}/run could not record the failed dispatch: ${persistError instanceof Error?persistError.message:String(persistError)}`)})}else{await restoreConsumedOneShot(target,rollbackBefore,updated,removalGenerations,`POST ${base}/${id}/run fresh-session dispatch`)}writeStderrLine(`qwen serve: POST ${base}/${id}/run could not create a fresh session: ${error instanceof Error?error.message:String(error)}`);res.status(500).json({error:"Failed to create a fresh session for the scheduled task",code:"scheduled_task_session_dispatch_failed"});return}updated=annotateCronRunSession(updated,now,{sessionId:childSessionId});await persistOutcome({sessionId:childSessionId}).catch(error=>{writeStderrLine(`qwen serve: POST ${base}/${id}/run could not attribute fresh session ${childSessionId}: ${error instanceof Error?error.message:String(error)}`)})}if(!updated.recurring&&updated.sessionId){channelDeliveryAuthorizations?.revokeScheduledTask(workspaceCwd,updated.sessionId,updated.id)}const view=toView(updated);if(!updated.recurring)view.nextRunAt=null;res.status(200).json(view)}))}__name(registerScheduledTaskCrudRoutes,"registerScheduledTaskCrudRoutes");function registerScheduledTasksRoutes(app,deps){const{boundWorkspace,mutate,safeBody,bridge,channelDeliveryAuthorizations}=deps;registerScheduledTaskCrudRoutes(app,{prefix:"",resolveTarget:__name((_req,res)=>{const runtime=deps.getRuntime?.();if(deps.getRuntime&&!runtime){res.set("Retry-After","1");res.status(503).json({error:"Workspace runtime is not active",code:"workspace_runtime_unavailable"});return null}if(runtime&&!requireTrustedWorkspaceRuntime(runtime,res))return null;return{workspaceCwd:boundWorkspace,...runtime?{runtimeBaseDir:runtime.sessionRuntimeBaseDir,...deps.cleanupSession?{cleanupSession:__name(sessionId=>deps.cleanupSession(runtime,sessionId),"cleanupSession")}:{}}:{},bridge:bridge===void 0?void 0:runtime?.bridge??bridge,...runtime?.generationGuard?{assertGenerationOpen:__name(()=>runtime.generationGuard?.assertOpen(),"assertGenerationOpen")}:{},...deps.workspaceRegistry?{resolveLiveSessionOwner:__name(sessionId=>deps.workspaceRegistry.resolveLiveSessionOwner(sessionId),"resolveLiveSessionOwner")}:{}}},"resolveTarget"),mutate,safeBody,channelDeliveryAuthorizations})}__name(registerScheduledTasksRoutes,"registerScheduledTasksRoutes");function registerWorkspaceQualifiedScheduledTasksRoutes(app,deps){const{workspaceRegistry,mutate,safeBody,manageScheduledTaskSessions,channelDeliveryAuthorizations,cleanupSession}=deps;registerScheduledTaskCrudRoutes(app,{prefix:"/workspaces/:workspace",resolveTarget:__name((req,res)=>{const runtime=resolveWorkspaceRuntimeWithLiveCompatibilityFromParam(workspaceRegistry,req,res);if(!runtime)return null;if(!requireTrustedWorkspaceRuntime(runtime,res))return null;if(runtime.provenance==="live-conversation"&&!deps.conversationRuntimeActivity){sendConversationRuntimeUnavailable(res);return null}if(runtime.provenance==="live-conversation"&&req.method==="POST"&&req.params["id"]===void 0&&parseCallerSuppliedSessionId(safeBody(req)["sessionId"]).kind==="absent"){res.status(400).json({error:"Generic scheduled tasks cannot create sessions in the Conversations workspace.",code:"live_session_creation_reserved"});return null}return{workspaceCwd:runtime.workspaceCwd,runtimeBaseDir:runtime.sessionRuntimeBaseDir,...runtime.provenance==="live-conversation"&&deps.conversationRuntimeActivity?{activity:deps.conversationRuntimeActivity}:{},...cleanupSession?{cleanupSession:__name(sessionId=>cleanupSession(runtime,sessionId),"cleanupSession")}:{},bridge:manageScheduledTaskSessions?runtime.bridge:void 0,...runtime.generationGuard?{assertGenerationOpen:__name(()=>runtime.generationGuard?.assertOpen(),"assertGenerationOpen")}:{},resolveLiveSessionOwner:__name(sessionId=>workspaceRegistry.resolveLiveSessionOwner(sessionId),"resolveLiveSessionOwner")}},"resolveTarget"),mutate,safeBody,channelDeliveryAuthorizations})}__name(registerWorkspaceQualifiedScheduledTasksRoutes,"registerWorkspaceQualifiedScheduledTasksRoutes");var REMOVED_TASK_FIELDS=["runMode","condition"];function findRemovedTaskField(body){return REMOVED_TASK_FIELDS.find(field=>field in body)}__name(findRemovedTaskField,"findRemovedTaskField");function removedFieldError(field){return{error:`\`${field}\` is no longer supported: the isolated scheduled-task run mode was removed. Every task now runs in its bound session; call the \`create_sub_session\` tool from the task prompt for per-run isolation.`,code:"unsupported_field"}}__name(removedFieldError,"removedFieldError");function parseNameField(raw){if(raw===void 0||raw===null)return{value:void 0};if(typeof raw!=="string"){return{error:"`name` must be a string"}}const trimmed=raw.trim();if(trimmed.length===0)return{value:void 0};if(trimmed.length>MAX_NAME_LENGTH){return{error:`\`name\` exceeds ${MAX_NAME_LENGTH}-character limit`}}return{value:trimmed}}__name(parseNameField,"parseNameField");export{scheduledTaskSessionName,ExistingSessionScheduledTaskCreateError,createScheduledTaskWithExistingSession,registerScheduledTasksRoutes,registerWorkspaceQualifiedScheduledTasksRoutes};
|
|
4
4
|
/**
|
|
5
5
|
* @license
|
|
6
6
|
* Copyright 2025 Qwen Team
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// Force strict mode and setup for ESM
|
|
2
2
|
"use strict";
|
|
3
|
-
import{appEvents}from"./chunk-
|
|
3
|
+
import{appEvents}from"./chunk-34WLYVDK.js";import{CUSTOM_SANDBOX_IMAGE_ENV_VAR,HOST_UPDATE_RELAUNCH_ENV_VAR,SKIP_UPDATE_CHECK_ENV_VAR,requestUpdateOnExit}from"./chunk-JRJY343T.js";import{loadUndici}from"./chunk-XKSB7VTV.js";import{IdeClient}from"./chunk-LDXZT3SG.js";import{getAllProviderBaseUrls}from"./chunk-DIHJELGW.js";import{detectRuntime,getOrCreateSharedDispatcher,preloadRuntimeFetchModule,redactProxyCredentials}from"./chunk-ZZZAYAJW.js";import{initializeTelemetry}from"./chunk-XHV5HLJS.js";import{recordStartupEvent}from"./chunk-H4XFFVZ2.js";import{createDebugLogger}from"./chunk-JAUJI56S.js";import{init_esbuild_shims}from"./chunk-VKDAXTCZ.js";import{__name}from"./chunk-KBWJGX7I.js";init_esbuild_shims();init_esbuild_shims();var debugLogger=createDebugLogger("PRECONNECT");var preconnectFired=false;var preconnectInFlight;var DEFAULT_BASE_URLS={openai:"https://api.openai.com","qwen-oauth":"https://coding.dashscope.aliyuncs.com",anthropic:"https://api.anthropic.com",dashscope:"https://dashscope.aliyuncs.com"};var ALL_DEFAULT_URLS=[...Object.values(DEFAULT_BASE_URLS),...getAllProviderBaseUrls()];function shouldSkipPreconnect(){if(process.env["NODE_EXTRA_CA_CERTS"]){debugLogger.debug("Skipping preconnect: custom CA certificate configured");return true}return false}__name(shouldSkipPreconnect,"shouldSkipPreconnect");function isInSandboxMode(){return process.env["SANDBOX"]!==void 0}__name(isInSandboxMode,"isInSandboxMode");function isDefaultBaseUrl(baseUrl){const normalizedInput=baseUrl.toLowerCase().replace(/^https?:\/\//,"").replace(/\/+$/,"");return ALL_DEFAULT_URLS.some(defaultUrl=>{const normalizedDefault=defaultUrl.toLowerCase().replace(/^https?:\/\//,"").replace(/\/+$/,"");return normalizedInput===normalizedDefault||normalizedInput.startsWith(normalizedDefault+"/")})}__name(isDefaultBaseUrl,"isDefaultBaseUrl");function getPreconnectTargetUrl(authType,resolvedBaseUrl){if(resolvedBaseUrl&&/^https?:\/\//i.test(resolvedBaseUrl)){if(isDefaultBaseUrl(resolvedBaseUrl)){return resolvedBaseUrl}debugLogger.debug("Skipping preconnect: resolved baseUrl is not a default URL");return void 0}if(authType&&DEFAULT_BASE_URLS[authType]){return DEFAULT_BASE_URLS[authType]}return void 0}__name(getPreconnectTargetUrl,"getPreconnectTargetUrl");function preconnectApi(authType,options={}){if(preconnectFired){return}if(process.env["QWEN_CODE_DISABLE_PRECONNECT"]==="1"){debugLogger.debug("Preconnect disabled by environment variable");preconnectFired=true;return}if(isInSandboxMode()){debugLogger.debug("Skipping preconnect: sandbox mode detected");preconnectFired=true;return}if(shouldSkipPreconnect()){preconnectFired=true;return}if(detectRuntime()!=="node"){debugLogger.debug("Skipping preconnect: unsupported runtime");preconnectFired=true;return}if(!options.proxy){debugLogger.debug("Skipping preconnect dispatcher: no proxy configured");return}const proxy=options.proxy;const targetUrl=getPreconnectTargetUrl(authType,options.resolvedBaseUrl);if(!targetUrl){debugLogger.debug("No target URL for preconnect");return}preconnectFired=true;debugLogger.debug(`Preconnecting to: ${targetUrl}`);preconnectInFlight=(async()=>{await preloadRuntimeFetchModule();const dispatcher=getOrCreateSharedDispatcher(proxy);const{fetch:undiciFetch}=await loadUndici();await undiciFetch(targetUrl,{method:"HEAD",signal:AbortSignal.timeout(5e3),headers:{"User-Agent":"QwenCode-Preconnect/1.0"},dispatcher});debugLogger.debug("Preconnect completed")})().catch(error=>{const redactedError=redactProxyCredentials(String(error));debugLogger.debug(`Preconnect failed (ignored): ${redactedError}`)})}__name(preconnectApi,"preconnectApi");var debugLogger2=createDebugLogger("STARTUP_PREFETCH");var DEFERRED_IDE_CONNECT_TIMEOUT_MS=15e3;var earlyStarted=new WeakSet;var postRenderStarted=new WeakSet;function withTimeout(promise,name,timeoutMs,onTimeout=()=>{}){let timeoutId;let timedOut=false;const runTimeoutCleanup=__name(()=>{void Promise.resolve().then(onTimeout).catch(err=>{debugLogger2.debug(`${name} timeout cleanup failed:`,err)})},"runTimeoutCleanup");const timeout=new Promise((_,reject)=>{timeoutId=setTimeout(()=>{timedOut=true;runTimeoutCleanup();reject(new Error(`${name} timed out after ${timeoutMs}ms`))},timeoutMs);timeoutId.unref?.()});void promise.then(()=>{if(timedOut){runTimeoutCleanup()}},err=>{if(timedOut){debugLogger2.debug(`${name} underlying error after timeout:`,err)}});return Promise.race([promise,timeout]).finally(()=>{if(timeoutId){clearTimeout(timeoutId)}})}__name(withTimeout,"withTimeout");function runDeferredTask(name,task){recordStartupEvent("startup_prefetch_started",{name});void Promise.resolve().then(task).then(()=>{recordStartupEvent("startup_prefetch_completed",{name})}).catch(err=>{recordStartupEvent("startup_prefetch_failed",{name});debugLogger2.warn(`${name} failed:`,err)})}__name(runDeferredTask,"runDeferredTask");async function disconnectIdeAfterDeferredTimeout(){const ideClient=await IdeClient.getInstance();await ideClient.disconnect()}__name(disconnectIdeAfterDeferredTimeout,"disconnectIdeAfterDeferredTimeout");function startEarlyStartupPrefetches(config){if(earlyStarted.has(config))return;earlyStarted.add(config);try{const modelsConfig=config.getModelsConfig();const authType=modelsConfig.getCurrentAuthType();const resolvedBaseUrl=modelsConfig.getGenerationConfig().baseUrl;const proxy=config.getProxy();preconnectApi(authType,{resolvedBaseUrl,proxy})}catch(error){debugLogger2.debug(`Preconnect skipped due to error getting authType: ${error}`)}}__name(startEarlyStartupPrefetches,"startEarlyStartupPrefetches");var UPDATE_CHECK_DELAY_MS=3e3;function startPostRenderPrefetches(config,settings,options={}){if(postRenderStarted.has(config))return;postRenderStarted.add(config);if(settings.merged.general?.enableAutoUpdate!==false&&process.env[SKIP_UPDATE_CHECK_ENV_VAR]!=="true"&&!process.env[CUSTOM_SANDBOX_IMAGE_ENV_VAR]){runDeferredTask("update_check",async()=>{await new Promise(resolve=>{setTimeout(resolve,UPDATE_CHECK_DELAY_MS).unref?.()});const[{checkForUpdatesDetailed,describeUpdateCheckFailure},{handleAutoUpdate},{getInstallationInfo},{updateEventEmitter},{t}]=await Promise.all([import("./updateCheck-XWE3TWL5.js"),import("./handleAutoUpdate-PG7R3KPH.js"),import("./installationInfo-BBADHZLD.js"),import("./updateEventEmitter-HCGBOCP2.js"),import("./i18n-EGTBMA3N.js")]);const updateCheckSkippedMessage=__name(error=>t("Update check skipped ({{reason}}) \u2014 run /update to retry.",{reason:describeUpdateCheckFailure(error)}),"updateCheckSkippedMessage");try{const result=await checkForUpdatesDetailed();if(result.status==="update"){const projectRoot=config.getProjectRoot();const hostUpdateRelaunch=process.env[HOST_UPDATE_RELAUNCH_ENV_VAR];if(hostUpdateRelaunch==="true"){updateEventEmitter.emit("update-info",{message:`${result.info.message}
|
|
4
4
|
${t("Run /update to install the update on the host.")}`});return}if(hostUpdateRelaunch==="false"){updateEventEmitter.emit("update-info",{message:`${result.info.message}
|
|
5
5
|
${t("Update Qwen Code on the host, then restart the sandbox.")}`});return}const installationInfo=getInstallationInfo(projectRoot,true);if(installationInfo.packageManager==="npm"){void handleAutoUpdate(result.info,settings,projectRoot);return}if(installationInfo.updateCommand||installationInfo.isStandalone&&installationInfo.standaloneDir){if(requestUpdateOnExit()){updateEventEmitter.emit("update-info",{message:`${result.info.message}
|
|
6
6
|
${t("The update will be installed after you exit this session.")}`})}else{updateEventEmitter.emit("update-info",{message:`${result.info.message}
|
|
7
|
-
${t("Run /update to install the update.")}`})}}else{void handleAutoUpdate(result.info,settings,projectRoot)}}else if(result.status==="error"){updateEventEmitter.emit("update-failed",{message:updateCheckSkippedMessage(result.error),severity:"warning"})}}catch(error){updateEventEmitter.emit("update-failed",{message:updateCheckSkippedMessage(error),severity:"warning"});throw error}})}if(options.connectIde&&config.getIdeMode()){runDeferredTask("ide_connect",async()=>{appEvents.emit("startup-ide-connection-status-changed",{state:"connecting"});try{const{connectIdeForStartup}=await import("./initializer-
|
|
7
|
+
${t("Run /update to install the update.")}`})}}else{void handleAutoUpdate(result.info,settings,projectRoot)}}else if(result.status==="error"){updateEventEmitter.emit("update-failed",{message:updateCheckSkippedMessage(result.error),severity:"warning"})}}catch(error){updateEventEmitter.emit("update-failed",{message:updateCheckSkippedMessage(error),severity:"warning"});throw error}})}if(options.connectIde&&config.getIdeMode()){runDeferredTask("ide_connect",async()=>{appEvents.emit("startup-ide-connection-status-changed",{state:"connecting"});try{const{connectIdeForStartup}=await import("./initializer-RIKH4PCP.js");await withTimeout(connectIdeForStartup(config),"ide_connect",DEFERRED_IDE_CONNECT_TIMEOUT_MS,disconnectIdeAfterDeferredTimeout);appEvents.emit("startup-ide-connection-status-changed",{state:"connected"})}catch(err){appEvents.emit("startup-ide-connection-status-changed",{state:"failed",message:err instanceof Error?err.message:String(err)});throw err}})}if(options.initializeTelemetry){runDeferredTask("telemetry_init",()=>initializeTelemetry(config))}if(config.isInteractive()&&settings.merged.general?.batchAutoCollect!==false){runDeferredTask("batch_auto_collect",async()=>{const[{startBatchAutoCollect},{resolveEndpoint},{updateEventEmitter}]=await Promise.all([import("./batch-auto-collect-QQ5AN2VF.js"),import("./batch-YJJGMJWO.js"),import("./updateEventEmitter-HCGBOCP2.js")]);startBatchAutoCollect({projectRoot:config.getWorkingDir(),notify:__name(message=>updateEventEmitter.emit("update-info",{message}),"notify"),resolveEndpoint:__name(()=>resolveEndpoint(process.env,{settings:settings.merged,warn:__name(message=>debugLogger2.debug(message),"warn")}),"resolveEndpoint"),log:__name(message=>debugLogger2.debug(message),"log")})})}if(config.isInteractive()){runDeferredTask("background_housekeeping",async()=>{const{startBackgroundHousekeeping}=await import("./scheduler-EBQY6BOK.js");startBackgroundHousekeeping(config,settings)})}}__name(startPostRenderPrefetches,"startPostRenderPrefetches");export{startEarlyStartupPrefetches,startPostRenderPrefetches};
|
|
8
8
|
/**
|
|
9
9
|
* @license
|
|
10
10
|
* Copyright 2026 Qwen Team
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Force strict mode and setup for ESM
|
|
2
2
|
"use strict";
|
|
3
|
-
import{require_source}from"./chunk-D2NY7HVY.js";import{loadSettings}from"./chunk-
|
|
3
|
+
import{require_source}from"./chunk-D2NY7HVY.js";import{loadSettings}from"./chunk-FHFBCG6N.js";import{getCurrentLanguage,t}from"./chunk-H45OX4VY.js";import{isWorkspaceTrusted}from"./chunk-W5D2T2JK.js";import{ExtensionManager,getExtensionDescription,getExtensionDisplayName,require_prompts}from"./chunk-LDXZT3SG.js";import{resolveExtensionTelemetryProxy,resolveUsageStatisticsEnabled}from"./chunk-F63ESLTI.js";import{stripAnsi}from"./chunk-YGLM5XPP.js";import{redactUrlCredentials}from"./chunk-XHV5HLJS.js";import{writeStdoutLine}from"./chunk-SLPJ4OII.js";import{init_esbuild_shims}from"./chunk-VKDAXTCZ.js";import{__name,__toESM}from"./chunk-KBWJGX7I.js";init_esbuild_shims();init_esbuild_shims();var import_chalk=__toESM(require_source(),1);var import_prompts=__toESM(require_prompts(),1);async function requestConsentNonInteractive(consentDescription){writeStdoutLine(consentDescription);const result=await promptForConsentNonInteractive(t("Do you want to continue? [Y/n]: "));return result}__name(requestConsentNonInteractive,"requestConsentNonInteractive");async function requestChoicePluginNonInteractive(marketplace){const plugins=marketplace.plugins;if(plugins.length===0){throw new Error(t("No plugins available in this marketplace."))}const choices=plugins.map(plugin=>({title:import_chalk.default.green(import_chalk.default.bold(`[${plugin.name}]`)),value:plugin.name}));const response=await(0,import_prompts.default)({type:"select",name:"plugin",message:t('Select a plugin to install from marketplace "{{name}}":',{name:marketplace.name}),choices,initial:0});if(response.plugin===void 0){throw new Error(t("Plugin selection cancelled."))}return response.plugin}__name(requestChoicePluginNonInteractive,"requestChoicePluginNonInteractive");async function requestConsentInteractive(consentDescription,addExtensionUpdateConfirmationRequest){return promptForConsentInteractive(consentDescription+"\n\n"+t("Do you want to continue?"),addExtensionUpdateConfirmationRequest)}__name(requestConsentInteractive,"requestConsentInteractive");async function promptForConsentNonInteractive(prompt){const readline=await import("node:readline");const rl=readline.createInterface({input:process.stdin,output:process.stdout});return new Promise(resolve=>{rl.question(prompt,answer=>{rl.close();resolve(["y",""].includes(answer.trim().toLowerCase()))})})}__name(promptForConsentNonInteractive,"promptForConsentNonInteractive");async function promptForConsentInteractive(prompt,addExtensionUpdateConfirmationRequest){return new Promise(resolve=>{addExtensionUpdateConfirmationRequest({prompt,onConfirm:__name(resolvedConfirmed=>{resolve(resolvedConfirmed)},"onConfirm")})})}__name(promptForConsentInteractive,"promptForConsentInteractive");function extensionConsentString(extensionConfig,commands=[],skills=[],subagents=[],originSource="QwenCode",workflows=[]){const output=[];if(originSource!=="QwenCode"&&originSource!=="AgentPlugins"){output.push(t("You are installing an extension from {{originSource}}. Some features may not work perfectly with Qwen Code.",{originSource}))}const mcpServerEntries=Object.entries(extensionConfig.mcpServers||{});const displayLabel=extensionConfig.displayName??extensionConfig.name;output.push(t('Installing extension "{{name}}".',{name:displayLabel}));if(typeof extensionConfig.description==="string"&&extensionConfig.description){output.push(stripAnsi(extensionConfig.description))}output.push(t("**Extensions may introduce unexpected behavior. Ensure you have investigated the extension source and trust the author.**"));if(mcpServerEntries.length){output.push(t("This extension will run the following MCP servers:"));for(const[key,mcpServer]of mcpServerEntries){const isLocal=!!mcpServer.command;const source=mcpServer.httpUrl??`${mcpServer.command||""}${mcpServer.args?" "+mcpServer.args.join(" "):""}`;output.push(` * ${key} (${isLocal?t("local"):t("remote")}): ${source}`)}}if(commands&&commands.length>0){output.push(t("This extension will add the following commands: {{commands}}.",{commands:commands.join(", ")}))}if(extensionConfig.contextFileName){const fileName=Array.isArray(extensionConfig.contextFileName)?extensionConfig.contextFileName.join(", "):extensionConfig.contextFileName;output.push(t("This extension will append info to your QWEN.md context using {{fileName}}",{fileName}))}if(skills.length>0){output.push(t("This extension will install the following skills:"));for(const skill of skills){output.push(` * ${import_chalk.default.bold(skill.name)}: ${skill.description}`)}}if(subagents.length>0){output.push(t("This extension will install the following subagents:"));for(const subagent of subagents){output.push(` * ${import_chalk.default.bold(subagent.name)}: ${subagent.description}`)}}if(workflows.length>0){output.push(t("This extension will install the following workflows (JavaScript scripts that can start subagents):"));for(const workflow of workflows){const description=stripAnsi(workflow.description).replace(/\s+/g," ");output.push(` * ${import_chalk.default.bold(workflow.name)}: ${description}`)}}return output.join("\n")}__name(extensionConsentString,"extensionConsentString");function changedWorkflowScripts(workflows,previousWorkflows){const previousDigests=new Map(previousWorkflows.map(workflow=>[workflow.name,workflow.contentDigest]));return workflows.filter(workflow=>{const previous=previousDigests.get(workflow.name);return previous!==void 0&&previous!==workflow.contentDigest}).map(workflow=>workflow.name)}__name(changedWorkflowScripts,"changedWorkflowScripts");var requestConsentOrFail=__name(async(requestConsent,options)=>{if(!options)return;const{extensionConfig,originSource="QwenCode",commands=[],skills=[],subagents=[],workflows=[],previousExtensionConfig,previousCommands=[],previousSkills=[],previousSubagents=[],previousWorkflows=[]}=options;const extensionConsent=extensionConsentString(extensionConfig,commands,skills,subagents,originSource,workflows);const changedScripts=previousExtensionConfig?changedWorkflowScripts(workflows,previousWorkflows):[];if(previousExtensionConfig){const previousExtensionConsent=extensionConsentString(previousExtensionConfig,previousCommands,previousSkills,previousSubagents,originSource,previousWorkflows);if(previousExtensionConsent===extensionConsent&&changedScripts.length===0){return}}const consent=changedScripts.length>0?`${extensionConsent}
|
|
4
4
|
${t("These workflow scripts changed since the installed version: {{names}}.",{names:changedScripts.join(", ")})}`:extensionConsent;if(!await requestConsent(consent)){throw new Error(t('Installation cancelled for "{{name}}".',{name:extensionConfig.name}))}},"requestConsentOrFail");var import_chalk2=__toESM(require_source(),1);import*as os from"node:os";async function getExtensionManager(){const workspaceDir=process.cwd();const settings=loadSettings(workspaceDir).merged;const extensionManager=new ExtensionManager({workspaceDir,locale:getCurrentLanguage(),requestConsent:requestConsentOrFail.bind(null,requestConsentNonInteractive),requestChoicePlugin:requestChoicePluginNonInteractive,isWorkspaceTrusted:isWorkspaceTrusted(settings).isTrusted??true,usageStatisticsEnabled:resolveUsageStatisticsEnabled(settings.privacy?.usageStatisticsEnabled),proxy:resolveExtensionTelemetryProxy(settings.proxy)});await extensionManager.refreshCache();return extensionManager}__name(getExtensionManager,"getExtensionManager");var EXTENSION_COMMAND_SCOPES=["User","Workspace"];function extensionCommandScopesList(){return EXTENSION_COMMAND_SCOPES.map(s=>s.toLowerCase()).join(", ")}__name(extensionCommandScopesList,"extensionCommandScopesList");function resolveExtensionCommandScope(scope){if(!scope){return"User"}const normalized=scope.toLowerCase();const matched=EXTENSION_COMMAND_SCOPES.find(candidate=>candidate.toLowerCase()===normalized);if(matched){return matched}throw new Error(t("Invalid scope: {{scope}}. Please use one of {{scopes}}.",{scope,scopes:extensionCommandScopesList()}))}__name(resolveExtensionCommandScope,"resolveExtensionCommandScope");function extensionToOutputString(extension,extensionManager,workspaceDir,inline=false){const cwd=workspaceDir;const userEnabled=extensionManager.isEnabled(extension.config.name,os.homedir());const workspaceEnabled=extensionManager.isEnabled(extension.config.name,cwd);const status=workspaceEnabled?import_chalk2.default.green("\u2713"):import_chalk2.default.red("\u2717");const locale=getCurrentLanguage();const displayLabel=getExtensionDisplayName(extension,locale);let output=`${inline?"":status} ${displayLabel} (${extension.config.version})`;const desc=getExtensionDescription(extension,locale);if(desc){output+=`
|
|
5
5
|
${t("Description:")} ${stripAnsi(desc)}`}output+=`
|
|
6
6
|
${t("Path:")} ${extension.path}`;if(extension.installMetadata){output+=`
|