@qwen-code/qwen-code 0.23.5-dev.codemode-responses.20260915.f024b37689 → 0.23.5-preview.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundled/computer-use/SKILL.md +24 -3
- package/bundled/qc-helper/docs/configuration/model-providers.md +43 -0
- package/bundled/qc-helper/docs/configuration/settings.md +10 -9
- package/bundled/qc-helper/docs/extension/agent-plugins.md +1 -0
- package/bundled/qc-helper/docs/extension/introduction.md +49 -0
- package/bundled/qc-helper/docs/features/channels/dingtalk.md +39 -4
- package/bundled/qc-helper/docs/features/channels/overview.md +12 -0
- package/bundled/qc-helper/docs/features/commands.md +57 -52
- package/bundled/qc-helper/docs/features/computer-use.md +1 -1
- package/bundled/qc-helper/docs/features/goals.md +8 -0
- package/bundled/qc-helper/docs/features/hooks.md +16 -0
- package/bundled/qc-helper/docs/qwen-serve.md +3 -1
- package/bundled/workflow-authoring/SKILL.md +48 -22
- package/chunks/{MaxSizedBox-BFMIFJWT.js → MaxSizedBox-FCF6M53W.js} +40 -43
- package/chunks/{StandaloneSessionPicker-4ZH7MOVG.js → StandaloneSessionPicker-V635V72I.js} +60 -63
- package/chunks/{acp-startup-profiler-RUQNTNU5.js → acp-startup-profiler-MOOU37VM.js} +2 -2
- package/chunks/{acp-subagent-executor-AHMVA4P3.js → acp-subagent-executor-TND6W2O5.js} +46 -47
- package/chunks/{acpAgent-UMAJ3XR3.js → acpAgent-3DPWZTNC.js} +954 -322
- package/chunks/{agent-CXB2CCQN.js → agent-KIHGINKN.js} +27 -30
- package/chunks/{agent-headless-7D5ZC736.js → agent-headless-EJ4QOUSM.js} +27 -30
- package/chunks/{anthropicContentGenerator-H5YPXIDE.js → anthropicContentGenerator-4FGOM5LK.js} +46 -64
- package/chunks/{artifact-tool-MFGORTWZ.js → artifact-tool-MUTNH4NI.js} +1 -1
- package/chunks/{askUserQuestion-WS4GUT7C.js → askUserQuestion-AKIRLVB5.js} +1 -1
- package/chunks/bareMode-QWKZPLPX.js +14 -0
- package/chunks/{bridge-A2WKX6IK.js → bridge-MUX5YJZT.js} +46 -49
- package/chunks/{ca-GZ4FDJU2.js → ca-WC3A5B3Q.js} +12 -1
- package/chunks/{channel-management-service-AFVIT4VH.js → channel-management-service-RRILWSXX.js} +4 -4
- package/chunks/{channel-settings-store-AXJIN7HG.js → channel-settings-store-7CBIRZER.js} +51 -54
- package/chunks/{channel-worker-group-JR6JOELM.js → channel-worker-group-3DUJFZJR.js} +8 -8
- package/chunks/{channel-worker-manager-AVKJEZFL.js → channel-worker-manager-E5UW2VLA.js} +8 -8
- package/chunks/{channel-worker-supervisor-OOYY7BAQ.js → channel-worker-supervisor-VN33GSEC.js} +5 -5
- package/chunks/{chunk-2YMRRI2C.js → chunk-2C5TR6HN.js} +82 -9
- package/chunks/{chunk-YDFOHRS5.js → chunk-2GP6BQ2J.js} +1 -1
- package/chunks/{chunk-RN6BU77T.js → chunk-347O2YZJ.js} +158 -290
- package/chunks/{chunk-LTINUI3O.js → chunk-36NRLIR6.js} +10 -8
- package/chunks/{chunk-AXZMWAJV.js → chunk-36SDZ2Q4.js} +8 -0
- package/chunks/{chunk-QR4Q425T.js → chunk-3BZI5GDP.js} +1 -1
- package/chunks/{chunk-C3YMBSLR.js → chunk-3HTUE6ZR.js} +3 -3
- package/chunks/{chunk-QS5Q5F42.js → chunk-3LLEB5CU.js} +2 -2
- package/chunks/{chunk-FPPG5Y3W.js → chunk-3UGMLA4V.js} +10 -8
- package/chunks/{chunk-66N6C4EH.js → chunk-3WILPKTJ.js} +2 -2
- package/chunks/{chunk-SROLVJFY.js → chunk-3WWPEFMX.js} +1 -1
- package/chunks/{chunk-ZKIAGIGH.js → chunk-3XBUCOWS.js} +1 -1
- package/chunks/{chunk-6RQFMGN2.js → chunk-43Y26NPF.js} +3 -3
- package/chunks/{chunk-INGBUYL6.js → chunk-4FLUQWJ4.js} +1 -1
- package/chunks/{chunk-S77FFY67.js → chunk-4JFLRHNE.js} +1 -1
- package/chunks/{chunk-MJHLKWGJ.js → chunk-4QPVZA5J.js} +70 -23
- package/chunks/{chunk-XX5HQLCZ.js → chunk-6OTF7TTE.js} +32 -1
- package/chunks/{chunk-4Y2I3CI3.js → chunk-6USYH3EU.js} +99 -6
- package/chunks/{chunk-Q3TFRP5G.js → chunk-7D4CV7JH.js} +102 -9
- package/chunks/{chunk-EWJTAP3Y.js → chunk-7O5PYQ3M.js} +20 -1
- package/chunks/chunk-ADN5KESB.js +28 -0
- package/chunks/chunk-AKRSSKUT.js +229 -0
- package/chunks/{chunk-54YUXX7X.js → chunk-AQP3H22J.js} +1 -1
- package/chunks/{chunk-EQWKIA72.js → chunk-AUX2FL5T.js} +24 -7
- package/chunks/{chunk-YGFJ6BRT.js → chunk-AZCTY64Z.js} +1 -1
- package/chunks/{chunk-QLX4D55R.js → chunk-B5TJK7B3.js} +1 -1
- package/chunks/{chunk-HXMDDII6.js → chunk-B6RMK4ED.js} +4 -4
- package/chunks/{chunk-UCKM6KCJ.js → chunk-BHG3H6OZ.js} +1 -1
- package/chunks/{chunk-JLF2AQAL.js → chunk-BHVF3R6B.js} +7 -5
- package/chunks/{chunk-HFJSQ4GL.js → chunk-BTICBRPL.js} +1 -1
- package/chunks/{chunk-KZCK5JUN.js → chunk-C3T6HPNM.js} +1 -1
- package/chunks/{chunk-FCLMJS6N.js → chunk-CDDP4ONL.js} +164 -27
- package/chunks/{chunk-Y3ZXDBUL.js → chunk-CQPM66MG.js} +4 -4
- package/chunks/{chunk-WKVZES7O.js → chunk-CXONOVBN.js} +1 -1
- package/chunks/{chunk-TYBRGFYL.js → chunk-CXY6BICQ.js} +501 -479
- package/chunks/{chunk-W23HOFDK.js → chunk-D3KVGQUV.js} +1 -1
- package/chunks/{chunk-LMJSPC55.js → chunk-D7JMO2GP.js} +3 -7
- package/chunks/{chunk-CXXAZ2LZ.js → chunk-DC4ZNGH4.js} +1 -1
- package/chunks/{chunk-FMLBBXHB.js → chunk-DRAX5YAI.js} +2 -2
- package/chunks/{chunk-DOTF2PF2.js → chunk-DRD6VBNH.js} +1 -1
- package/chunks/chunk-DX6JTDMR.js +105 -0
- package/chunks/{chunk-MNRK6MIH.js → chunk-E2VSBAFA.js} +53 -11
- package/chunks/{chunk-QJKR2P2K.js → chunk-EIBECN2J.js} +3 -3
- package/chunks/{chunk-LWWRJRCD.js → chunk-ESBYWATJ.js} +1 -1
- package/chunks/{chunk-3544ZEGZ.js → chunk-FASYATAZ.js} +5 -7
- package/chunks/{chunk-6YUS5JCV.js → chunk-FBY32737.js} +4 -4
- package/chunks/{chunk-LBWIJ5T7.js → chunk-FCPJXKDG.js} +10 -7
- package/chunks/{chunk-FX6GJIPZ.js → chunk-FEDFZBGR.js} +3 -3
- package/chunks/{chunk-DQ4LBRZN.js → chunk-FIJODK52.js} +3 -3
- package/chunks/{chunk-HVSRWLOW.js → chunk-FX6PZBOV.js} +3 -3
- package/chunks/{chunk-L6DIANLD.js → chunk-G45B3INR.js} +1 -1
- package/chunks/{chunk-EYLUKEYW.js → chunk-GI7SLDOI.js} +2 -2
- package/chunks/chunk-GJKP6XOB.js +1092 -0
- package/chunks/{chunk-I6YJZGHS.js → chunk-GSAOVDTH.js} +9 -9
- package/chunks/{chunk-XK4UQSIR.js → chunk-H6L4NEAT.js} +1 -1
- package/chunks/{chunk-GMCEFKNR.js → chunk-HNFKYKHH.js} +103 -22
- package/chunks/{chunk-6XDB3FR4.js → chunk-HX4WXX3H.js} +301 -138
- package/chunks/{chunk-HG46TTAG.js → chunk-HXUI5D4H.js} +1 -1
- package/chunks/{chunk-QI4WBHPF.js → chunk-HYHSMTRA.js} +4 -4
- package/chunks/{chunk-ZUKC5J6Q.js → chunk-IKBEIDOH.js} +14 -14
- package/chunks/{chunk-LCAJ63TF.js → chunk-INN5ORKX.js} +1 -1
- package/chunks/{chunk-GNV2SFO7.js → chunk-IVFTLUZD.js} +26 -1
- package/chunks/{chunk-GNKSR3FU.js → chunk-IXO2OCIP.js} +2 -2
- package/chunks/{chunk-SNT634Q6.js → chunk-K4XMAIRX.js} +30 -33
- package/chunks/{chunk-WBP64MZR.js → chunk-KAYC5FBN.js} +5269 -2785
- package/chunks/chunk-KEM7MWS7.js +3541 -0
- package/chunks/{chunk-ADQUK6WA.js → chunk-KVC7HZWK.js} +1 -1
- package/chunks/{chunk-UQXURNLM.js → chunk-KVQ3QL4K.js} +3 -3
- package/chunks/{chunk-7U5G6JXI.js → chunk-KWYTSSTJ.js} +105 -6
- package/chunks/{chunk-Q4G2YPI4.js → chunk-L2A5VBDL.js} +3019 -2352
- package/chunks/{chunk-WD6YQI5M.js → chunk-L3SNMEDW.js} +1 -1
- package/chunks/{chunk-BYUAT5OC.js → chunk-L7TJUPNR.js} +19 -3
- package/chunks/{chunk-ABNX6E6K.js → chunk-LFKXIOGC.js} +1 -1
- package/chunks/{chunk-GFAK6DYU.js → chunk-LO2UWNO5.js} +2 -2
- package/chunks/{chunk-67ZDP7UX.js → chunk-M22WLKLI.js} +5 -5
- package/chunks/{chunk-54B2LTKP.js → chunk-M23GFJ5B.js} +24 -5
- package/chunks/{chunk-VGY2RGXL.js → chunk-M4U2LTD2.js} +1 -1
- package/chunks/{chunk-ZNI3YJHS.js → chunk-MFDKHGTD.js} +1 -1
- package/chunks/{chunk-R7OO56VZ.js → chunk-MMRGG6R4.js} +1 -1
- package/chunks/{chunk-E6IR653O.js → chunk-MO4XID7S.js} +1 -1
- package/chunks/{chunk-NJ4ZNDVP.js → chunk-NKTMUPHJ.js} +3 -6
- package/chunks/{chunk-4DTFTPTU.js → chunk-NQ272MQG.js} +1 -1
- package/chunks/{chunk-DWKFTUGI.js → chunk-OALXNGUA.js} +6 -6
- package/chunks/{chunk-FBDHP23D.js → chunk-OSG23MR3.js} +1 -1
- package/chunks/{chunk-NJ2OFVUX.js → chunk-P42KMMU6.js} +860 -1
- package/chunks/{chunk-5KJ54DY3.js → chunk-PF7GAP6K.js} +60 -58
- package/chunks/{chunk-MQRLLBMQ.js → chunk-PPJSG2PU.js} +2 -2
- package/chunks/{chunk-EPVEPTI3.js → chunk-PZRXWQUA.js} +753 -18
- package/chunks/{chunk-VI5UVPOB.js → chunk-Q54O3EIA.js} +30 -28
- package/chunks/{chunk-QTUQV33C.js → chunk-QGEISOJ2.js} +4 -4
- package/chunks/{chunk-XKRYQOHS.js → chunk-QHSOINX6.js} +2 -2
- package/chunks/{chunk-Z6Q7I37O.js → chunk-QIPLWW6Q.js} +1 -1
- package/chunks/chunk-QMENOK5T.js +1246 -0
- package/chunks/chunk-QT6Z2IBF.js +347 -0
- package/chunks/{chunk-TBSCTWKF.js → chunk-RN6A53UJ.js} +25 -0
- package/chunks/{chunk-E7ZTAOJZ.js → chunk-RRI764F7.js} +21 -19
- package/chunks/{chunk-YI2YCNSP.js → chunk-SENYKRII.js} +1 -1
- package/chunks/chunk-SFHX5G2S.js +2796 -0
- package/chunks/chunk-SK3RZOPS.js +34 -0
- package/chunks/{chunk-SKYOAH4Z.js → chunk-SOLRBF7L.js} +13 -9
- package/chunks/{chunk-5WLF44DS.js → chunk-SSWTA7CH.js} +12 -12
- package/chunks/{chunk-IAS753HG.js → chunk-SYMXYRM5.js} +11 -2
- package/chunks/{chunk-FGROOEKM.js → chunk-TDKUXSJO.js} +34 -6
- package/chunks/{chunk-ZJ7JQUGY.js → chunk-TKF4JINY.js} +1 -1
- package/chunks/{chunk-ZOQ6HC7U.js → chunk-TPY6HW55.js} +4 -4
- package/chunks/{chunk-EDB556X7.js → chunk-TRZ22SG5.js} +1 -1
- package/chunks/{chunk-FHSOZSBO.js → chunk-TXTCM3TC.js} +4 -4
- package/chunks/{chunk-5ODRE7E5.js → chunk-U4AASWUQ.js} +28 -12
- package/chunks/{chunk-PPE7VUMD.js → chunk-UQGRJTDK.js} +2 -2
- package/chunks/{chunk-JO67LVXW.js → chunk-UZSB57EV.js} +6 -8
- package/chunks/{chunk-UY4OCBX4.js → chunk-V4JJAVHQ.js} +2 -2
- package/chunks/chunk-VEXUA6DX.js +1026 -0
- package/chunks/{chunk-ME4JBHSB.js → chunk-VQDWCQOE.js} +2 -0
- package/chunks/{chunk-ZC75SULX.js → chunk-VU3XMZ5I.js} +23 -4
- package/chunks/{chunk-A2UYI473.js → chunk-WL36KHUQ.js} +6 -6
- package/chunks/{chunk-IWOJ2FHG.js → chunk-WNQIJTOP.js} +8 -8
- package/chunks/{chunk-IANIY25T.js → chunk-WSJI6ODG.js} +99 -30
- package/chunks/{chunk-3CKAOJ4L.js → chunk-WZWTY7SG.js} +6 -6
- package/chunks/{chunk-EKMJR7M3.js → chunk-X7AYIXC7.js} +1 -1
- package/chunks/{chunk-IBRQG2MP.js → chunk-XAJZFGD2.js} +11 -11
- package/chunks/{chunk-VRQZESKP.js → chunk-XICCGDWF.js} +2 -2
- package/chunks/{chunk-L5R4D5T4.js → chunk-Y2KJC55Y.js} +12 -7
- package/chunks/{chunk-2S2WIGCM.js → chunk-Y4NNIGYO.js} +1 -1
- package/chunks/{chunk-J7LBAKDH.js → chunk-YL3UJML3.js} +7 -7
- package/chunks/{chunk-GSS4SZNG.js → chunk-YP2K3WOS.js} +40 -56
- package/chunks/{chunk-ZZUXUBEB.js → chunk-YQQ2U7AS.js} +8 -5
- package/chunks/{chunk-FAWTMDX7.js → chunk-YXHY6BKS.js} +15 -0
- package/chunks/{chunk-FIP5QS2U.js → chunk-YZXSDPOQ.js} +140 -39
- package/chunks/{chunk-WATHOB6X.js → chunk-ZFHKUQZ4.js} +3 -3
- package/chunks/{chunk-R5OA3ONY.js → chunk-ZMYKNKET.js} +6 -6
- package/chunks/{codex-subagent-executor-LANZAZPH.js → codex-subagent-executor-AEAIQZDC.js} +48 -49
- package/chunks/{config-utils-CRK2LQPA.js → config-utils-KX2YS725.js} +43 -46
- package/chunks/{contextCommand-GY5X3LIY.js → contextCommand-RV6Y5LNJ.js} +41 -44
- package/chunks/{core-runtime-IJIV2LHP.js → core-runtime-ZI4RTOJQ.js} +45 -48
- package/chunks/{create-sub-session-MNIVRHGB.js → create-sub-session-BBWFQARJ.js} +46 -48
- package/chunks/{daemon-NJB4PWZ7.js → daemon-INCM4VBX.js} +3 -1
- package/chunks/{daemon-git-worktree-guard-W6Z2BGDH.js → daemon-git-worktree-guard-KECEMV6A.js} +39 -42
- package/chunks/{daemon-status-provider-TJF3APU3.js → daemon-status-provider-NULJNAEV.js} +53 -56
- package/chunks/{daemon-trust-policy-6INCISDU.js → daemon-trust-policy-S4KWGPV3.js} +47 -50
- package/chunks/{daemon-trust-policy-monitor-JRTAQG54.js → daemon-trust-policy-monitor-546N5ZVL.js} +47 -50
- package/chunks/{de-VGY3VNBU.js → de-6AVKPTXQ.js} +11 -0
- package/chunks/{deferred-core-runtime-2JRTPTNM.js → deferred-core-runtime-T23ZT443.js} +39 -42
- package/chunks/{dist-NIOJXMGY.js → dist-4P3ZJYGI.js} +1 -1
- package/chunks/{dist-VDLSBCLM.js → dist-7MGRENQ5.js} +1 -1
- package/chunks/{dist-SE4J6Z4O.js → dist-BNW423XT.js} +326 -77
- package/chunks/{dist-TFGETXFN.js → dist-CESMUYGN.js} +4 -4
- package/chunks/{dist-MPUZZOG5.js → dist-DBBOFWSC.js} +1 -1
- package/chunks/{dist-T6DDPDLQ.js → dist-G5UMXIGF.js} +1 -1
- package/chunks/{dist-PA7WPFVE.js → dist-UXVNLQHG.js} +3 -3
- package/chunks/{dist-GUB7QRYA.js → dist-VA4LREAQ.js} +2 -2
- package/chunks/{dist-2QYIVNS6.js → dist-XDRTR4QP.js} +1 -1
- package/chunks/{edit-JDIXXCYB.js → edit-CMSQB7NP.js} +27 -30
- package/chunks/{en-E5ZO5TZW.js → en-56QLKXS2.js} +23 -1
- package/chunks/{enter-worktree-CAARFWBI.js → enter-worktree-DA6A4XC5.js} +3 -3
- package/chunks/{enterPlanMode-YTNTBZBN.js → enterPlanMode-UDPMNESD.js} +27 -30
- package/chunks/{environment-UAI5L52V.js → environment-TSQJUTPV.js} +42 -45
- package/chunks/{errors-J4UCDCW5.js → errors-RIVYJS6T.js} +41 -44
- package/chunks/{exit-worktree-JXGGUOBP.js → exit-worktree-4H6Z2VQI.js} +3 -3
- package/chunks/{exitPlanMode-YMWJ2EO7.js → exitPlanMode-BYBBFN2T.js} +27 -30
- package/chunks/{fast-path-MBAN7TK3.js → fast-path-F2CYDDZ4.js} +4 -4
- package/chunks/{fast-path-settings-XDYX7X5Z.js → fast-path-settings-N2VGRGDJ.js} +2 -2
- package/chunks/{fr-UAZJJH5N.js → fr-EBUDHJL3.js} +11 -0
- package/chunks/{glob-YEM24E3Z.js → glob-Z2JMJKKN.js} +27 -30
- package/chunks/{goal-tools-LJIVH5T6.js → goal-tools-HXVVLGCV.js} +27 -30
- package/chunks/{handleAutoUpdate-DYCSYDYL.js → handleAutoUpdate-FZP45KOR.js} +43 -46
- package/chunks/{i18n-PTAV7SN3.js → i18n-OTB62AKW.js} +40 -43
- package/chunks/{image-gen-5G2TQ3DY.js → image-gen-HIAZCB5T.js} +6 -7
- package/chunks/{initializer-MPXTKQA4.js → initializer-4JXZEC4B.js} +47 -50
- package/chunks/{installationInfo-U5EFA3OL.js → installationInfo-2IJV5QKC.js} +39 -42
- package/chunks/{ja-2RITCMAJ.js → ja-NCDT4CGV.js} +11 -0
- package/chunks/{list-YOE25QUI.js → list-KQSQ4A5G.js} +50 -53
- package/chunks/{llm-ZZ2WNQMC.js → llm-LSUBOJAR.js} +154 -974
- package/chunks/{llm-content-generator-CG2HRJZC.js → llm-content-generator-MLIONRXE.js} +17 -12
- package/chunks/{loadedSettingsAdapter-NPGWGURF.js → loadedSettingsAdapter-TZTTNRHI.js} +47 -50
- package/chunks/{loggingContentGenerator-TUL6SJVL.js → loggingContentGenerator-TUPEXFMM.js} +31 -34
- package/chunks/{loop-wakeup-VG6CGBQA.js → loop-wakeup-ZBVRI6VH.js} +1 -1
- package/chunks/{managed-npm-update-YUDSCJP3.js → managed-npm-update-WEA5XMFZ.js} +40 -43
- package/chunks/{mcp-EX3GDQVO.js → mcp-TFDTUPIA.js} +47 -50
- package/chunks/{model-configuration-6DEKTXJI.js → model-configuration-ZCAKKIOF.js} +48 -51
- package/chunks/{modelConfigUtils-4NA2MHEE.js → modelConfigUtils-J3ZPW7ZK.js} +41 -44
- package/chunks/{monitor-PPUGNAWR.js → monitor-CI7YE7MT.js} +29 -32
- package/chunks/{nonInteractiveCli-6TW2XYP5.js → nonInteractiveCli-GPT3TVOK.js} +96 -98
- package/chunks/{notebook-edit-4MUXHZHT.js → notebook-edit-3WCVRNGL.js} +27 -30
- package/chunks/{openaiContentGenerator-5J73W5XZ.js → openaiContentGenerator-OGILGUZE.js} +12 -17
- package/chunks/{openaiResponsesContentGenerator-AWRYZLJU.js → openaiResponsesContentGenerator-NXOXUPFM.js} +45 -13
- package/chunks/{pidfile-M7WELKBB.js → pidfile-GBTBIGHF.js} +39 -42
- package/chunks/{process-registry-X6ZCASEN.js → process-registry-7LAPI3ZB.js} +1 -1
- package/chunks/{processUtils-SPRINFNY.js → processUtils-O4II3RYH.js} +2 -2
- package/chunks/{prompt-terminal-ledger-25BRD7FX.js → prompt-terminal-ledger-ILIXZI3E.js} +40 -43
- package/chunks/{pt-5ZF7ZQUV.js → pt-FYYFWYUC.js} +11 -0
- package/chunks/{qwenContentGenerator-H5AAKXPC.js → qwenContentGenerator-I4LRYADV.js} +33 -36
- package/chunks/{qwenOAuth2-WIEUEFEY.js → qwenOAuth2-3J66TOT5.js} +6 -7
- package/chunks/{read-file-ILGEFPB3.js → read-file-G4XKW2CS.js} +5 -9
- package/chunks/{record-artifact-PXMNP7GZ.js → record-artifact-L3CFJOMA.js} +2 -2
- package/chunks/{report-findings-W6GR7SYZ.js → report-findings-LY5HQY4K.js} +3 -3
- package/chunks/{resumeHistoryUtils-RB52QOCH.js → resumeHistoryUtils-YPJU4XFE.js} +44 -47
- package/chunks/{ripGrep-O6QAFHQK.js → ripGrep-AAKMALLM.js} +7 -11
- package/chunks/{ru-7BNZFQKG.js → ru-RHEB3RNS.js} +11 -0
- package/chunks/{run-qwen-serve-5NO3TKUL.js → run-qwen-serve-ZVEKGS7Y.js} +177 -98
- package/chunks/{runtime-G2YUYMSZ.js → runtime-SJCRYNPA.js} +52 -55
- package/chunks/safe-mode-KLGUG54M.js +11 -0
- package/chunks/sandbox-UIXL423Z.js +146 -0
- package/chunks/sandboxConfig-CY343YNJ.js +114 -0
- package/chunks/{scheduled-tasks-HDHV3URA.js → scheduled-tasks-5UGBEVNZ.js} +50 -53
- package/chunks/{scheduler-6MDJX2ZK.js → scheduler-GCZYLZ2P.js} +41 -44
- package/chunks/{sdk-exporters-http-3R2TRQHE.js → sdk-exporters-http-DR4G663K.js} +1 -1
- package/chunks/{sdk-impl-4WF3VZ2F.js → sdk-impl-SJR26MQF.js} +3 -3
- package/chunks/{send-message-UMJKN27Q.js → send-message-DN76MXDX.js} +6 -6
- package/chunks/{serve-Z2EJQYKB.js → serve-2XXQLVK2.js} +48 -51
- package/chunks/{server-JTNBK3LH.js → server-UHMKPCAZ.js} +408 -211
- package/chunks/{session-5YK2BXH4.js → session-ZLUK7E4P.js} +108 -108
- package/chunks/{session-attachments-root-QO3VFJS6.js → session-attachments-root-DHQM5IEZ.js} +39 -42
- package/chunks/{session-pr-refresh-OTK3HCJZ.js → session-pr-refresh-3OMTQWCZ.js} +48 -51
- package/chunks/{settings-2VKLACYV.js → settings-P4DHIIUP.js} +50 -53
- package/chunks/{shell-64NAVGMS.js → shell-IMFUVQQ5.js} +27 -30
- package/chunks/{skill-R3ALMLLM.js → skill-NB5RJGZW.js} +7 -11
- package/chunks/{skill-settings-HZ34TUMP.js → skill-settings-IXG5CTQO.js} +47 -50
- package/chunks/{spawnChannel-XGFWHEIK.js → spawnChannel-Q3YALTCJ.js} +44 -45
- package/chunks/{standalone-update-R32Y3XRR.js → standalone-update-H5OJ7MM7.js} +41 -44
- package/chunks/{start-opentui-ui-YGJOUE2H.js → start-opentui-ui-JKAIWGF7.js} +733 -386
- package/chunks/{startInteractiveUI-5ZEVKSFF.js → startInteractiveUI-YRPOT6GH.js} +370 -337
- package/chunks/task-create-75HVPEAH.js +1 -1
- package/chunks/{team-create-GCVUXJLE.js → team-create-2XTBYRJF.js} +31 -34
- package/chunks/{team-plan-approval-NOL62FJD.js → team-plan-approval-CFNWW7ZQ.js} +27 -30
- package/chunks/{terminal-image-renderer-WG5TLPGC.js → terminal-image-renderer-UDPJPGPQ.js} +39 -42
- package/chunks/{theme-manager-HDS4YFPW.js → theme-manager-SK57EKMO.js} +39 -42
- package/chunks/{tool-search-HMT5GYUR.js → tool-search-ZHTJU2MV.js} +5 -9
- package/chunks/{total-session-admission-Y5RCHEXO.js → total-session-admission-UUZBDQCG.js} +47 -50
- package/chunks/{tree-sitter-LSORDVZ3.js → tree-sitter-4D7QS7F6.js} +1 -1
- package/chunks/{tree-sitter-bash-UARELQ6C.js → tree-sitter-bash-VEJGF5XF.js} +1 -1
- package/chunks/{trustedFolders-3Y2WCXMR.js → trustedFolders-4LDBLNTS.js} +40 -43
- package/chunks/{update-relaunch-MTJ32SLF.js → update-relaunch-LI7GRP36.js} +5 -5
- package/chunks/{updateCheck-YFX3VY6O.js → updateCheck-PKSSORPO.js} +43 -46
- package/chunks/{useAutoAcceptIndicator-FCHNQPMD.js → useAutoAcceptIndicator-I32UEQPI.js} +50 -53
- package/chunks/{validateNonInterActiveAuth-HUFQKCGG.js → validateNonInterActiveAuth-YFPCYYNL.js} +93 -95
- package/chunks/{version-S5TGWCA3.js → version-4MTL4JVU.js} +1 -1
- package/chunks/{web-fetch-23M7BYHB.js → web-fetch-O6RG6ISB.js} +9 -13
- package/chunks/{web-search-F5PNIQUA.js → web-search-JHAXVEMD.js} +9 -14
- package/chunks/{web-shell-static-T7UGLVE4.js → web-shell-static-FFWCUUZS.js} +8 -4
- package/chunks/{workflow-BLJLID2C.js → workflow-O7L6VDYU.js} +396 -113
- package/chunks/{workspace-providers-status-UH7KLZDT.js → workspace-providers-status-WRX6CJM4.js} +53 -56
- package/chunks/{workspace-registration-store-3SA3V7BA.js → workspace-registration-store-7G4E7YPY.js} +1 -1
- package/chunks/{workspace-registry-C6C6EKQ5.js → workspace-registry-SXIMGT4D.js} +47 -50
- package/chunks/{workspace-runtime-coordinator-RAI6XDJB.js → workspace-runtime-coordinator-7DOEHXYT.js} +47 -50
- package/chunks/{workspace-service-H7UTJYJU.js → workspace-service-HDXOZMYC.js} +53 -56
- package/chunks/{workspace-skills-status-FPVC7XXK.js → workspace-skills-status-VN4L37CA.js} +50 -53
- package/chunks/{workspace-trust-reconciler-JS7A6UIF.js → workspace-trust-reconciler-XEBW5FUL.js} +57 -60
- package/chunks/{write-file-GQGG7NBQ.js → write-file-LKX4ETIO.js} +29 -32
- package/chunks/{zh-V2EYTYJP.js → zh-F76MZTL3.js} +23 -1
- package/chunks/{zh-TW-7PRVUGLW.js → zh-TW-S3YTQ4DS.js} +23 -1
- package/chunks/{zoom-image-EC43KL4H.js → zoom-image-RDPRTP4B.js} +5 -9
- package/cli.js +19 -15
- package/export-transcript-document.css +1 -1
- package/export-transcript-document.js +151 -150
- package/locales/ca.js +19 -2
- package/locales/de.js +18 -0
- package/locales/en.js +33 -2
- package/locales/fr.js +18 -0
- package/locales/ja.js +18 -0
- package/locales/pt.js +18 -0
- package/locales/ru.js +18 -0
- package/locales/zh-TW.js +33 -2
- package/locales/zh.js +33 -2
- package/package.json +3 -3
- package/web-shell/assets/{abnfDiagram-VCTEODGH-BtpzKw3A.js → abnfDiagram-VCTEODGH-RxykUDmi.js} +1 -1
- package/web-shell/assets/{arc-CQiVKZJP.js → arc-CZpgGCJC.js} +1 -1
- package/web-shell/assets/{architectureDiagram-5GKGNRK7-ekIPBb2d.js → architectureDiagram-5GKGNRK7-BHSMzNDT.js} +1 -1
- package/web-shell/assets/{blockDiagram-NRAW4CY4-BrRWkWri.js → blockDiagram-NRAW4CY4-Bn4mF9SZ.js} +1 -1
- package/web-shell/assets/{c4Diagram-UCG6FXSJ-qYS8CYZ3.js → c4Diagram-UCG6FXSJ-CBM-Bj6t.js} +1 -1
- package/web-shell/assets/channel-DFYs_LlK.js +1 -0
- package/web-shell/assets/{chunk-2Q5K7J3B-ZasyyEZm.js → chunk-2Q5K7J3B-D5Fin58O.js} +1 -1
- package/web-shell/assets/{chunk-5VM5RSS4-C_IzCGeA.js → chunk-5VM5RSS4-CY05weF7.js} +1 -1
- package/web-shell/assets/{chunk-F27PBJKO-C25NZOyD.js → chunk-F27PBJKO-3neZnj5Y.js} +1 -1
- package/web-shell/assets/{chunk-G27WJ6UU-XPOHNSGX.js → chunk-G27WJ6UU-Cd7EU4BE.js} +1 -1
- package/web-shell/assets/{chunk-JWPE2WC7-BQBh0Xni.js → chunk-JWPE2WC7-DwK1mqFw.js} +1 -1
- package/web-shell/assets/{chunk-LCL6LL3I-CoShjpX7.js → chunk-LCL6LL3I-Sl7vY22C.js} +1 -1
- package/web-shell/assets/{chunk-POPQ4Y6H-BwRmCDSz.js → chunk-POPQ4Y6H-BXNzpbVg.js} +1 -1
- package/web-shell/assets/{chunk-SVP7TREG-DSzE5-Mw.js → chunk-SVP7TREG-DjjButcp.js} +1 -1
- package/web-shell/assets/{chunk-XXDRQBXY-BQSQv30h.js → chunk-XXDRQBXY-DNOiCjOJ.js} +1 -1
- package/web-shell/assets/classDiagram-DTDB5LWJ-DnGrKXoM.js +1 -0
- package/web-shell/assets/classDiagram-v2-JRS7N3AN-DnGrKXoM.js +1 -0
- package/web-shell/assets/{cose-bilkent-JH36ORCC-XVUVTHVo.js → cose-bilkent-JH36ORCC-BUnker7a.js} +1 -1
- package/web-shell/assets/{cynefin-OW5HDTMX-CrsKx4lQ.js → cynefin-OW5HDTMX-DcUgdWE5.js} +1 -1
- package/web-shell/assets/{cynefinDiagram-5FMLGOSQ-BPeZEuHw.js → cynefinDiagram-5FMLGOSQ-CvDKsZsL.js} +1 -1
- package/web-shell/assets/{dagre-3AP2YEHR-D31cQ2Qs.js → dagre-3AP2YEHR-jpCmUbr1.js} +1 -1
- package/web-shell/assets/{diagram-S7CK7UJ4-zyiG097Q.js → diagram-S7CK7UJ4-DBe_bKE5.js} +1 -1
- package/web-shell/assets/{diagram-UQ7AKVKN-Br3vtfsy.js → diagram-UQ7AKVKN-oXvPpDgs.js} +1 -1
- package/web-shell/assets/{diagram-VSXAHHWV-Bxkhjx4u.js → diagram-VSXAHHWV-BD7-_SGh.js} +1 -1
- package/web-shell/assets/{diagram-VX7I27RA-BQH8QiDk.js → diagram-VX7I27RA-DOJL0wub.js} +1 -1
- package/web-shell/assets/{diagram-Z3DM3KII-B_aQ1cw0.js → diagram-Z3DM3KII-DRIiodDD.js} +1 -1
- package/web-shell/assets/{ebnfDiagram-PWID7BFC-B9N7BRQE.js → ebnfDiagram-PWID7BFC-Db31Ulmb.js} +1 -1
- package/web-shell/assets/{erDiagram-SSCWMZ5O-Cx6Hb1Re.js → erDiagram-SSCWMZ5O-CVHhwI2_.js} +1 -1
- package/web-shell/assets/{flowDiagram-A5DVABFB-DTuLP7GU.js → flowDiagram-A5DVABFB-DWOFy1FK.js} +1 -1
- package/web-shell/assets/{ganttDiagram-EL5Y4UJY-DYS3d-sL.js → ganttDiagram-EL5Y4UJY-C0sxQtPd.js} +1 -1
- package/web-shell/assets/{gitGraphDiagram-WWUBYQGX-Cp0EGx04.js → gitGraphDiagram-WWUBYQGX-CNituBYC.js} +1 -1
- package/web-shell/assets/index-B15NlwB8.js +2213 -0
- package/web-shell/assets/index-BSrS0tQ6.css +36 -0
- package/web-shell/assets/{index-45-LkPDB.js → index-gm9tLk7h.js} +1 -1
- package/web-shell/assets/{infoDiagram-RXCK75RN-9--kukiT.js → infoDiagram-RXCK75RN-CxhJYtIR.js} +1 -1
- package/web-shell/assets/{ishikawaDiagram-5VMMS53U-CGBdsDLD.js → ishikawaDiagram-5VMMS53U-By2mchUy.js} +1 -1
- package/web-shell/assets/{journeyDiagram-EYS64GPL-DeXhcscd.js → journeyDiagram-EYS64GPL-CVH-OweI.js} +1 -1
- package/web-shell/assets/{kanban-definition-3QL26DDD-CFdvsU3b.js → kanban-definition-3QL26DDD-Cc9dQXLy.js} +1 -1
- package/web-shell/assets/knowledge-Dg9788h4.svg +1 -0
- package/web-shell/assets/{layout-DAnwQ3KB.js → layout-C_60ysHw.js} +1 -1
- package/web-shell/assets/{linear-CTo7v7Nh.js → linear-BvAVfqwu.js} +1 -1
- package/web-shell/assets/{mermaid.core-jggSxF1i.js → mermaid.core-C3CoBKAc.js} +6 -6
- package/web-shell/assets/{mindmap-definition-FBJOCRG2-DzIepvlJ.js → mindmap-definition-FBJOCRG2-Cuu8Q8LM.js} +1 -1
- package/web-shell/assets/{pegDiagram-XKGWAZYB-BFGS9GJv.js → pegDiagram-XKGWAZYB-DmAeyDO2.js} +1 -1
- package/web-shell/assets/{pieDiagram-E7YTZNPT-B2UUcNIT.js → pieDiagram-E7YTZNPT-B7vbB_xv.js} +1 -1
- package/web-shell/assets/{quadrantDiagram-AXDQQJYC-BgM6htrX.js → quadrantDiagram-AXDQQJYC-BqOBkRR7.js} +1 -1
- package/web-shell/assets/{railroadDiagram-O6MQD6OU-Dk9cS7N-.js → railroadDiagram-O6MQD6OU-sI06lZIu.js} +1 -1
- package/web-shell/assets/{requirementDiagram-EFPCY7ZU-C9oRg7xi.js → requirementDiagram-EFPCY7ZU-Bg13d10S.js} +1 -1
- package/web-shell/assets/{sankeyDiagram-P5KCCOFB-B-_c7GzI.js → sankeyDiagram-P5KCCOFB-WFOzZHrR.js} +1 -1
- package/web-shell/assets/{sequenceDiagram-WJ2MYXX4-R0M-347u.js → sequenceDiagram-WJ2MYXX4-CCdRbA4E.js} +1 -1
- package/web-shell/assets/{sizeCapture-X5ZJPWSS-Df0f8UAW.js → sizeCapture-X5ZJPWSS-BH5F3bGg.js} +1 -1
- package/web-shell/assets/{stateDiagram-HBIQ2CUA-CsUEfAA-.js → stateDiagram-HBIQ2CUA-NwS2X3QB.js} +1 -1
- package/web-shell/assets/stateDiagram-v2-4QOOHH4V-1aU2JZXO.js +1 -0
- package/web-shell/assets/{swimlanes-XN3QIQJK-9OGHVSrx.js → swimlanes-XN3QIQJK-Bm38pM28.js} +1 -1
- package/web-shell/assets/swimlanesDiagram-VK2B7HYN-Dp-u6kQG.js +8 -0
- package/web-shell/assets/{timeline-definition-24CTP7MA-DAfGqS2B.js → timeline-definition-24CTP7MA-Do-agLSo.js} +1 -1
- package/web-shell/assets/{vennDiagram-4TSXK5OY-CKATpwHi.js → vennDiagram-4TSXK5OY-aggLfZzl.js} +1 -1
- package/web-shell/assets/{wardleyDiagram-VM6X3IG4-CQHdhTrm.js → wardleyDiagram-VM6X3IG4-D5JR3mXX.js} +1 -1
- package/web-shell/assets/{xychartDiagram-S5SC5T6Z-5k9NLqlY.js → xychartDiagram-S5SC5T6Z-DhtLDuXs.js} +1 -1
- package/web-shell/index.html +2 -2
- package/chunks/chunk-4OQSG35W.js +0 -1416
- package/chunks/chunk-7MIBD3LG.js +0 -137
- package/chunks/chunk-ARDHE6MM.js +0 -235
- package/chunks/chunk-C75BXMPM.js +0 -169
- package/chunks/chunk-ERU3SDXT.js +0 -27
- package/chunks/chunk-FPGTNKCP.js +0 -251
- package/chunks/chunk-JIJ65YKA.js +0 -2812
- package/chunks/chunk-JL6APGBX.js +0 -43
- package/chunks/chunk-SGXJQP5Q.js +0 -4172
- package/chunks/chunk-TPEV2QHG.js +0 -514
- package/chunks/chunk-YVWS4SLL.js +0 -137
- package/web-shell/assets/channel-DSQQnOZj.js +0 -1
- package/web-shell/assets/classDiagram-DTDB5LWJ-V94ta08R.js +0 -1
- package/web-shell/assets/classDiagram-v2-JRS7N3AN-V94ta08R.js +0 -1
- package/web-shell/assets/index-H8um-iEl.js +0 -2207
- package/web-shell/assets/index-n6N-2a3v.css +0 -36
- package/web-shell/assets/stateDiagram-v2-4QOOHH4V-CnSuTPJ2.js +0 -1
- package/web-shell/assets/swimlanesDiagram-VK2B7HYN-Bb7TcWQw.js +0 -8
- package/chunks/{chunk-QZW6WRB7.js → chunk-5NUKK2DT.js} +2 -2
- package/chunks/{chunk-JS73NNWF.js → chunk-FUSEMYFX.js} +0 -0
- package/chunks/{chunk-SVWWF5TZ.js → chunk-WVURIAEE.js} +3 -3
- package/chunks/{task-update-RI7QNVDP.js → task-update-3LSYQDRW.js} +4 -4
|
@@ -0,0 +1,1246 @@
|
|
|
1
|
+
// Force strict mode and setup for ESM
|
|
2
|
+
"use strict";
|
|
3
|
+
import {
|
|
4
|
+
CUSTOM_SANDBOX_IMAGE_ENV_VAR,
|
|
5
|
+
HOST_UPDATE_RELAUNCH_ENV_VAR,
|
|
6
|
+
SKIP_UPDATE_CHECK_ENV_VAR
|
|
7
|
+
} from "./chunk-B5TJK7B3.js";
|
|
8
|
+
import {
|
|
9
|
+
getUserSettingsDir
|
|
10
|
+
} from "./chunk-RRI764F7.js";
|
|
11
|
+
import {
|
|
12
|
+
SETTINGS_DIRECTORY_NAME
|
|
13
|
+
} from "./chunk-NKTMUPHJ.js";
|
|
14
|
+
import {
|
|
15
|
+
QWEN_CODE_DESKTOP_ENV,
|
|
16
|
+
QWEN_CODE_SERVE_ENV
|
|
17
|
+
} from "./chunk-6OTF7TTE.js";
|
|
18
|
+
import {
|
|
19
|
+
gitEnv
|
|
20
|
+
} from "./chunk-KAYC5FBN.js";
|
|
21
|
+
import {
|
|
22
|
+
require_shell_quote
|
|
23
|
+
} from "./chunk-V545KI73.js";
|
|
24
|
+
import {
|
|
25
|
+
resolveBundleDir
|
|
26
|
+
} from "./chunk-ACHCT36C.js";
|
|
27
|
+
import {
|
|
28
|
+
FatalSandboxError,
|
|
29
|
+
Storage,
|
|
30
|
+
isSubpath
|
|
31
|
+
} from "./chunk-ZAFYHRVY.js";
|
|
32
|
+
import {
|
|
33
|
+
writeStderrLine
|
|
34
|
+
} from "./chunk-7FA2II6K.js";
|
|
35
|
+
import {
|
|
36
|
+
init_esbuild_shims
|
|
37
|
+
} from "./chunk-5O2XNYP6.js";
|
|
38
|
+
import {
|
|
39
|
+
__name,
|
|
40
|
+
__toESM
|
|
41
|
+
} from "./chunk-J2S4EL5Y.js";
|
|
42
|
+
|
|
43
|
+
// packages/cli/src/serve/sandbox.ts
|
|
44
|
+
init_esbuild_shims();
|
|
45
|
+
var import_shell_quote = __toESM(require_shell_quote(), 1);
|
|
46
|
+
import {
|
|
47
|
+
exec,
|
|
48
|
+
execSync,
|
|
49
|
+
spawn,
|
|
50
|
+
spawnSync
|
|
51
|
+
} from "node:child_process";
|
|
52
|
+
import os2 from "node:os";
|
|
53
|
+
import path2 from "node:path";
|
|
54
|
+
import fs from "node:fs";
|
|
55
|
+
import { promisify } from "node:util";
|
|
56
|
+
import { randomBytes } from "node:crypto";
|
|
57
|
+
|
|
58
|
+
// packages/cli/src/utils/sandboxImageName.ts
|
|
59
|
+
init_esbuild_shims();
|
|
60
|
+
function parseSandboxImageName(image) {
|
|
61
|
+
const imageWithoutDigest = image.split("@")[0] ?? image;
|
|
62
|
+
const lastSlash = imageWithoutDigest.lastIndexOf("/");
|
|
63
|
+
const lastColon = imageWithoutDigest.lastIndexOf(":");
|
|
64
|
+
const hasTag = lastColon > lastSlash;
|
|
65
|
+
const fullName = hasTag ? imageWithoutDigest.slice(0, lastColon) : imageWithoutDigest;
|
|
66
|
+
const tag = hasTag ? imageWithoutDigest.slice(lastColon + 1) : void 0;
|
|
67
|
+
const name = fullName.split("/").at(-1) || "unknown-image";
|
|
68
|
+
return tag ? `${name}-${tag}` : name;
|
|
69
|
+
}
|
|
70
|
+
__name(parseSandboxImageName, "parseSandboxImageName");
|
|
71
|
+
|
|
72
|
+
// packages/cli/src/utils/sandbox-path.ts
|
|
73
|
+
init_esbuild_shims();
|
|
74
|
+
import path from "node:path";
|
|
75
|
+
function isContainerPathWithinWorkdir(containerWorkdir, containerPath) {
|
|
76
|
+
const normalize = /* @__PURE__ */ __name((value) => {
|
|
77
|
+
const normalized = path.posix.normalize(value.replace(/\\/g, "/")).replace(/\/+$/, "").toLowerCase();
|
|
78
|
+
return normalized || "/";
|
|
79
|
+
}, "normalize");
|
|
80
|
+
const normalizedWorkdir = normalize(containerWorkdir);
|
|
81
|
+
const normalizedPath = normalize(containerPath);
|
|
82
|
+
if (normalizedWorkdir === "/") {
|
|
83
|
+
return normalizedPath.startsWith("/");
|
|
84
|
+
}
|
|
85
|
+
return normalizedPath === normalizedWorkdir || normalizedPath.startsWith(`${normalizedWorkdir}/`);
|
|
86
|
+
}
|
|
87
|
+
__name(isContainerPathWithinWorkdir, "isContainerPathWithinWorkdir");
|
|
88
|
+
|
|
89
|
+
// packages/cli/src/utils/sandboxMounts.ts
|
|
90
|
+
init_esbuild_shims();
|
|
91
|
+
import os from "node:os";
|
|
92
|
+
function parseSandboxMountSpec(rawMount, platform = os.platform()) {
|
|
93
|
+
const mount = rawMount.trim();
|
|
94
|
+
const mountSeparator = platform === "win32" && /^[A-Za-z]:[\\/]/.test(mount) ? mount.indexOf(":", 2) : mount.indexOf(":");
|
|
95
|
+
const from = mountSeparator === -1 ? mount : mount.slice(0, mountSeparator);
|
|
96
|
+
const rest = mountSeparator === -1 ? "" : mount.slice(mountSeparator + 1);
|
|
97
|
+
const [toPart, optsPart] = rest.split(":");
|
|
98
|
+
return {
|
|
99
|
+
from,
|
|
100
|
+
to: toPart || from,
|
|
101
|
+
opts: optsPart || "ro"
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
__name(parseSandboxMountSpec, "parseSandboxMountSpec");
|
|
105
|
+
|
|
106
|
+
// packages/cli/src/serve/sandbox.ts
|
|
107
|
+
var execAsync = promisify(exec);
|
|
108
|
+
function getContainerPath(hostPath) {
|
|
109
|
+
if (os2.platform() !== "win32") {
|
|
110
|
+
return hostPath;
|
|
111
|
+
}
|
|
112
|
+
const withForwardSlashes = hostPath.replace(/\\/g, "/");
|
|
113
|
+
const match = withForwardSlashes.match(/^([A-Z]):\/(.*)/i);
|
|
114
|
+
if (match) {
|
|
115
|
+
return `/${match[1].toLowerCase()}/${match[2]}`;
|
|
116
|
+
}
|
|
117
|
+
return hostPath;
|
|
118
|
+
}
|
|
119
|
+
__name(getContainerPath, "getContainerPath");
|
|
120
|
+
function ensureDirectoryAndGetRealPath(dir) {
|
|
121
|
+
if (!fs.existsSync(dir)) {
|
|
122
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
123
|
+
}
|
|
124
|
+
return fs.realpathSync(dir);
|
|
125
|
+
}
|
|
126
|
+
__name(ensureDirectoryAndGetRealPath, "ensureDirectoryAndGetRealPath");
|
|
127
|
+
var LOCAL_DEV_SANDBOX_IMAGE_NAME = "qwen-code-sandbox";
|
|
128
|
+
var SANDBOX_NETWORK_NAME = "qwen-code-sandbox";
|
|
129
|
+
var SANDBOX_PROXY_NAME = "qwen-code-sandbox-proxy";
|
|
130
|
+
var BUILTIN_SEATBELT_PROFILES = [
|
|
131
|
+
"permissive-open",
|
|
132
|
+
"permissive-closed",
|
|
133
|
+
"permissive-proxied",
|
|
134
|
+
"restrictive-open",
|
|
135
|
+
"restrictive-closed",
|
|
136
|
+
"restrictive-proxied"
|
|
137
|
+
];
|
|
138
|
+
function getSandboxPassthroughEnvArgs(env = process.env) {
|
|
139
|
+
return [
|
|
140
|
+
"QWEN_DEBUG_LOG_FILE",
|
|
141
|
+
"QWEN_CODE_LEGACY_MCP_BLOCKING",
|
|
142
|
+
SKIP_UPDATE_CHECK_ENV_VAR,
|
|
143
|
+
CUSTOM_SANDBOX_IMAGE_ENV_VAR,
|
|
144
|
+
HOST_UPDATE_RELAUNCH_ENV_VAR,
|
|
145
|
+
QWEN_CODE_SERVE_ENV,
|
|
146
|
+
QWEN_CODE_DESKTOP_ENV
|
|
147
|
+
].flatMap(
|
|
148
|
+
(envVar) => env[envVar] === void 0 ? [] : ["--env", `${envVar}=${env[envVar]}`]
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
__name(getSandboxPassthroughEnvArgs, "getSandboxPassthroughEnvArgs");
|
|
152
|
+
function resolveSeatbeltProfileFile(profile, importMetaUrl = import.meta.url) {
|
|
153
|
+
if (!BUILTIN_SEATBELT_PROFILES.includes(profile)) {
|
|
154
|
+
return path2.join(SETTINGS_DIRECTORY_NAME, `sandbox-macos-${profile}.sb`);
|
|
155
|
+
}
|
|
156
|
+
return path2.join(
|
|
157
|
+
resolveBundleDir(importMetaUrl),
|
|
158
|
+
`sandbox-macos-${profile}.sb`
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
__name(resolveSeatbeltProfileFile, "resolveSeatbeltProfileFile");
|
|
162
|
+
async function shouldUseCurrentUserInSandbox() {
|
|
163
|
+
const envVar = process.env["SANDBOX_SET_UID_GID"]?.toLowerCase().trim();
|
|
164
|
+
if (envVar === "1" || envVar === "true") {
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
if (envVar === "0" || envVar === "false") {
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
if (os2.platform() === "linux") {
|
|
171
|
+
const debugEnv = [process.env["DEBUG"], process.env["DEBUG_MODE"]].some(
|
|
172
|
+
(v) => v === "true" || v === "1"
|
|
173
|
+
);
|
|
174
|
+
if (debugEnv) {
|
|
175
|
+
writeStderrLine(
|
|
176
|
+
"INFO: Using current user UID/GID in Linux sandbox. Set SANDBOX_SET_UID_GID=false to disable."
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
return true;
|
|
180
|
+
}
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
__name(shouldUseCurrentUserInSandbox, "shouldUseCurrentUserInSandbox");
|
|
184
|
+
function ports() {
|
|
185
|
+
return (process.env["SANDBOX_PORTS"] ?? "").split(",").filter((p) => p.trim()).map((p) => p.trim());
|
|
186
|
+
}
|
|
187
|
+
__name(ports, "ports");
|
|
188
|
+
function entrypoint(workdir, cliArgs) {
|
|
189
|
+
const isWindows = os2.platform() === "win32";
|
|
190
|
+
const containerWorkdir = getContainerPath(workdir);
|
|
191
|
+
const shellCmds = [];
|
|
192
|
+
const pathSeparator = isWindows ? ";" : ":";
|
|
193
|
+
let pathSuffix = "";
|
|
194
|
+
if (process.env["PATH"]) {
|
|
195
|
+
const paths = process.env["PATH"].split(pathSeparator);
|
|
196
|
+
for (const p of paths) {
|
|
197
|
+
const containerPath = getContainerPath(p);
|
|
198
|
+
if (isContainerPathWithinWorkdir(containerWorkdir, containerPath)) {
|
|
199
|
+
pathSuffix += `:${containerPath}`;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
if (pathSuffix) {
|
|
204
|
+
shellCmds.push(`export PATH="$PATH${pathSuffix}";`);
|
|
205
|
+
}
|
|
206
|
+
let pythonPathSuffix = "";
|
|
207
|
+
if (process.env["PYTHONPATH"]) {
|
|
208
|
+
const paths = process.env["PYTHONPATH"].split(pathSeparator);
|
|
209
|
+
for (const p of paths) {
|
|
210
|
+
const containerPath = getContainerPath(p);
|
|
211
|
+
if (isContainerPathWithinWorkdir(containerWorkdir, containerPath)) {
|
|
212
|
+
pythonPathSuffix += `:${containerPath}`;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
if (pythonPathSuffix) {
|
|
217
|
+
shellCmds.push(`export PYTHONPATH="$PYTHONPATH${pythonPathSuffix}";`);
|
|
218
|
+
}
|
|
219
|
+
const projectSandboxBashrc = path2.join(
|
|
220
|
+
SETTINGS_DIRECTORY_NAME,
|
|
221
|
+
"sandbox.bashrc"
|
|
222
|
+
);
|
|
223
|
+
if (fs.existsSync(projectSandboxBashrc)) {
|
|
224
|
+
shellCmds.push(`source ${getContainerPath(projectSandboxBashrc)};`);
|
|
225
|
+
}
|
|
226
|
+
ports().forEach(
|
|
227
|
+
(p) => shellCmds.push(
|
|
228
|
+
`socat TCP4-LISTEN:${p},bind=$(hostname -i),fork,reuseaddr TCP4:127.0.0.1:${p} 2> /dev/null &`
|
|
229
|
+
)
|
|
230
|
+
);
|
|
231
|
+
const quotedCliArgs = cliArgs.slice(2).map((arg) => (0, import_shell_quote.quote)([arg]));
|
|
232
|
+
const cliCmd = false ? process.env["DEBUG"] ? "npm run debug --" : "npm rebuild && npm run start --" : process.env["DEBUG"] ? `node --inspect-brk=0.0.0.0:${process.env["DEBUG_PORT"] || "9229"} $(which qwen)` : "qwen";
|
|
233
|
+
const args = [...shellCmds, cliCmd, ...quotedCliArgs];
|
|
234
|
+
return ["bash", "-c", args.join(" ")];
|
|
235
|
+
}
|
|
236
|
+
__name(entrypoint, "entrypoint");
|
|
237
|
+
var VALID_SANDBOX_NETWORK_MODES = [
|
|
238
|
+
"open",
|
|
239
|
+
"closed",
|
|
240
|
+
"proxied"
|
|
241
|
+
];
|
|
242
|
+
function resolveSandboxNetworkMode(env = process.env) {
|
|
243
|
+
const requested = env["QWEN_SANDBOX_NET"]?.toLowerCase().trim();
|
|
244
|
+
if (requested && !VALID_SANDBOX_NETWORK_MODES.includes(requested)) {
|
|
245
|
+
throw new FatalSandboxError(
|
|
246
|
+
`Invalid QWEN_SANDBOX_NET '${env["QWEN_SANDBOX_NET"]}'. Must be one of ${VALID_SANDBOX_NETWORK_MODES.join(", ")}.`
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
if (requested === "closed") {
|
|
250
|
+
return "closed";
|
|
251
|
+
}
|
|
252
|
+
if (requested === "proxied" && !env["QWEN_SANDBOX_PROXY_COMMAND"]?.trim()) {
|
|
253
|
+
throw new FatalSandboxError(
|
|
254
|
+
"QWEN_SANDBOX_NET=proxied requires QWEN_SANDBOX_PROXY_COMMAND."
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
return env["QWEN_SANDBOX_PROXY_COMMAND"] ? "proxied" : "open";
|
|
258
|
+
}
|
|
259
|
+
__name(resolveSandboxNetworkMode, "resolveSandboxNetworkMode");
|
|
260
|
+
var GIT_ROOT_PROBE_TIMEOUT_MS = 2e3;
|
|
261
|
+
function resolveGitWritableRoots(cwd) {
|
|
262
|
+
const read = /* @__PURE__ */ __name((gitArgs) => {
|
|
263
|
+
try {
|
|
264
|
+
const result = spawnSync("git", gitArgs, {
|
|
265
|
+
cwd,
|
|
266
|
+
env: gitEnv(),
|
|
267
|
+
encoding: "utf8",
|
|
268
|
+
stdio: "pipe",
|
|
269
|
+
timeout: GIT_ROOT_PROBE_TIMEOUT_MS
|
|
270
|
+
});
|
|
271
|
+
if (result.status !== 0) {
|
|
272
|
+
return void 0;
|
|
273
|
+
}
|
|
274
|
+
const value = result.stdout?.trim();
|
|
275
|
+
return value ? value : void 0;
|
|
276
|
+
} catch {
|
|
277
|
+
return void 0;
|
|
278
|
+
}
|
|
279
|
+
}, "read");
|
|
280
|
+
try {
|
|
281
|
+
const topLevel = read(["rev-parse", "--show-toplevel"]);
|
|
282
|
+
const gitDirValue = read(["rev-parse", "--absolute-git-dir"]);
|
|
283
|
+
const commonDirValue = read(["rev-parse", "--git-common-dir"]);
|
|
284
|
+
if (!topLevel || !gitDirValue || !commonDirValue) {
|
|
285
|
+
return [];
|
|
286
|
+
}
|
|
287
|
+
const targetDir = fs.realpathSync(topLevel);
|
|
288
|
+
const currentDir = fs.realpathSync(cwd);
|
|
289
|
+
if (currentDir !== targetDir && !isSubpath(targetDir, currentDir)) {
|
|
290
|
+
return [];
|
|
291
|
+
}
|
|
292
|
+
const gitEntry = path2.join(targetDir, ".git");
|
|
293
|
+
const entryStat = fs.lstatSync(gitEntry);
|
|
294
|
+
const gitDir = fs.realpathSync(path2.resolve(cwd, gitDirValue));
|
|
295
|
+
const commonDir = fs.realpathSync(path2.resolve(cwd, commonDirValue));
|
|
296
|
+
if (entryStat.isDirectory()) {
|
|
297
|
+
return fs.realpathSync(gitEntry) === gitDir && commonDir === gitDir ? [gitDir, commonDir] : [];
|
|
298
|
+
}
|
|
299
|
+
if (!entryStat.isFile()) {
|
|
300
|
+
return [];
|
|
301
|
+
}
|
|
302
|
+
const registration = path2.join(
|
|
303
|
+
commonDir,
|
|
304
|
+
"worktrees",
|
|
305
|
+
path2.basename(gitDir)
|
|
306
|
+
);
|
|
307
|
+
const backPointerPath = path2.join(gitDir, "gitdir");
|
|
308
|
+
if (gitDir !== registration || !fs.lstatSync(backPointerPath).isFile()) {
|
|
309
|
+
return [];
|
|
310
|
+
}
|
|
311
|
+
const backPointer = fs.readFileSync(backPointerPath, "utf8").trim();
|
|
312
|
+
return fs.realpathSync(path2.resolve(gitDir, backPointer)) === gitEntry ? [gitDir, commonDir] : [];
|
|
313
|
+
} catch {
|
|
314
|
+
return [];
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
__name(resolveGitWritableRoots, "resolveGitWritableRoots");
|
|
318
|
+
function normalizeWritableRoots(candidates) {
|
|
319
|
+
const homeDir = fs.realpathSync(os2.homedir());
|
|
320
|
+
const resolved = [];
|
|
321
|
+
for (const candidate of candidates) {
|
|
322
|
+
let real;
|
|
323
|
+
try {
|
|
324
|
+
real = fs.realpathSync(candidate);
|
|
325
|
+
} catch {
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
if (real === homeDir || isSubpath(real, homeDir)) {
|
|
329
|
+
throw new FatalSandboxError(
|
|
330
|
+
`Refusing sandbox writable root '${real}': the home directory ('${homeDir}') and its ancestors must stay read-only.`
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
if (resolved.some(
|
|
334
|
+
(existing) => existing === real || isSubpath(existing, real)
|
|
335
|
+
)) {
|
|
336
|
+
continue;
|
|
337
|
+
}
|
|
338
|
+
resolved.push(real);
|
|
339
|
+
}
|
|
340
|
+
return resolved;
|
|
341
|
+
}
|
|
342
|
+
__name(normalizeWritableRoots, "normalizeWritableRoots");
|
|
343
|
+
function resolveBwrapWritableRoots(includedDirs = []) {
|
|
344
|
+
const qwenDir = Storage.getGlobalQwenDir();
|
|
345
|
+
const runtimeDir = Storage.getRuntimeBaseDir();
|
|
346
|
+
fs.mkdirSync(qwenDir, { recursive: true });
|
|
347
|
+
fs.mkdirSync(runtimeDir, { recursive: true });
|
|
348
|
+
const targetDir = fs.realpathSync(process.cwd());
|
|
349
|
+
const homeDir = os2.homedir();
|
|
350
|
+
const cacheDir = process.env["XDG_CACHE_HOME"] || path2.join(homeDir, ".cache");
|
|
351
|
+
try {
|
|
352
|
+
fs.mkdirSync(cacheDir);
|
|
353
|
+
} catch {
|
|
354
|
+
}
|
|
355
|
+
const roots = normalizeWritableRoots([
|
|
356
|
+
targetDir,
|
|
357
|
+
os2.tmpdir(),
|
|
358
|
+
cacheDir,
|
|
359
|
+
qwenDir,
|
|
360
|
+
runtimeDir,
|
|
361
|
+
...resolveGitWritableRoots(targetDir),
|
|
362
|
+
path2.join(homeDir, ".npm")
|
|
363
|
+
]);
|
|
364
|
+
const realHomeDir = fs.realpathSync(homeDir);
|
|
365
|
+
const extras = [];
|
|
366
|
+
for (const dir of includedDirs) {
|
|
367
|
+
let real;
|
|
368
|
+
try {
|
|
369
|
+
real = fs.realpathSync(dir);
|
|
370
|
+
} catch {
|
|
371
|
+
continue;
|
|
372
|
+
}
|
|
373
|
+
if (roots.some((root) => isSubpath(root, real))) {
|
|
374
|
+
continue;
|
|
375
|
+
}
|
|
376
|
+
if (isSubpath(realHomeDir, real)) {
|
|
377
|
+
throw new FatalSandboxError(
|
|
378
|
+
`Refusing sandbox writable root '${real}': additional workspace directories inside the home directory must stay read-only.`
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
extras.push(real);
|
|
382
|
+
}
|
|
383
|
+
const qwenEnvFile = path2.join(qwenDir, ".env");
|
|
384
|
+
let protectedEnvFile;
|
|
385
|
+
try {
|
|
386
|
+
try {
|
|
387
|
+
fs.writeFileSync(qwenEnvFile, "", { flag: "wx", mode: 384 });
|
|
388
|
+
} catch (error) {
|
|
389
|
+
if (error.code !== "EEXIST") throw error;
|
|
390
|
+
}
|
|
391
|
+
const stat = fs.lstatSync(qwenEnvFile);
|
|
392
|
+
if (!stat.isFile() || stat.nlink !== 1) {
|
|
393
|
+
throw new Error("Expected a regular file with a single link.");
|
|
394
|
+
}
|
|
395
|
+
protectedEnvFile = fs.realpathSync(qwenEnvFile);
|
|
396
|
+
} catch (error) {
|
|
397
|
+
throw new FatalSandboxError(
|
|
398
|
+
`Cannot protect sandbox configuration '${qwenEnvFile}': ${error instanceof Error ? error.message : String(error)}`
|
|
399
|
+
);
|
|
400
|
+
}
|
|
401
|
+
return {
|
|
402
|
+
targetDir,
|
|
403
|
+
roots: normalizeWritableRoots([...roots, ...extras]),
|
|
404
|
+
readOnlyOverrides: [protectedEnvFile]
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
__name(resolveBwrapWritableRoots, "resolveBwrapWritableRoots");
|
|
408
|
+
function buildBwrapArgs(options) {
|
|
409
|
+
const args = [
|
|
410
|
+
// Recursive, so /proc /sys /run come along read-only and Node keeps the
|
|
411
|
+
// /proc it needs without a fresh (writable) procfs instance.
|
|
412
|
+
"--ro-bind",
|
|
413
|
+
"/",
|
|
414
|
+
"/",
|
|
415
|
+
"--dev",
|
|
416
|
+
"/dev",
|
|
417
|
+
"--die-with-parent"
|
|
418
|
+
];
|
|
419
|
+
if (options.networkMode === "closed") {
|
|
420
|
+
args.push("--unshare-net");
|
|
421
|
+
}
|
|
422
|
+
for (const root of options.writableRoots) {
|
|
423
|
+
args.push("--bind", root, root);
|
|
424
|
+
}
|
|
425
|
+
for (const override of options.readOnlyOverrides) {
|
|
426
|
+
args.push("--ro-bind", override, override);
|
|
427
|
+
}
|
|
428
|
+
args.push("--chdir", options.targetDir, "--");
|
|
429
|
+
args.push(...options.cliArgs);
|
|
430
|
+
return args;
|
|
431
|
+
}
|
|
432
|
+
__name(buildBwrapArgs, "buildBwrapArgs");
|
|
433
|
+
function buildBwrapEnv(networkMode, baseEnv = process.env) {
|
|
434
|
+
const env = {
|
|
435
|
+
...baseEnv,
|
|
436
|
+
SANDBOX: "bwrap",
|
|
437
|
+
SANDBOX_ENFORCEMENT: "full"
|
|
438
|
+
};
|
|
439
|
+
delete env["DISPLAY"];
|
|
440
|
+
delete env["WAYLAND_DISPLAY"];
|
|
441
|
+
delete env["MIR_SOCKET"];
|
|
442
|
+
if (networkMode === "proxied") {
|
|
443
|
+
const proxy = env["HTTPS_PROXY"] || env["https_proxy"] || env["HTTP_PROXY"] || env["http_proxy"] || "http://localhost:8877";
|
|
444
|
+
env["HTTPS_PROXY"] = env["https_proxy"] = env["HTTP_PROXY"] = env["http_proxy"] = proxy;
|
|
445
|
+
const noProxy = env["NO_PROXY"] || env["no_proxy"];
|
|
446
|
+
if (noProxy) env["NO_PROXY"] = env["no_proxy"] = noProxy;
|
|
447
|
+
}
|
|
448
|
+
return env;
|
|
449
|
+
}
|
|
450
|
+
__name(buildBwrapEnv, "buildBwrapEnv");
|
|
451
|
+
function runBwrap(options, env = buildBwrapEnv(options.networkMode)) {
|
|
452
|
+
return new Promise((resolve, reject) => {
|
|
453
|
+
let proxyProcess;
|
|
454
|
+
let sandboxProcess;
|
|
455
|
+
let finished = false;
|
|
456
|
+
let stdinPaused = false;
|
|
457
|
+
const readiness = new AbortController();
|
|
458
|
+
const signalSandbox = /* @__PURE__ */ __name((signal) => {
|
|
459
|
+
if (sandboxProcess?.pid) {
|
|
460
|
+
try {
|
|
461
|
+
process.kill(-sandboxProcess.pid, signal);
|
|
462
|
+
} catch {
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
}, "signalSandbox");
|
|
466
|
+
const stopProxy = /* @__PURE__ */ __name(() => {
|
|
467
|
+
if (proxyProcess?.pid) {
|
|
468
|
+
try {
|
|
469
|
+
process.kill(-proxyProcess.pid, "SIGTERM");
|
|
470
|
+
} catch {
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}, "stopProxy");
|
|
474
|
+
const finish = /* @__PURE__ */ __name((error, code = 1) => {
|
|
475
|
+
if (finished) return;
|
|
476
|
+
finished = true;
|
|
477
|
+
readiness.abort();
|
|
478
|
+
process.removeListener("exit", stopProxy);
|
|
479
|
+
process.removeListener("SIGINT", onSigint);
|
|
480
|
+
process.removeListener("SIGTERM", onSigterm);
|
|
481
|
+
process.removeListener("SIGWINCH", onSigwinch);
|
|
482
|
+
proxyProcess?.removeListener("error", proxyError);
|
|
483
|
+
proxyProcess?.removeListener("close", proxyClosed);
|
|
484
|
+
if (error) signalSandbox("SIGTERM");
|
|
485
|
+
stopProxy();
|
|
486
|
+
if (stdinPaused) process.stdin.resume();
|
|
487
|
+
if (error) reject(error);
|
|
488
|
+
else resolve(code);
|
|
489
|
+
}, "finish");
|
|
490
|
+
const forwardSignal = /* @__PURE__ */ __name((signal) => {
|
|
491
|
+
if (finished) return;
|
|
492
|
+
if (sandboxProcess?.pid) signalSandbox(signal);
|
|
493
|
+
else finish(null, signal === "SIGINT" ? 130 : 143);
|
|
494
|
+
}, "forwardSignal");
|
|
495
|
+
const onSigint = /* @__PURE__ */ __name(() => forwardSignal("SIGINT"), "onSigint");
|
|
496
|
+
const onSigterm = /* @__PURE__ */ __name(() => forwardSignal("SIGTERM"), "onSigterm");
|
|
497
|
+
const onSigwinch = /* @__PURE__ */ __name(() => signalSandbox("SIGWINCH"), "onSigwinch");
|
|
498
|
+
const proxyError = /* @__PURE__ */ __name((error) => finish(new FatalSandboxError(`Sandbox proxy failed: ${error.message}`)), "proxyError");
|
|
499
|
+
const proxyClosed = /* @__PURE__ */ __name((code, signal) => finish(
|
|
500
|
+
new FatalSandboxError(
|
|
501
|
+
`Sandbox proxy exited with code ${code}, signal ${signal}`
|
|
502
|
+
)
|
|
503
|
+
), "proxyClosed");
|
|
504
|
+
const launch = /* @__PURE__ */ __name(() => {
|
|
505
|
+
if (finished) return;
|
|
506
|
+
try {
|
|
507
|
+
process.stdin.pause();
|
|
508
|
+
stdinPaused = true;
|
|
509
|
+
sandboxProcess = spawn("bwrap", buildBwrapArgs(options), {
|
|
510
|
+
stdio: "inherit",
|
|
511
|
+
env,
|
|
512
|
+
// A separate session removes the host controlling terminal. Keep
|
|
513
|
+
// bwrap and its payload in one group so signals reach both.
|
|
514
|
+
detached: true
|
|
515
|
+
});
|
|
516
|
+
sandboxProcess.once("error", (error) => finish(error));
|
|
517
|
+
sandboxProcess.once(
|
|
518
|
+
"close",
|
|
519
|
+
(code, signal) => finish(
|
|
520
|
+
null,
|
|
521
|
+
code ?? (signal === "SIGINT" ? 130 : signal === "SIGTERM" ? 143 : 1)
|
|
522
|
+
)
|
|
523
|
+
);
|
|
524
|
+
} catch (error) {
|
|
525
|
+
finish(error);
|
|
526
|
+
}
|
|
527
|
+
}, "launch");
|
|
528
|
+
process.on("SIGINT", onSigint);
|
|
529
|
+
process.on("SIGTERM", onSigterm);
|
|
530
|
+
process.on("SIGWINCH", onSigwinch);
|
|
531
|
+
if (options.networkMode !== "proxied") {
|
|
532
|
+
launch();
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
535
|
+
try {
|
|
536
|
+
proxyProcess = spawn("bash", ["-c", env["QWEN_SANDBOX_PROXY_COMMAND"]], {
|
|
537
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
538
|
+
detached: true
|
|
539
|
+
});
|
|
540
|
+
proxyProcess.once("error", proxyError);
|
|
541
|
+
proxyProcess.once("close", proxyClosed);
|
|
542
|
+
proxyProcess.stderr?.on(
|
|
543
|
+
"data",
|
|
544
|
+
(data) => writeStderrLine(data.toString())
|
|
545
|
+
);
|
|
546
|
+
process.once("exit", stopProxy);
|
|
547
|
+
const proxy = env["HTTPS_PROXY"] || "http://localhost:8877";
|
|
548
|
+
writeStderrLine("waiting for proxy to start ...");
|
|
549
|
+
void execAsync(
|
|
550
|
+
`until curl --noproxy '*' --max-time 0.25 -s -o /dev/null ${(0, import_shell_quote.quote)([proxy])}; do sleep 0.25; done`,
|
|
551
|
+
{
|
|
552
|
+
signal: readiness.signal,
|
|
553
|
+
timeout: 3e4
|
|
554
|
+
}
|
|
555
|
+
).then(launch, proxyError);
|
|
556
|
+
} catch (error) {
|
|
557
|
+
proxyError(error);
|
|
558
|
+
}
|
|
559
|
+
});
|
|
560
|
+
}
|
|
561
|
+
__name(runBwrap, "runBwrap");
|
|
562
|
+
async function start_sandbox(config, nodeArgs = [], cliConfig, cliArgs = [], childEnv) {
|
|
563
|
+
if (config.command === "sandbox-exec") {
|
|
564
|
+
if (process.env["BUILD_SANDBOX"]) {
|
|
565
|
+
throw new FatalSandboxError(
|
|
566
|
+
"Cannot BUILD_SANDBOX when using macOS Seatbelt"
|
|
567
|
+
);
|
|
568
|
+
}
|
|
569
|
+
const profile = process.env["SEATBELT_PROFILE"] ??= "permissive-open";
|
|
570
|
+
const profileFile = resolveSeatbeltProfileFile(profile);
|
|
571
|
+
if (!fs.existsSync(profileFile)) {
|
|
572
|
+
throw new FatalSandboxError(
|
|
573
|
+
`Missing macos seatbelt profile file '${profileFile}'`
|
|
574
|
+
);
|
|
575
|
+
}
|
|
576
|
+
writeStderrLine(`using macos seatbelt (profile: ${profile}) ...`);
|
|
577
|
+
const nodeOptions = [
|
|
578
|
+
...process.env["DEBUG"] ? ["--inspect-brk"] : [],
|
|
579
|
+
...nodeArgs
|
|
580
|
+
].join(" ");
|
|
581
|
+
const qwenDir = Storage.getGlobalQwenDir();
|
|
582
|
+
const runtimeDir = Storage.getRuntimeBaseDir();
|
|
583
|
+
fs.mkdirSync(qwenDir, { recursive: true });
|
|
584
|
+
fs.mkdirSync(runtimeDir, { recursive: true });
|
|
585
|
+
const args2 = [
|
|
586
|
+
"-D",
|
|
587
|
+
`TARGET_DIR=${fs.realpathSync(process.cwd())}`,
|
|
588
|
+
"-D",
|
|
589
|
+
`TMP_DIR=${fs.realpathSync(os2.tmpdir())}`,
|
|
590
|
+
"-D",
|
|
591
|
+
`HOME_DIR=${fs.realpathSync(os2.homedir())}`,
|
|
592
|
+
"-D",
|
|
593
|
+
`CACHE_DIR=${fs.realpathSync(execSync(`getconf DARWIN_USER_CACHE_DIR`).toString().trim())}`,
|
|
594
|
+
"-D",
|
|
595
|
+
`QWEN_DIR=${fs.realpathSync(qwenDir)}`,
|
|
596
|
+
"-D",
|
|
597
|
+
`RUNTIME_DIR=${fs.realpathSync(runtimeDir)}`
|
|
598
|
+
];
|
|
599
|
+
const MAX_INCLUDE_DIRS = 5;
|
|
600
|
+
const targetDir = fs.realpathSync(cliConfig?.getTargetDir() || "");
|
|
601
|
+
const includedDirs = [];
|
|
602
|
+
if (cliConfig) {
|
|
603
|
+
const workspaceContext = cliConfig.getWorkspaceContext();
|
|
604
|
+
const directories = workspaceContext.getDirectories();
|
|
605
|
+
for (const dir of directories) {
|
|
606
|
+
const realDir = fs.realpathSync(dir);
|
|
607
|
+
if (realDir !== targetDir) {
|
|
608
|
+
includedDirs.push(realDir);
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
for (let i = 0; i < MAX_INCLUDE_DIRS; i++) {
|
|
613
|
+
let dirPath = "/dev/null";
|
|
614
|
+
if (i < includedDirs.length) {
|
|
615
|
+
dirPath = includedDirs[i];
|
|
616
|
+
}
|
|
617
|
+
args2.push("-D", `INCLUDE_DIR_${i}=${dirPath}`);
|
|
618
|
+
}
|
|
619
|
+
const finalArgv = cliArgs;
|
|
620
|
+
args2.push(
|
|
621
|
+
"-f",
|
|
622
|
+
profileFile,
|
|
623
|
+
"sh",
|
|
624
|
+
"-c",
|
|
625
|
+
[
|
|
626
|
+
...process.env["QWEN_CODE_SCRUB_ELECTRON_RUN_AS_NODE"] === "1" ? ["ELECTRON_RUN_AS_NODE=1"] : [],
|
|
627
|
+
`SANDBOX=sandbox-exec`,
|
|
628
|
+
`NODE_OPTIONS="${nodeOptions}"`,
|
|
629
|
+
...finalArgv.map((arg) => (0, import_shell_quote.quote)([arg]))
|
|
630
|
+
].join(" ")
|
|
631
|
+
);
|
|
632
|
+
const proxyCommand2 = process.env["QWEN_SANDBOX_PROXY_COMMAND"];
|
|
633
|
+
let proxyProcess2 = void 0;
|
|
634
|
+
let sandboxProcess2 = void 0;
|
|
635
|
+
const sandboxEnv = { ...process.env };
|
|
636
|
+
if (proxyCommand2) {
|
|
637
|
+
const proxy = process.env["HTTPS_PROXY"] || process.env["https_proxy"] || process.env["HTTP_PROXY"] || process.env["http_proxy"] || "http://localhost:8877";
|
|
638
|
+
sandboxEnv["HTTPS_PROXY"] = proxy;
|
|
639
|
+
sandboxEnv["https_proxy"] = proxy;
|
|
640
|
+
sandboxEnv["HTTP_PROXY"] = proxy;
|
|
641
|
+
sandboxEnv["http_proxy"] = proxy;
|
|
642
|
+
const noProxy = process.env["NO_PROXY"] || process.env["no_proxy"];
|
|
643
|
+
if (noProxy) {
|
|
644
|
+
sandboxEnv["NO_PROXY"] = noProxy;
|
|
645
|
+
sandboxEnv["no_proxy"] = noProxy;
|
|
646
|
+
}
|
|
647
|
+
proxyProcess2 = spawn("bash", ["-c", proxyCommand2], {
|
|
648
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
649
|
+
detached: true
|
|
650
|
+
});
|
|
651
|
+
const stopProxy = /* @__PURE__ */ __name(() => {
|
|
652
|
+
writeStderrLine("stopping proxy ...");
|
|
653
|
+
if (proxyProcess2?.pid) {
|
|
654
|
+
process.kill(-proxyProcess2.pid, "SIGTERM");
|
|
655
|
+
}
|
|
656
|
+
}, "stopProxy");
|
|
657
|
+
process.on("exit", stopProxy);
|
|
658
|
+
process.on("SIGINT", stopProxy);
|
|
659
|
+
process.on("SIGTERM", stopProxy);
|
|
660
|
+
proxyProcess2.stderr?.on("data", (data) => {
|
|
661
|
+
writeStderrLine(data.toString());
|
|
662
|
+
});
|
|
663
|
+
proxyProcess2.on("close", (code, signal) => {
|
|
664
|
+
if (sandboxProcess2?.pid) {
|
|
665
|
+
process.kill(-sandboxProcess2.pid, "SIGTERM");
|
|
666
|
+
}
|
|
667
|
+
throw new FatalSandboxError(
|
|
668
|
+
`Proxy command '${proxyCommand2}' exited with code ${code}, signal ${signal}`
|
|
669
|
+
);
|
|
670
|
+
});
|
|
671
|
+
writeStderrLine("waiting for proxy to start ...");
|
|
672
|
+
await execAsync(
|
|
673
|
+
`until timeout 0.25 curl -s http://localhost:8877; do sleep 0.25; done`
|
|
674
|
+
);
|
|
675
|
+
}
|
|
676
|
+
process.stdin.pause();
|
|
677
|
+
sandboxProcess2 = spawn(config.command, args2, {
|
|
678
|
+
stdio: "inherit",
|
|
679
|
+
...childEnv ? { env: { ...process.env, ...childEnv } } : {}
|
|
680
|
+
});
|
|
681
|
+
return new Promise((resolve, reject) => {
|
|
682
|
+
sandboxProcess2?.on("error", reject);
|
|
683
|
+
sandboxProcess2?.on("close", (code) => {
|
|
684
|
+
process.stdin.resume();
|
|
685
|
+
resolve(code ?? 1);
|
|
686
|
+
});
|
|
687
|
+
});
|
|
688
|
+
}
|
|
689
|
+
if (config.command === "bwrap") {
|
|
690
|
+
if (process.env["BUILD_SANDBOX"]) {
|
|
691
|
+
throw new FatalSandboxError("Cannot BUILD_SANDBOX when using bwrap");
|
|
692
|
+
}
|
|
693
|
+
const networkMode = resolveSandboxNetworkMode();
|
|
694
|
+
writeStderrLine(`using bwrap (network: ${networkMode}) ...`);
|
|
695
|
+
const {
|
|
696
|
+
targetDir,
|
|
697
|
+
roots: writableRoots,
|
|
698
|
+
readOnlyOverrides
|
|
699
|
+
} = resolveBwrapWritableRoots(
|
|
700
|
+
cliConfig ? cliConfig.getWorkspaceContext().getDirectories() : []
|
|
701
|
+
);
|
|
702
|
+
const nodeOptions = [
|
|
703
|
+
childEnv?.["NODE_OPTIONS"] ?? process.env["NODE_OPTIONS"],
|
|
704
|
+
...process.env["DEBUG"] ? ["--inspect-brk"] : [],
|
|
705
|
+
...nodeArgs
|
|
706
|
+
].filter(Boolean).join(" ");
|
|
707
|
+
const env = buildBwrapEnv(networkMode, { ...process.env, ...childEnv });
|
|
708
|
+
if (nodeOptions) env["NODE_OPTIONS"] = nodeOptions;
|
|
709
|
+
if (process.env["QWEN_CODE_SCRUB_ELECTRON_RUN_AS_NODE"] === "1") {
|
|
710
|
+
env["ELECTRON_RUN_AS_NODE"] = "1";
|
|
711
|
+
}
|
|
712
|
+
return runBwrap(
|
|
713
|
+
{ writableRoots, targetDir, networkMode, cliArgs, readOnlyOverrides },
|
|
714
|
+
env
|
|
715
|
+
);
|
|
716
|
+
}
|
|
717
|
+
writeStderrLine(`hopping into sandbox (command: ${config.command}) ...`);
|
|
718
|
+
const gcPath = fs.realpathSync(process.argv[1]);
|
|
719
|
+
const projectSandboxDockerfile = path2.join(
|
|
720
|
+
SETTINGS_DIRECTORY_NAME,
|
|
721
|
+
"sandbox.Dockerfile"
|
|
722
|
+
);
|
|
723
|
+
const isCustomProjectSandbox = fs.existsSync(projectSandboxDockerfile);
|
|
724
|
+
const image = config.image;
|
|
725
|
+
if (!image) {
|
|
726
|
+
throw new FatalSandboxError(
|
|
727
|
+
`Sandbox command '${config.command}' requires an image`
|
|
728
|
+
);
|
|
729
|
+
}
|
|
730
|
+
const workdir = path2.resolve(process.cwd());
|
|
731
|
+
const containerWorkdir = getContainerPath(workdir);
|
|
732
|
+
if (process.env["BUILD_SANDBOX"]) {
|
|
733
|
+
if (!gcPath.includes("qwen-code/packages/")) {
|
|
734
|
+
throw new FatalSandboxError(
|
|
735
|
+
"Cannot build sandbox using installed Qwen Code binary; run `npm link ./packages/cli` under QwenCode-cli repo to switch to linked binary."
|
|
736
|
+
);
|
|
737
|
+
} else {
|
|
738
|
+
writeStderrLine("building sandbox ...");
|
|
739
|
+
const gcRoot = gcPath.split("/packages/")[0];
|
|
740
|
+
let buildArgs = "";
|
|
741
|
+
const projectSandboxDockerfile2 = path2.join(
|
|
742
|
+
SETTINGS_DIRECTORY_NAME,
|
|
743
|
+
"sandbox.Dockerfile"
|
|
744
|
+
);
|
|
745
|
+
if (isCustomProjectSandbox) {
|
|
746
|
+
writeStderrLine(`using ${projectSandboxDockerfile2} for sandbox`);
|
|
747
|
+
buildArgs += `-f ${path2.resolve(projectSandboxDockerfile2)} -i ${image}`;
|
|
748
|
+
}
|
|
749
|
+
execSync(
|
|
750
|
+
`cd ${gcRoot} && node scripts/build_sandbox.js -s ${buildArgs}`,
|
|
751
|
+
{
|
|
752
|
+
stdio: "inherit",
|
|
753
|
+
env: {
|
|
754
|
+
...process.env,
|
|
755
|
+
QWEN_SANDBOX: config.command
|
|
756
|
+
// in case sandbox is enabled via flags (see config.ts under cli package)
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
);
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
if (!await ensureSandboxImageIsPresent(config.command, image)) {
|
|
763
|
+
const remedy = image === LOCAL_DEV_SANDBOX_IMAGE_NAME ? "Try running `npm run build:all` or `npm run build:sandbox` under the qwen-code repo to build it locally, or check the image name and your network connection." : "Please check the image name, your network connection, or notify qwen-code-dev@service.alibaba.com if the issue persists.";
|
|
764
|
+
throw new FatalSandboxError(
|
|
765
|
+
`Sandbox image '${image}' is missing or could not be pulled. ${remedy}`
|
|
766
|
+
);
|
|
767
|
+
}
|
|
768
|
+
const args = ["run", "-i", "--rm", "--init", "--workdir", containerWorkdir];
|
|
769
|
+
if (process.env["SANDBOX_FLAGS"]) {
|
|
770
|
+
const flags = (0, import_shell_quote.parse)(process.env["SANDBOX_FLAGS"], process.env).filter(
|
|
771
|
+
(f) => typeof f === "string"
|
|
772
|
+
);
|
|
773
|
+
args.push(...flags);
|
|
774
|
+
}
|
|
775
|
+
if (process.stdin.isTTY) {
|
|
776
|
+
args.push("-t");
|
|
777
|
+
}
|
|
778
|
+
args.push("--add-host", "host.docker.internal:host-gateway");
|
|
779
|
+
args.push("--volume", `${workdir}:${containerWorkdir}`);
|
|
780
|
+
const userSettingsDirOnHost = getUserSettingsDir();
|
|
781
|
+
const runtimeBaseDirOnHost = Storage.getRuntimeBaseDir();
|
|
782
|
+
const userSettingsDirRealPath = ensureDirectoryAndGetRealPath(
|
|
783
|
+
userSettingsDirOnHost
|
|
784
|
+
);
|
|
785
|
+
const runtimeBaseDirRealPath = ensureDirectoryAndGetRealPath(runtimeBaseDirOnHost);
|
|
786
|
+
const userSettingsDirInSandbox = getContainerPath(
|
|
787
|
+
`/home/node/${SETTINGS_DIRECTORY_NAME}`
|
|
788
|
+
);
|
|
789
|
+
const userSettingsDirContainerPath = getContainerPath(
|
|
790
|
+
userSettingsDirRealPath
|
|
791
|
+
);
|
|
792
|
+
const runtimeBaseDirContainerPath = getContainerPath(runtimeBaseDirRealPath);
|
|
793
|
+
const runtimeCoveredByUserSettings = isSubpath(
|
|
794
|
+
userSettingsDirRealPath,
|
|
795
|
+
runtimeBaseDirRealPath
|
|
796
|
+
);
|
|
797
|
+
const userSettingsCoveredByRuntime = isSubpath(
|
|
798
|
+
runtimeBaseDirRealPath,
|
|
799
|
+
userSettingsDirRealPath
|
|
800
|
+
);
|
|
801
|
+
const runtimeSameAsUserSettings = runtimeCoveredByUserSettings && userSettingsCoveredByRuntime;
|
|
802
|
+
args.push(
|
|
803
|
+
"--volume",
|
|
804
|
+
`${userSettingsDirRealPath}:${userSettingsDirInSandbox}`
|
|
805
|
+
);
|
|
806
|
+
if ((!userSettingsCoveredByRuntime || runtimeSameAsUserSettings) && userSettingsDirInSandbox !== userSettingsDirContainerPath) {
|
|
807
|
+
args.push(
|
|
808
|
+
"--volume",
|
|
809
|
+
`${userSettingsDirRealPath}:${userSettingsDirContainerPath}`
|
|
810
|
+
);
|
|
811
|
+
}
|
|
812
|
+
args.push("--env", `QWEN_HOME=${userSettingsDirContainerPath}`);
|
|
813
|
+
if (!runtimeCoveredByUserSettings) {
|
|
814
|
+
args.push(
|
|
815
|
+
"--volume",
|
|
816
|
+
`${runtimeBaseDirRealPath}:${runtimeBaseDirContainerPath}`
|
|
817
|
+
);
|
|
818
|
+
}
|
|
819
|
+
if (!runtimeSameAsUserSettings) {
|
|
820
|
+
args.push("--env", `QWEN_RUNTIME_DIR=${runtimeBaseDirContainerPath}`);
|
|
821
|
+
}
|
|
822
|
+
args.push("--volume", `${os2.tmpdir()}:${getContainerPath(os2.tmpdir())}`);
|
|
823
|
+
const gcloudConfigDir = path2.join(os2.homedir(), ".config", "gcloud");
|
|
824
|
+
if (fs.existsSync(gcloudConfigDir)) {
|
|
825
|
+
args.push(
|
|
826
|
+
"--volume",
|
|
827
|
+
`${gcloudConfigDir}:${getContainerPath(gcloudConfigDir)}:ro`
|
|
828
|
+
);
|
|
829
|
+
}
|
|
830
|
+
if (process.env["GOOGLE_APPLICATION_CREDENTIALS"]) {
|
|
831
|
+
const adcFile = process.env["GOOGLE_APPLICATION_CREDENTIALS"];
|
|
832
|
+
if (fs.existsSync(adcFile)) {
|
|
833
|
+
args.push("--volume", `${adcFile}:${getContainerPath(adcFile)}:ro`);
|
|
834
|
+
args.push(
|
|
835
|
+
"--env",
|
|
836
|
+
`GOOGLE_APPLICATION_CREDENTIALS=${getContainerPath(adcFile)}`
|
|
837
|
+
);
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
if (process.env["SANDBOX_MOUNTS"]) {
|
|
841
|
+
for (let mount of process.env["SANDBOX_MOUNTS"].split(",")) {
|
|
842
|
+
if (mount.trim()) {
|
|
843
|
+
const { from, to, opts } = parseSandboxMountSpec(mount);
|
|
844
|
+
mount = `${from}:${to}:${opts}`;
|
|
845
|
+
if (!path2.isAbsolute(from)) {
|
|
846
|
+
throw new FatalSandboxError(
|
|
847
|
+
`Path '${from}' listed in SANDBOX_MOUNTS must be absolute`
|
|
848
|
+
);
|
|
849
|
+
}
|
|
850
|
+
if (!fs.existsSync(from)) {
|
|
851
|
+
throw new FatalSandboxError(
|
|
852
|
+
`Missing mount path '${from}' listed in SANDBOX_MOUNTS`
|
|
853
|
+
);
|
|
854
|
+
}
|
|
855
|
+
writeStderrLine(`SANDBOX_MOUNTS: ${from} -> ${to} (${opts})`);
|
|
856
|
+
args.push("--volume", mount);
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
ports().forEach((p) => args.push("--publish", `${p}:${p}`));
|
|
861
|
+
if (process.env["DEBUG"]) {
|
|
862
|
+
const debugPort = process.env["DEBUG_PORT"] || "9229";
|
|
863
|
+
args.push(`--publish`, `${debugPort}:${debugPort}`);
|
|
864
|
+
}
|
|
865
|
+
const proxyCommand = process.env["QWEN_SANDBOX_PROXY_COMMAND"];
|
|
866
|
+
if (proxyCommand) {
|
|
867
|
+
let proxy = process.env["HTTPS_PROXY"] || process.env["https_proxy"] || process.env["HTTP_PROXY"] || process.env["http_proxy"] || "http://localhost:8877";
|
|
868
|
+
proxy = proxy.replace("localhost", SANDBOX_PROXY_NAME);
|
|
869
|
+
if (proxy) {
|
|
870
|
+
args.push("--env", `HTTPS_PROXY=${proxy}`);
|
|
871
|
+
args.push("--env", `https_proxy=${proxy}`);
|
|
872
|
+
args.push("--env", `HTTP_PROXY=${proxy}`);
|
|
873
|
+
args.push("--env", `http_proxy=${proxy}`);
|
|
874
|
+
}
|
|
875
|
+
const noProxy = process.env["NO_PROXY"] || process.env["no_proxy"];
|
|
876
|
+
if (noProxy) {
|
|
877
|
+
args.push("--env", `NO_PROXY=${noProxy}`);
|
|
878
|
+
args.push("--env", `no_proxy=${noProxy}`);
|
|
879
|
+
}
|
|
880
|
+
if (proxy) {
|
|
881
|
+
execSync(
|
|
882
|
+
`${config.command} network inspect ${SANDBOX_NETWORK_NAME} || ${config.command} network create --internal ${SANDBOX_NETWORK_NAME}`
|
|
883
|
+
);
|
|
884
|
+
args.push("--network", SANDBOX_NETWORK_NAME);
|
|
885
|
+
if (proxyCommand) {
|
|
886
|
+
execSync(
|
|
887
|
+
`${config.command} network inspect ${SANDBOX_PROXY_NAME} || ${config.command} network create ${SANDBOX_PROXY_NAME}`
|
|
888
|
+
);
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
const imageName = parseSandboxImageName(image);
|
|
893
|
+
const isIntegrationTest = process.env["QWEN_CODE_INTEGRATION_TEST"] === "true";
|
|
894
|
+
let containerName;
|
|
895
|
+
if (isIntegrationTest) {
|
|
896
|
+
containerName = `qwen-code-integration-test-${randomBytes(4).toString(
|
|
897
|
+
"hex"
|
|
898
|
+
)}`;
|
|
899
|
+
writeStderrLine(`ContainerName: ${containerName}`);
|
|
900
|
+
} else {
|
|
901
|
+
containerName = `${imageName}-${randomBytes(4).toString("hex")}`;
|
|
902
|
+
writeStderrLine(`ContainerName (regular): ${containerName}`);
|
|
903
|
+
}
|
|
904
|
+
args.push("--name", containerName);
|
|
905
|
+
if (containerName.length <= 64) {
|
|
906
|
+
args.push("--hostname", containerName);
|
|
907
|
+
}
|
|
908
|
+
if (process.env["QWEN_CODE_TEST_VAR"]) {
|
|
909
|
+
args.push(
|
|
910
|
+
"--env",
|
|
911
|
+
`QWEN_CODE_TEST_VAR=${process.env["QWEN_CODE_TEST_VAR"]}`
|
|
912
|
+
);
|
|
913
|
+
}
|
|
914
|
+
args.push(...getSandboxPassthroughEnvArgs());
|
|
915
|
+
if (process.env["QWEN_CODE_MCP_APPROVALS_PATH"]) {
|
|
916
|
+
args.push(
|
|
917
|
+
"--env",
|
|
918
|
+
`QWEN_CODE_MCP_APPROVALS_PATH=${getContainerPath(
|
|
919
|
+
process.env["QWEN_CODE_MCP_APPROVALS_PATH"]
|
|
920
|
+
)}`
|
|
921
|
+
);
|
|
922
|
+
}
|
|
923
|
+
if (process.env["QWEN_CODE_WARNINGS_FILE"]) {
|
|
924
|
+
args.push(
|
|
925
|
+
"--env",
|
|
926
|
+
`QWEN_CODE_WARNINGS_FILE=${getContainerPath(
|
|
927
|
+
process.env["QWEN_CODE_WARNINGS_FILE"]
|
|
928
|
+
)}`
|
|
929
|
+
);
|
|
930
|
+
}
|
|
931
|
+
if (process.env["GEMINI_API_KEY"]) {
|
|
932
|
+
args.push("--env", `GEMINI_API_KEY=${process.env["GEMINI_API_KEY"]}`);
|
|
933
|
+
}
|
|
934
|
+
if (process.env["GOOGLE_API_KEY"]) {
|
|
935
|
+
args.push("--env", `GOOGLE_API_KEY=${process.env["GOOGLE_API_KEY"]}`);
|
|
936
|
+
}
|
|
937
|
+
if (process.env["OPENAI_API_KEY"]) {
|
|
938
|
+
args.push("--env", `OPENAI_API_KEY=${process.env["OPENAI_API_KEY"]}`);
|
|
939
|
+
}
|
|
940
|
+
if (process.env["OPENAI_BASE_URL"]) {
|
|
941
|
+
args.push("--env", `OPENAI_BASE_URL=${process.env["OPENAI_BASE_URL"]}`);
|
|
942
|
+
}
|
|
943
|
+
if (process.env["OPENAI_MODEL"]) {
|
|
944
|
+
args.push("--env", `OPENAI_MODEL=${process.env["OPENAI_MODEL"]}`);
|
|
945
|
+
}
|
|
946
|
+
if (process.env["GOOGLE_GENAI_USE_VERTEXAI"]) {
|
|
947
|
+
args.push(
|
|
948
|
+
"--env",
|
|
949
|
+
`GOOGLE_GENAI_USE_VERTEXAI=${process.env["GOOGLE_GENAI_USE_VERTEXAI"]}`
|
|
950
|
+
);
|
|
951
|
+
}
|
|
952
|
+
if (process.env["GOOGLE_GENAI_USE_GCA"]) {
|
|
953
|
+
args.push(
|
|
954
|
+
"--env",
|
|
955
|
+
`GOOGLE_GENAI_USE_GCA=${process.env["GOOGLE_GENAI_USE_GCA"]}`
|
|
956
|
+
);
|
|
957
|
+
}
|
|
958
|
+
if (process.env["GOOGLE_CLOUD_PROJECT"]) {
|
|
959
|
+
args.push(
|
|
960
|
+
"--env",
|
|
961
|
+
`GOOGLE_CLOUD_PROJECT=${process.env["GOOGLE_CLOUD_PROJECT"]}`
|
|
962
|
+
);
|
|
963
|
+
}
|
|
964
|
+
if (process.env["GOOGLE_CLOUD_LOCATION"]) {
|
|
965
|
+
args.push(
|
|
966
|
+
"--env",
|
|
967
|
+
`GOOGLE_CLOUD_LOCATION=${process.env["GOOGLE_CLOUD_LOCATION"]}`
|
|
968
|
+
);
|
|
969
|
+
}
|
|
970
|
+
if (process.env["GEMINI_MODEL"]) {
|
|
971
|
+
args.push("--env", `GEMINI_MODEL=${process.env["GEMINI_MODEL"]}`);
|
|
972
|
+
}
|
|
973
|
+
if (process.env["TERM"]) {
|
|
974
|
+
args.push("--env", `TERM=${process.env["TERM"]}`);
|
|
975
|
+
}
|
|
976
|
+
if (process.env["COLORTERM"]) {
|
|
977
|
+
args.push("--env", `COLORTERM=${process.env["COLORTERM"]}`);
|
|
978
|
+
}
|
|
979
|
+
for (const envVar of [
|
|
980
|
+
"QWEN_CODE_IDE_SERVER_PORT",
|
|
981
|
+
"QWEN_CODE_IDE_WORKSPACE_PATH",
|
|
982
|
+
"TERM_PROGRAM"
|
|
983
|
+
]) {
|
|
984
|
+
if (process.env[envVar]) {
|
|
985
|
+
args.push("--env", `${envVar}=${process.env[envVar]}`);
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
const virtualEnv = process.env["VIRTUAL_ENV"];
|
|
989
|
+
if (virtualEnv && isContainerPathWithinWorkdir(
|
|
990
|
+
getContainerPath(workdir),
|
|
991
|
+
getContainerPath(virtualEnv)
|
|
992
|
+
)) {
|
|
993
|
+
const sandboxVenvPath = path2.resolve(
|
|
994
|
+
SETTINGS_DIRECTORY_NAME,
|
|
995
|
+
"sandbox.venv"
|
|
996
|
+
);
|
|
997
|
+
if (!fs.existsSync(sandboxVenvPath)) {
|
|
998
|
+
fs.mkdirSync(sandboxVenvPath, { recursive: true });
|
|
999
|
+
}
|
|
1000
|
+
args.push("--volume", `${sandboxVenvPath}:${getContainerPath(virtualEnv)}`);
|
|
1001
|
+
args.push("--env", `VIRTUAL_ENV=${getContainerPath(virtualEnv)}`);
|
|
1002
|
+
}
|
|
1003
|
+
if (process.env["SANDBOX_ENV"]) {
|
|
1004
|
+
for (let env of process.env["SANDBOX_ENV"].split(",")) {
|
|
1005
|
+
if (env = env.trim()) {
|
|
1006
|
+
if (env.includes("=")) {
|
|
1007
|
+
writeStderrLine(`SANDBOX_ENV: ${env}`);
|
|
1008
|
+
args.push("--env", env);
|
|
1009
|
+
} else {
|
|
1010
|
+
throw new FatalSandboxError(
|
|
1011
|
+
"SANDBOX_ENV must be a comma-separated list of key=value pairs"
|
|
1012
|
+
);
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
for (const name of Object.keys(childEnv ?? {})) {
|
|
1018
|
+
args.push("--env", name);
|
|
1019
|
+
}
|
|
1020
|
+
const existingNodeOptions = process.env["NODE_OPTIONS"] || "";
|
|
1021
|
+
const allNodeOptions = [
|
|
1022
|
+
...existingNodeOptions ? [existingNodeOptions] : [],
|
|
1023
|
+
...nodeArgs
|
|
1024
|
+
].join(" ");
|
|
1025
|
+
if (allNodeOptions.length > 0) {
|
|
1026
|
+
args.push("--env", `NODE_OPTIONS="${allNodeOptions}"`);
|
|
1027
|
+
}
|
|
1028
|
+
args.push("--env", `SANDBOX=${containerName}`);
|
|
1029
|
+
if (config.command === "podman") {
|
|
1030
|
+
const emptyAuthFilePath = path2.join(os2.tmpdir(), "empty_auth.json");
|
|
1031
|
+
fs.writeFileSync(emptyAuthFilePath, "{}", "utf-8");
|
|
1032
|
+
args.push("--authfile", emptyAuthFilePath);
|
|
1033
|
+
}
|
|
1034
|
+
let userFlag = "";
|
|
1035
|
+
const finalEntrypoint = entrypoint(workdir, cliArgs);
|
|
1036
|
+
const useCurrentUser = await shouldUseCurrentUserInSandbox();
|
|
1037
|
+
if (useCurrentUser) {
|
|
1038
|
+
args.push("--user", "root");
|
|
1039
|
+
const uid = execSync("id -u").toString().trim();
|
|
1040
|
+
const gid = execSync("id -g").toString().trim();
|
|
1041
|
+
const username = "qwen";
|
|
1042
|
+
const homeDir = getContainerPath(os2.homedir());
|
|
1043
|
+
const setupUserCommands = [
|
|
1044
|
+
// Use -f with groupadd to avoid errors if the group already exists.
|
|
1045
|
+
`groupadd -f -g ${gid} ${username}`,
|
|
1046
|
+
// Create user only if it doesn't exist. Use -o for non-unique UID.
|
|
1047
|
+
`id -u ${username} &>/dev/null || useradd -o -u ${uid} -g ${gid} -d ${homeDir} -s /bin/bash ${username}`
|
|
1048
|
+
].join(" && ");
|
|
1049
|
+
const originalCommand = finalEntrypoint[2];
|
|
1050
|
+
const escapedOriginalCommand = originalCommand.replace(/'/g, "'\\''");
|
|
1051
|
+
const suCommand = `su -p ${username} -c '${escapedOriginalCommand}'`;
|
|
1052
|
+
finalEntrypoint[2] = `${setupUserCommands} && ${suCommand}`;
|
|
1053
|
+
userFlag = `--user ${uid}:${gid}`;
|
|
1054
|
+
args.push("--env", `HOME=${os2.homedir()}`);
|
|
1055
|
+
} else if (isIntegrationTest) {
|
|
1056
|
+
args.push("--user", "root");
|
|
1057
|
+
userFlag = "--user root";
|
|
1058
|
+
}
|
|
1059
|
+
args.push(image);
|
|
1060
|
+
args.push(...finalEntrypoint);
|
|
1061
|
+
let proxyProcess = void 0;
|
|
1062
|
+
let sandboxProcess = void 0;
|
|
1063
|
+
if (proxyCommand) {
|
|
1064
|
+
const proxyContainerCommand = `${config.command} run --rm --init ${userFlag} --name ${SANDBOX_PROXY_NAME} --network ${SANDBOX_PROXY_NAME} -p 8877:8877 -v ${process.cwd()}:${workdir} --workdir ${workdir} ${image} ${proxyCommand}`;
|
|
1065
|
+
const isWindows = os2.platform() === "win32";
|
|
1066
|
+
const proxyShell = isWindows ? "cmd.exe" : "bash";
|
|
1067
|
+
const proxyShellArgs = isWindows ? ["/c", proxyContainerCommand] : ["-c", proxyContainerCommand];
|
|
1068
|
+
proxyProcess = spawn(proxyShell, proxyShellArgs, {
|
|
1069
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
1070
|
+
detached: true
|
|
1071
|
+
});
|
|
1072
|
+
const stopProxy = /* @__PURE__ */ __name(() => {
|
|
1073
|
+
writeStderrLine("stopping proxy container ...");
|
|
1074
|
+
execSync(`${config.command} rm -f ${SANDBOX_PROXY_NAME}`);
|
|
1075
|
+
}, "stopProxy");
|
|
1076
|
+
process.on("exit", stopProxy);
|
|
1077
|
+
process.on("SIGINT", stopProxy);
|
|
1078
|
+
process.on("SIGTERM", stopProxy);
|
|
1079
|
+
proxyProcess.stderr?.on("data", (data) => {
|
|
1080
|
+
writeStderrLine(data.toString().trim());
|
|
1081
|
+
});
|
|
1082
|
+
proxyProcess.on("close", (code, signal) => {
|
|
1083
|
+
if (sandboxProcess?.pid) {
|
|
1084
|
+
process.kill(-sandboxProcess.pid, "SIGTERM");
|
|
1085
|
+
}
|
|
1086
|
+
throw new FatalSandboxError(
|
|
1087
|
+
`Proxy container command '${proxyContainerCommand}' exited with code ${code}, signal ${signal}`
|
|
1088
|
+
);
|
|
1089
|
+
});
|
|
1090
|
+
writeStderrLine("waiting for proxy to start ...");
|
|
1091
|
+
await execAsync(
|
|
1092
|
+
`until timeout 0.25 curl -s http://localhost:8877; do sleep 0.25; done`
|
|
1093
|
+
);
|
|
1094
|
+
await execAsync(
|
|
1095
|
+
`${config.command} network connect ${SANDBOX_NETWORK_NAME} ${SANDBOX_PROXY_NAME}`
|
|
1096
|
+
);
|
|
1097
|
+
}
|
|
1098
|
+
process.stdin.pause();
|
|
1099
|
+
sandboxProcess = spawn(config.command, args, {
|
|
1100
|
+
stdio: "inherit",
|
|
1101
|
+
...childEnv ? { env: { ...process.env, ...childEnv } } : {}
|
|
1102
|
+
});
|
|
1103
|
+
return new Promise((resolve, reject) => {
|
|
1104
|
+
sandboxProcess.on("error", (err) => {
|
|
1105
|
+
writeStderrLine(`Sandbox process error: ${err}`);
|
|
1106
|
+
reject(err);
|
|
1107
|
+
});
|
|
1108
|
+
sandboxProcess?.on("close", (code, signal) => {
|
|
1109
|
+
process.stdin.resume();
|
|
1110
|
+
if (code !== 0 && code !== null) {
|
|
1111
|
+
writeStderrLine(
|
|
1112
|
+
`Sandbox process exited with code: ${code}, signal: ${signal}`
|
|
1113
|
+
);
|
|
1114
|
+
}
|
|
1115
|
+
resolve(code ?? 1);
|
|
1116
|
+
});
|
|
1117
|
+
});
|
|
1118
|
+
}
|
|
1119
|
+
__name(start_sandbox, "start_sandbox");
|
|
1120
|
+
async function imageExists(sandbox, image) {
|
|
1121
|
+
return new Promise((resolve) => {
|
|
1122
|
+
const args = ["image", "inspect", "--format", "{{.Id}}", image];
|
|
1123
|
+
const checkProcess = spawn(sandbox, args);
|
|
1124
|
+
let stdoutData = "";
|
|
1125
|
+
if (checkProcess.stdout) {
|
|
1126
|
+
checkProcess.stdout.on("data", (data) => {
|
|
1127
|
+
stdoutData += data.toString();
|
|
1128
|
+
});
|
|
1129
|
+
}
|
|
1130
|
+
checkProcess.on("error", (err) => {
|
|
1131
|
+
writeStderrLine(
|
|
1132
|
+
`Failed to start '${sandbox}' command for image check: ${err.message}`
|
|
1133
|
+
);
|
|
1134
|
+
resolve(false);
|
|
1135
|
+
});
|
|
1136
|
+
checkProcess.on("close", () => {
|
|
1137
|
+
resolve(stdoutData.trim() !== "");
|
|
1138
|
+
});
|
|
1139
|
+
});
|
|
1140
|
+
}
|
|
1141
|
+
__name(imageExists, "imageExists");
|
|
1142
|
+
async function pullImage(sandbox, image) {
|
|
1143
|
+
writeStderrLine(`Attempting to pull image ${image} using ${sandbox}...`);
|
|
1144
|
+
return new Promise((resolve) => {
|
|
1145
|
+
const args = ["pull", image];
|
|
1146
|
+
const pullProcess = spawn(sandbox, args, { stdio: "pipe" });
|
|
1147
|
+
let stderrData = "";
|
|
1148
|
+
const onStdoutData = /* @__PURE__ */ __name((data) => {
|
|
1149
|
+
writeStderrLine(data.toString().trim());
|
|
1150
|
+
}, "onStdoutData");
|
|
1151
|
+
const onStderrData = /* @__PURE__ */ __name((data) => {
|
|
1152
|
+
stderrData += data.toString();
|
|
1153
|
+
writeStderrLine(data.toString().trim());
|
|
1154
|
+
}, "onStderrData");
|
|
1155
|
+
const onError = /* @__PURE__ */ __name((err) => {
|
|
1156
|
+
writeStderrLine(
|
|
1157
|
+
`Failed to start '${sandbox} pull ${image}' command: ${err.message}`
|
|
1158
|
+
);
|
|
1159
|
+
cleanup();
|
|
1160
|
+
resolve(false);
|
|
1161
|
+
}, "onError");
|
|
1162
|
+
const onClose = /* @__PURE__ */ __name((code) => {
|
|
1163
|
+
if (code === 0) {
|
|
1164
|
+
writeStderrLine(`Successfully pulled image ${image}.`);
|
|
1165
|
+
cleanup();
|
|
1166
|
+
resolve(true);
|
|
1167
|
+
} else {
|
|
1168
|
+
writeStderrLine(
|
|
1169
|
+
`Failed to pull image ${image}. '${sandbox} pull ${image}' exited with code ${code}.`
|
|
1170
|
+
);
|
|
1171
|
+
if (stderrData.trim()) {
|
|
1172
|
+
}
|
|
1173
|
+
cleanup();
|
|
1174
|
+
resolve(false);
|
|
1175
|
+
}
|
|
1176
|
+
}, "onClose");
|
|
1177
|
+
const cleanup = /* @__PURE__ */ __name(() => {
|
|
1178
|
+
if (pullProcess.stdout) {
|
|
1179
|
+
pullProcess.stdout.removeListener("data", onStdoutData);
|
|
1180
|
+
}
|
|
1181
|
+
if (pullProcess.stderr) {
|
|
1182
|
+
pullProcess.stderr.removeListener("data", onStderrData);
|
|
1183
|
+
}
|
|
1184
|
+
pullProcess.removeListener("error", onError);
|
|
1185
|
+
pullProcess.removeListener("close", onClose);
|
|
1186
|
+
if (pullProcess.connected) {
|
|
1187
|
+
pullProcess.disconnect();
|
|
1188
|
+
}
|
|
1189
|
+
}, "cleanup");
|
|
1190
|
+
if (pullProcess.stdout) {
|
|
1191
|
+
pullProcess.stdout.on("data", onStdoutData);
|
|
1192
|
+
}
|
|
1193
|
+
if (pullProcess.stderr) {
|
|
1194
|
+
pullProcess.stderr.on("data", onStderrData);
|
|
1195
|
+
}
|
|
1196
|
+
pullProcess.on("error", onError);
|
|
1197
|
+
pullProcess.on("close", onClose);
|
|
1198
|
+
});
|
|
1199
|
+
}
|
|
1200
|
+
__name(pullImage, "pullImage");
|
|
1201
|
+
async function ensureSandboxImageIsPresent(sandbox, image) {
|
|
1202
|
+
writeStderrLine(`Checking for sandbox image: ${image}`);
|
|
1203
|
+
if (await imageExists(sandbox, image)) {
|
|
1204
|
+
writeStderrLine(`Sandbox image ${image} found locally.`);
|
|
1205
|
+
return true;
|
|
1206
|
+
}
|
|
1207
|
+
writeStderrLine(`Sandbox image ${image} not found locally.`);
|
|
1208
|
+
if (image === LOCAL_DEV_SANDBOX_IMAGE_NAME) {
|
|
1209
|
+
return false;
|
|
1210
|
+
}
|
|
1211
|
+
if (await pullImage(sandbox, image)) {
|
|
1212
|
+
if (await imageExists(sandbox, image)) {
|
|
1213
|
+
writeStderrLine(`Sandbox image ${image} is now available after pulling.`);
|
|
1214
|
+
return true;
|
|
1215
|
+
} else {
|
|
1216
|
+
writeStderrLine(
|
|
1217
|
+
`Sandbox image ${image} still not found after a pull attempt. This might indicate an issue with the image name or registry, or the pull command reported success but failed to make the image available.`
|
|
1218
|
+
);
|
|
1219
|
+
return false;
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
writeStderrLine(
|
|
1223
|
+
`Failed to obtain sandbox image ${image} after check and pull attempt.`
|
|
1224
|
+
);
|
|
1225
|
+
return false;
|
|
1226
|
+
}
|
|
1227
|
+
__name(ensureSandboxImageIsPresent, "ensureSandboxImageIsPresent");
|
|
1228
|
+
|
|
1229
|
+
export {
|
|
1230
|
+
BUILTIN_SEATBELT_PROFILES,
|
|
1231
|
+
getSandboxPassthroughEnvArgs,
|
|
1232
|
+
resolveSeatbeltProfileFile,
|
|
1233
|
+
resolveSandboxNetworkMode,
|
|
1234
|
+
resolveGitWritableRoots,
|
|
1235
|
+
normalizeWritableRoots,
|
|
1236
|
+
resolveBwrapWritableRoots,
|
|
1237
|
+
buildBwrapArgs,
|
|
1238
|
+
buildBwrapEnv,
|
|
1239
|
+
runBwrap,
|
|
1240
|
+
start_sandbox
|
|
1241
|
+
};
|
|
1242
|
+
/**
|
|
1243
|
+
* @license
|
|
1244
|
+
* Copyright 2025 Google LLC
|
|
1245
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
1246
|
+
*/
|