@seanhogg/builderforce-agents 2026.10.9 → 2026.10.11
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/dist/{acp-cli-DcKpPsJa.js → acp-cli-C23mmrQt.js} +1 -1
- package/dist/{acp-cli-BxH-eUDl.js → acp-cli-D6F-D5JB.js} +1 -1
- package/dist/{agent-cXF-aL0g.js → agent-B-2r1Lr_.js} +1 -1
- package/dist/{agent-wJmvciTM.js → agent-BI9qSnSp.js} +1 -1
- package/dist/{agentbot-cli-Cub3Abbt.js → agentbot-cli-Cyrhr5jX.js} +1 -1
- package/dist/{agentbot-cli-CTRvEfBp.js → agentbot-cli-sC55m-XS.js} +1 -1
- package/dist/{agents-Cr7WO73I.js → agents-CMThT_Bj.js} +1 -1
- package/dist/agents-Chz9nfm2.js +1 -0
- package/dist/{api-key-rotation-CHBjUwUJ.js → api-key-rotation-CyCi-UqR.js} +1 -1
- package/dist/{audio-preflight-CWFuqbao.js → audio-preflight-B411b2-y.js} +1 -1
- package/dist/{audio-preflight-F2e3Y4CW.js → audio-preflight-Cs4eUjQk.js} +1 -1
- package/dist/{audit-DGnEhZYe.js → audit-B-USV03V.js} +1 -1
- package/dist/{audit-DBjjjW93.js → audit-SKNPS-K2.js} +1 -1
- package/dist/auth-choice-CChsMy-F.js +1 -0
- package/dist/{auth-choice-9gZuOvPS.js → auth-choice-CCib_yVL.js} +1 -1
- package/dist/auth-choice-DSnpkrMc.js +1 -0
- package/dist/{auth-choice-BoZFVmEa.js → auth-choice-DzBqqq7i.js} +1 -1
- package/dist/auth-choice.apply-6f3Jb_lS.js +1 -0
- package/dist/{auth-choice.apply-CcatXiNo.js → auth-choice.apply-BgOXoS8X.js} +1 -1
- package/dist/{auth-choice.apply-BHLQeym9.js → auth-choice.apply-DBuvopiF.js} +1 -1
- package/dist/auth-choice.apply-DeXnLwVS.js +1 -0
- package/dist/auth-choice.apply.transformers-CZDuBaOr.js +1 -0
- package/dist/{auth-choice.apply.transformers-CIn3fs7K.js → auth-choice.apply.transformers-Df9l_jRz.js} +2 -2
- package/dist/{auth-choice.apply.transformers-1plI0MUg.js → auth-choice.apply.transformers-DmdxpHGz.js} +2 -2
- package/dist/{auth-choice.apply.transformers-D5OrjEHo.js → auth-choice.apply.transformers-dn7l6XyJ.js} +1 -1
- package/dist/{auth-json-D1ite-pW.js → auth-json-BB-VBn5E.js} +1 -1
- package/dist/{auth-json-CN3MWw57.js → auth-json-BVyos95N.js} +1 -1
- package/dist/{auth-json-HGu227VM.js → auth-json-CoOe4tEg.js} +1 -1
- package/dist/{auth-json-DZ7E50Y1.js → auth-json-wrKixZxh.js} +1 -1
- package/dist/{auth-profiles-C1VbcUOm.js → auth-profiles-pt7Tr4HA.js} +1 -1
- package/dist/{auth-token-CyVfNEQb.js → auth-token-BE67qxLw.js} +1 -1
- package/dist/{auth-token-CoQ5ePPl.js → auth-token-BPHeoBAW.js} +1 -1
- package/dist/{banner-DY-L7_eI.js → banner-ErBINvbk.js} +1 -1
- package/dist/{browser-cli-D2O94twn.js → browser-cli-BZc64-Xx.js} +1 -1
- package/dist/{browser-cli-CoRx_4iM.js → browser-cli-CoxVKdon.js} +1 -1
- package/dist/build-info.json +3 -3
- package/dist/{builderforce-BmrsVdFw.js → builderforce-B9187Tm9.js} +4 -4
- package/dist/{builderforce-Bwyw0GJ6.js → builderforce-BLqHwgeu.js} +4 -4
- package/dist/builderforce-api-DKgXl8BH.js +1 -0
- package/dist/builderforce-api-DcPAGsla.js +1 -0
- package/dist/builderforce-onboarding-CaPJZSvw.js +24 -0
- package/dist/builderforce-onboarding-RXFb0gct.js +24 -0
- package/dist/{builderforcellm-syscheck-CprBhARf.js → builderforcellm-syscheck-9ksvqHYX.js} +1 -1
- package/dist/{builderforcellm-syscheck-DrFJ638L.js → builderforcellm-syscheck-F5JMAr3p.js} +1 -1
- package/dist/{call-DxPWzV-k.js → call-BnAs_SER.js} +1 -1
- package/dist/{call-DFjBq0H2.js → call-D1Opj5ev.js} +1 -1
- package/dist/{call-DmAU4cRX.js → call-Du2LiaX6.js} +1 -1
- package/dist/{call-BbRf8gFM.js → call-T8ciwMTA.js} +1 -1
- package/dist/{channel-options-d4EwVQD0.js → channel-options-B7sRMp2v.js} +1 -1
- package/dist/{channel-options-CDixz6dT.js → channel-options-rhDBCtlp.js} +1 -1
- package/dist/{channel-web-DJa8JC9W.js → channel-web-CcCqUQrJ.js} +1 -1
- package/dist/{channels-cli-BgKy0MbE.js → channels-cli-BjnLW14T.js} +1 -1
- package/dist/{channels-cli-nNW0ezPM.js → channels-cli-DVWUBsmc.js} +1 -1
- package/dist/{chrome-BnEbJV3D.js → chrome-CFmcixaE.js} +1 -1
- package/dist/{chrome-a3X9_-nf.js → chrome-DXt86tmV.js} +1 -1
- package/dist/cli/daemon-cli.js +1 -1
- package/dist/{cli-DkWt7p2x.js → cli-BUqtALJK.js} +1 -1
- package/dist/{cli-C5MbcECQ.js → cli-K4reS6IS.js} +1 -1
- package/dist/{coding-tools.policy-NEPm7Mz1.js → coding-tools.policy-D9Ba8eDh.js} +1 -1
- package/dist/{coding-tools.policy-6qh9acJy.js → coding-tools.policy-ZhOdlcEI.js} +1 -1
- package/dist/{command-registry-COUcUWby.js → command-registry-B7uAoROP.js} +1 -1
- package/dist/{command-registry-4_K-lfW5.js → command-registry-CW16Mk2Y.js} +1 -1
- package/dist/{completion-cli-DlvHqL86.js → completion-cli-ZvXrCQqk.js} +1 -1
- package/dist/{completion-cli-B2qcVd6q.js → completion-cli-gyvx5ZXu.js} +1 -1
- package/dist/{completion-cli-DpFvU4Qn.js → completion-cli-n8UsdT91.js} +1 -1
- package/dist/{completion-cli-SdcQ-kQj.js → completion-cli-sKReGv3d.js} +1 -1
- package/dist/{config-_1Ca6jGb.js → config-BgV_FYSq.js} +1 -1
- package/dist/{config-toczWD3q.js → config-BpChMIJ6.js} +1 -1
- package/dist/{config-BTWlKwtB.js → config-D01EgOky.js} +1 -1
- package/dist/{config-27_FNba3.js → config-Dsnbi-a3.js} +1 -1
- package/dist/{config-cli-DeiQz5sY.js → config-cli-Bpo74mE5.js} +1 -1
- package/dist/{config-cli-CfczShaZ.js → config-cli-CF31O_5s.js} +1 -1
- package/dist/{config-guard-CD-Wq8kk.js → config-guard-BRUOk5YL.js} +1 -1
- package/dist/{config-guard-ClVl2FvD.js → config-guard-BUpQiSTW.js} +1 -1
- package/dist/{config-guard-B4in8l8I.js → config-guard-USCN-dq0.js} +1 -1
- package/dist/{config-validation-jpeXzoU3.js → config-validation-BGpSeNbh.js} +1 -1
- package/dist/{config-validation-C6u-z9bJ.js → config-validation-CdBJ-tZq.js} +1 -1
- package/dist/{configure-3W9C5LiT.js → configure-CWr61Ph2.js} +1 -1
- package/dist/configure-DhazB2qh.js +1 -0
- package/dist/{configure-BtXQW7ue.js → configure-DlcO1tWx.js} +1 -1
- package/dist/configure-MXheujvX.js +1 -0
- package/dist/{control-service-CJuuqNOE.js → control-service-2PkCt256.js} +1 -1
- package/dist/{control-service-qKfWP7VD.js → control-service-CcsbseZS.js} +1 -1
- package/dist/{control-service-izGyCWQs.js → control-service-qK1oboMo.js} +1 -1
- package/dist/{control-service-BbsswoMy.js → control-service-y3GYvIBg.js} +1 -1
- package/dist/{cron-cli-BrOM4s6N.js → cron-cli-BYu_lA8i.js} +1 -1
- package/dist/{cron-cli-CwtTX6pg.js → cron-cli-D_Og20iB.js} +1 -1
- package/dist/{daemon-cli-DyVsMf8p.js → daemon-cli-BNzthScZ.js} +1 -1
- package/dist/{daemon-cli-DlwOVDbt.js → daemon-cli-Bh3p0hui.js} +1 -1
- package/dist/{daemon-cli-Br0wu9xQ.js → daemon-cli-DxxKiKVN.js} +1 -1
- package/dist/{daemon-cli-DmicpZED.js → daemon-cli-emNxLkIw.js} +1 -1
- package/dist/{daemon-runtime-CtOr1ncS.js → daemon-runtime-9XitJmIL.js} +1 -1
- package/dist/{daemon-runtime-B4UjqdyJ.js → daemon-runtime-Dx800VUt.js} +1 -1
- package/dist/{deliver-BpLm3ktn.js → deliver--6OBF3LL.js} +1 -1
- package/dist/{deliver-9o_SE4ZK.js → deliver-ADpnRGRf.js} +1 -1
- package/dist/{deliver-D2VAVelb.js → deliver-BM6-damm.js} +1 -1
- package/dist/{deliver-BuZu68tp.js → deliver-CsG0cHbZ.js} +1 -1
- package/dist/{deps-CkJiJ6wc.js → deps-Dg_9rfXK.js} +1 -1
- package/dist/{devices-cli-BfXeDnbx.js → devices-cli-B8DXzcRP.js} +1 -1
- package/dist/{devices-cli-B9G6YOsS.js → devices-cli-BZkdWSx-.js} +1 -1
- package/dist/{directory-cli-BRCaiGOn.js → directory-cli-B78pAVI_.js} +1 -1
- package/dist/{directory-cli-D5ciZ5fY.js → directory-cli-CSaRkkL8.js} +1 -1
- package/dist/{dm-policy-shared-CRZpjRv0.js → dm-policy-shared-B9lW-AsK.js} +1 -1
- package/dist/{dm-policy-shared-Dhw9_6mi.js → dm-policy-shared-DYZ_T-az.js} +1 -1
- package/dist/{dns-cli-CgZ7oMcT.js → dns-cli-CLPGOFA1.js} +1 -1
- package/dist/{dns-cli-C4f4Tyij.js → dns-cli-dr5dHzfI.js} +1 -1
- package/dist/{doctor-completion-BSotFS6p.js → doctor-completion-94zme499.js} +1 -1
- package/dist/{doctor-completion-DVxbs-74.js → doctor-completion-CbF34DIH.js} +1 -1
- package/dist/{embedded-helpers-CEsr3aQ0.js → embedded-helpers-C9jpiwlw.js} +1 -1
- package/dist/{embedded-helpers-DK8_apW0.js → embedded-helpers-DdU30lmt.js} +1 -1
- package/dist/entry.js +1 -1
- package/dist/{exec-approvals-cli-YuOu7mVg.js → exec-approvals-cli-CS_uabo7.js} +1 -1
- package/dist/{exec-approvals-cli-BPFi82B0.js → exec-approvals-cli-ktB7M7WE.js} +1 -1
- package/dist/{gateway-cli-D2Bg1Um6.js → gateway-cli-CKcoLVMA.js} +5 -5
- package/dist/{gateway-cli-DFEo8C0z.js → gateway-cli-CuXBDBWe.js} +5 -5
- package/dist/{gateway-rpc-BXR_lVIx.js → gateway-rpc-B02y0PnE.js} +1 -1
- package/dist/{gateway-rpc-ByUcnQ7W.js → gateway-rpc-ff1RVb0_.js} +1 -1
- package/dist/{gemini-auth-CkD5jCPh.js → gemini-auth-DDR12zst.js} +1 -1
- package/dist/health-D0DZmCmh.js +1 -0
- package/dist/{health-yS3NRKvY.js → health-FO8MG5Ur.js} +1 -1
- package/dist/{health-DVo8a9yg.js → health-zrsgFZmR.js} +1 -1
- package/dist/{hooks-cli-B0lVee-j.js → hooks-cli-5Y4hnSX9.js} +1 -1
- package/dist/{hooks-cli-DsVmrQAG.js → hooks-cli-DpHZzRo2.js} +1 -1
- package/dist/index.js +2 -2
- package/dist/{ink-session-BitZ1wcY.js → ink-session-Dt9Q4iH-.js} +2 -2
- package/dist/{ink-session-CyAqXDla.js → ink-session-N8wCBzwk.js} +2 -2
- package/dist/{installs-CWd54ARy.js → installs-B_t2YXgq.js} +1 -1
- package/dist/{installs-C9A8QFiF.js → installs-DFiF4lGy.js} +1 -1
- package/dist/{io-3R_ZyUxB.js → io-BLBq4T2o.js} +1 -1
- package/dist/{io-DSIGyPrT.js → io-CXN4uLS2.js} +1 -1
- package/dist/{io-6jLoKffb.js → io-Ckd4NlvH.js} +1 -1
- package/dist/{io-CohJffHG.js → io-D9hC2aG0.js} +1 -1
- package/dist/{lifecycle-core-BpMvDXy1.js → lifecycle-core-D9Dg5Qps.js} +1 -1
- package/dist/{lifecycle-core-Dwb4gHjZ.js → lifecycle-core-uxjxTzFv.js} +1 -1
- package/dist/login-B3sDAgHb.js +1 -0
- package/dist/{login-C_ZdMOvv.js → login-CwwuaXtb.js} +1 -1
- package/dist/{login-DtDUyFO3.js → login-D1bVUPlv.js} +1 -1
- package/dist/{login-CEnjUo5c.js → login-GLDax56V.js} +1 -1
- package/dist/{login-qr-B9lyIZVD.js → login-qr-CbiUcBLy.js} +1 -1
- package/dist/{login-qr-BCBsxwhT.js → login-qr-Cp0YqK4e.js} +1 -1
- package/dist/{logs-cli-CdM5W3HE.js → logs-cli-Cy11HfSG.js} +1 -1
- package/dist/{logs-cli-jh5Xn3TD.js → logs-cli-nD36c-Y1.js} +1 -1
- package/dist/{manager-CRba8roB.js → manager-BeohB4-8.js} +1 -1
- package/dist/{manager-B3IJ_IKf.js → manager-CTTXDBt3.js} +1 -1
- package/dist/{manager-TGVy_fAb.js → manager-CoQMlcrf.js} +1 -1
- package/dist/{manager-DwywI_5-.js → manager-DSz61dXv.js} +1 -1
- package/dist/{memory-cli-BlayFTAM.js → memory-cli-BpAiRntI.js} +1 -1
- package/dist/{memory-cli-DRz4wtHk.js → memory-cli-CbkWGjRn.js} +1 -1
- package/dist/{memory-cli-PdyTQ84w.js → memory-cli-CrBMLM2P.js} +1 -1
- package/dist/{memory-cli-ivAs7q7v.js → memory-cli-CveeVOWH.js} +1 -1
- package/dist/{model-catalog-CQOdhMUY.js → model-catalog-B29yeBYS.js} +1 -1
- package/dist/{model-catalog-CiiFJX77.js → model-catalog-BeBXvbFm.js} +1 -1
- package/dist/model-catalog-CMKHKuBL.js +1 -0
- package/dist/{model-catalog-C6UrZ0uG.js → model-catalog-DjNiebr7.js} +1 -1
- package/dist/{model-discovery-C9Xm95uL.js → model-discovery-D0i1JpiL.js} +1 -1
- package/dist/{model-picker-swoSwauV.js → model-picker-CGDNPRPc.js} +1 -1
- package/dist/model-picker-CGEF8yhc.js +1 -0
- package/dist/model-picker-DeUNOC78.js +1 -0
- package/dist/{model-picker-BUePD7Zg.js → model-picker-EIhpfOZa.js} +1 -1
- package/dist/{model-selection-9bRFKBI_.js → model-selection-DG9J_VTz.js} +1 -1
- package/dist/{models-BNivsd2o.js → models-BjIzVQYX.js} +2 -2
- package/dist/{models-DQeSIY6M.js → models-JoqOgEF5.js} +1 -1
- package/dist/{models-cli-KokGgWeP.js → models-cli-B2zbchgs.js} +1 -1
- package/dist/{models-cli-BcNxU4P_.js → models-cli-CkFdc8NN.js} +2 -2
- package/dist/{node-cli-DIMh3X2F.js → node-cli-CXnuxiBq.js} +1 -1
- package/dist/{node-cli-EmTU-Gh0.js → node-cli-oVyjVnb7.js} +1 -1
- package/dist/{nodes-cli-BX8TznFK.js → nodes-cli-BBVotxNt.js} +1 -1
- package/dist/{nodes-cli-DyHovdAc.js → nodes-cli-DVMBSUhK.js} +1 -1
- package/dist/{onboard-DfMVh1bM.js → onboard-BItclJp0.js} +1 -1
- package/dist/{onboard-BVmZ4jMw.js → onboard-CqvHIvKj.js} +1 -1
- package/dist/{onboard-auth.credentials-yagR-VMG.js → onboard-auth.credentials-DneFSdYg.js} +1 -1
- package/dist/{onboard-auth.credentials-BuT-etnE.js → onboard-auth.credentials-DpitLlzw.js} +1 -1
- package/dist/onboard-channels-B91m5S3w.js +1 -0
- package/dist/onboard-channels-BOoPtYbF.js +1 -0
- package/dist/{onboard-channels-B6QDFkkK.js → onboard-channels-Dn0u5C-C.js} +1 -1
- package/dist/{onboard-channels-C8FCFn29.js → onboard-channels-vhtccaIV.js} +1 -1
- package/dist/onboard-custom-BN0uzSq_.js +1 -0
- package/dist/{onboard-custom-D1nd8Hlu.js → onboard-custom-BYIza2e7.js} +1 -1
- package/dist/onboard-custom-CCFthqto.js +1 -0
- package/dist/{onboard-custom-C_BI0ZXn.js → onboard-custom-Ckf0xKXY.js} +1 -1
- package/dist/{onboard-helpers-CGlLpagb.js → onboard-helpers-B8I5AVyb.js} +1 -1
- package/dist/{onboard-helpers-CckrS8_K.js → onboard-helpers-Ce_c4Raj.js} +1 -1
- package/dist/{onboard-helpers-Cf5dNq7-.js → onboard-helpers-CiHzTaFX.js} +1 -1
- package/dist/{onboard-helpers-BvIZ4-R5.js → onboard-helpers-DC-nMl-V.js} +1 -1
- package/dist/{onboard-interactive-DYJttZ2w.js → onboard-interactive-Cl2K3EYn.js} +1 -1
- package/dist/{onboard-interactive-zgjmwJz-.js → onboard-interactive-JNux9zfA.js} +1 -1
- package/dist/{onboard-interactive-B3-KBZbZ.js → onboard-interactive-J_ObFzeW.js} +1 -1
- package/dist/{onboard-interactive-Dc_7URYb.js → onboard-interactive-OUNsvlh0.js} +1 -1
- package/dist/{onboard-remote-D5lR2lVm.js → onboard-remote-0-q7MG9t.js} +1 -1
- package/dist/{onboard-remote-BmSyHww1.js → onboard-remote-CgAAEZpq.js} +1 -1
- package/dist/{onboard-remote-CzzQMZ3X.js → onboard-remote-DKXHDdBD.js} +1 -1
- package/dist/{onboard-remote-DcuX8b2g.js → onboard-remote-cB8j9RG-.js} +1 -1
- package/dist/{onboard-skills-ILHIeg1R.js → onboard-skills-47upVdA2.js} +1 -1
- package/dist/{onboard-skills-BPlNN_-T.js → onboard-skills-9Um4TL2x.js} +1 -1
- package/dist/{onboard-skills-DIhjDMom.js → onboard-skills-DhCmvhJY.js} +1 -1
- package/dist/{onboard-skills-CI1OtWsE.js → onboard-skills-mI2kfvdT.js} +1 -1
- package/dist/{onboarding-D4-HDbmU.js → onboarding-BSENgR9C.js} +5 -5
- package/dist/{onboarding-CP9rrz8y.js → onboarding-CIaZLNc1.js} +5 -5
- package/dist/{onboarding.finalize-C2kZi7F0.js → onboarding.finalize-BwOpvoPE.js} +1 -1
- package/dist/{onboarding.finalize-BfWXPgX7.js → onboarding.finalize-yMK-g7Uy.js} +1 -1
- package/dist/{onboarding.gateway-config-Cd7_bXVs.js → onboarding.gateway-config-Kn1O-QFl.js} +1 -1
- package/dist/{onboarding.gateway-config-Bd8HJkso.js → onboarding.gateway-config-huOjFf8D.js} +1 -1
- package/dist/{openai-model-default-Cp3nf21W.js → openai-model-default-CH2-2Hvk.js} +1 -1
- package/dist/{openai-model-default-BMRrqTmH.js → openai-model-default-pfoEzWYJ.js} +1 -1
- package/dist/{outbound-BRInCJD9.js → outbound-BdeHcMAo.js} +1 -1
- package/dist/{outbound-CAtBpFoD.js → outbound-BylJYD7n.js} +1 -1
- package/dist/{outbound-OI-t5zZ0.js → outbound-CAirtWr1.js} +1 -1
- package/dist/{outbound-CnIvOJlU.js → outbound-VNcvF2MG.js} +1 -1
- package/dist/{outbound-send-deps-m6DqOma_.js → outbound-send-deps-B3Lg-uqF.js} +1 -1
- package/dist/{pairing-cli-CEr0yEsc.js → pairing-cli-5RtPvz2i.js} +1 -1
- package/dist/{pairing-cli-Dxfoni-F.js → pairing-cli-C_Mj6Dy4.js} +1 -1
- package/dist/{pairing-labels-3j_iRYOO.js → pairing-labels-BJPrScRl.js} +1 -1
- package/dist/{pairing-labels-BW5jQZlr.js → pairing-labels-oA-nKTaW.js} +1 -1
- package/dist/{pairing-store-QDb6lhIU.js → pairing-store-YRy7EBgI.js} +1 -1
- package/dist/{pairing-store-CbvMJhD3.js → pairing-store-ti3FEkmr.js} +1 -1
- package/dist/{plugin-auto-enable-BV9K9Vhr.js → plugin-auto-enable-Cupr4wbt.js} +1 -1
- package/dist/{plugin-auto-enable-DDry2fA6.js → plugin-auto-enable-D8gKiE3F.js} +1 -1
- package/dist/plugin-registry-BEfyc2f_.js +1 -0
- package/dist/{plugin-registry-C-_GA65s.js → plugin-registry-BoPaef5I.js} +1 -1
- package/dist/{plugin-registry-SAdxNUwm.js → plugin-registry-CxnuHO_n.js} +1 -1
- package/dist/plugin-registry-D0tIqo8L.js +1 -0
- package/dist/plugin-sdk/{accounts-Cy3WCbWg.js → accounts-BwreSNAR.js} +1 -1
- package/dist/plugin-sdk/{active-listener-DVWVNlT9.js → active-listener-DpQ7aGYd.js} +1 -1
- package/dist/plugin-sdk/agent-runtime/src/infra/workflow-telemetry.d.ts +12 -1
- package/dist/plugin-sdk/{agent-scope-DgKN27hJ.js → agent-scope-BQByW0cD.js} +1 -1
- package/dist/plugin-sdk/{api-key-rotation-ftXf7mBZ.js → api-key-rotation-7YdImWrh.js} +1 -1
- package/dist/plugin-sdk/{audio-preflight-CfTmmeS-.js → audio-preflight-EbkaATDO.js} +1 -1
- package/dist/plugin-sdk/{auth-json-BrNBg87n.js → auth-json-DK6qod1_.js} +1 -1
- package/dist/plugin-sdk/{bindings-CH-YLOLC.js → bindings-CDEzl4kl.js} +1 -1
- package/dist/plugin-sdk/{channel-web-B6rg0Rbf.js → channel-web-D2KuONp0.js} +1 -1
- package/dist/plugin-sdk/{chrome-CuXP-hes.js → chrome-SOXFIkUM.js} +1 -1
- package/dist/plugin-sdk/{chunk-C94IAOuf.js → chunk-cW0POl22.js} +1 -1
- package/dist/plugin-sdk/{command-format-B3XMq_73.js → command-format-CAX9XFjI.js} +1 -1
- package/dist/plugin-sdk/{common-n0l_XN-S.js → common-BxEWhN2X.js} +1 -1
- package/dist/plugin-sdk/{config-DsXZsCkJ.js → config-v1EU9Ll8.js} +2 -2
- package/dist/plugin-sdk/{fetch-B-GxSYRO.js → fetch-DH0Y8iyO.js} +1 -1
- package/dist/plugin-sdk/index.js +1 -1
- package/dist/plugin-sdk/{login-_my8QwPP.js → login-d1zBgykF.js} +1 -1
- package/dist/plugin-sdk/{login-qr-BaePtXuG.js → login-qr-B6exvQnN.js} +1 -1
- package/dist/plugin-sdk/{manager-BsC-4ymy.js → manager-BH_bmGds.js} +1 -1
- package/dist/plugin-sdk/{markdown-tables-BUfhHgfs.js → markdown-tables-Epim9b-0.js} +1 -1
- package/dist/plugin-sdk/{message-channel-CuZ2xOAM.js → message-channel-sBPQc_-T.js} +1 -1
- package/dist/plugin-sdk/{model-catalog-yuiXVcmw.js → model-catalog-cXsza5GU.js} +1 -1
- package/dist/plugin-sdk/{model-selection-BtgvnqB5.js → model-selection-K82MAGlL.js} +1 -1
- package/dist/plugin-sdk/{outbound-D_attiyO.js → outbound-Chn_H1O7.js} +1 -1
- package/dist/plugin-sdk/{plugins-BdkC9v5E.js → plugins-CaUOZBVb.js} +1 -1
- package/dist/plugin-sdk/{pw-ai-A7Rathx6.js → pw-ai-BIiJF7ZD.js} +1 -1
- package/dist/plugin-sdk/{qmd-manager-Dxn0jCpE.js → qmd-manager-BRe5fGZw.js} +1 -1
- package/dist/plugin-sdk/{registry-CZHRcH-q.js → registry-DJq2Cvo9.js} +1 -1
- package/dist/plugin-sdk/{render-CuA_WRX5.js → render-BUCRXPIk.js} +1 -1
- package/dist/plugin-sdk/{replies-DmLfO-pg.js → replies-Cz5OD3qN.js} +1 -1
- package/dist/plugin-sdk/{reply-3-ne-N_7.js → reply-D5Uk7pUv.js} +9 -9
- package/dist/plugin-sdk/{reply-prefix-w7kAvH11.js → reply-prefix-CCymsmsP.js} +1 -1
- package/dist/plugin-sdk/{resolve-route-0sbvl4ZN.js → resolve-route-DN1J7Wyc.js} +1 -1
- package/dist/plugin-sdk/{runner-4UfrAQnx.js → runner-CYkuO7Fh.js} +4 -4
- package/dist/plugin-sdk/{session-BB-yfDWx.js → session-D5jHDo78.js} +1 -1
- package/dist/plugin-sdk/{sqlite-JjFgDV-H.js → sqlite-BlMLqMl8.js} +1 -1
- package/dist/plugin-sdk/{subsystem-D0Ril4rt.js → subsystem-COTa5Ly_.js} +1 -1
- package/dist/plugin-sdk/{tool-images-WRTP95FT.js → tool-images-DSpchb4x.js} +1 -1
- package/dist/plugin-sdk/{tool-loop-detection-sC_rhJfb.js → tool-loop-detection-BP6u-mbh.js} +1 -1
- package/dist/plugin-sdk/web-BbganhKi.js +1 -0
- package/dist/plugin-sdk/{whatsapp-actions-ThxQ5niy.js → whatsapp-actions-CZUqxmP1.js} +1 -1
- package/dist/{plugins-BIG8NDB9.js → plugins-Cx29kkDj.js} +1 -1
- package/dist/{plugins-iAq-Gr8l.js → plugins-DJqou2hi.js} +1 -1
- package/dist/{plugins-cli-CpaVUv_r.js → plugins-cli-Bu-A8aGy.js} +1 -1
- package/dist/{plugins-cli-CPkSgvdL.js → plugins-cli-CGFsQDVW.js} +1 -1
- package/dist/{program-context-BCwL3wlM.js → program-context-ClBa4lUj.js} +1 -1
- package/dist/{program-2w7Ue902.js → program-vVCzU0cH.js} +2 -2
- package/dist/{prompt-select-styled-hB_nLOn1.js → prompt-select-styled-BJPGccTJ.js} +1 -1
- package/dist/{prompt-select-styled-Dd5swW2b.js → prompt-select-styled-BK74z6FF.js} +1 -1
- package/dist/{provider-auth-helpers-BpTnp2Yr.js → provider-auth-helpers-B84m5VMc.js} +1 -1
- package/dist/{provider-auth-helpers-CJTG_tVx.js → provider-auth-helpers-hNwpK_hl.js} +1 -1
- package/dist/{provider-dispatcher-TWwBT2aH.js → provider-dispatcher-BjR5DE3O.js} +1 -1
- package/dist/provider-dispatcher-DgOeVjcL.js +1 -0
- package/dist/{provider-usage-BdrU4cIE.js → provider-usage-B-wPVN_j.js} +1 -1
- package/dist/{provider-usage-Bn4ZrnU7.js → provider-usage-B8lFHp0K.js} +1 -1
- package/dist/{push-apns-C4sJnHbO.js → push-apns-BTPPvY81.js} +1 -1
- package/dist/{push-apns-CiD3rrVv.js → push-apns-CscYUS0D.js} +1 -1
- package/dist/{pw-ai-DSEj1QrV.js → pw-ai-CLS_VZ8p.js} +1 -1
- package/dist/{pw-ai-dNZY-qBs.js → pw-ai-D5og_rIf.js} +1 -1
- package/dist/{qr-cli-qr-SFLZW.js → qr-cli-CAquM1Zk.js} +1 -1
- package/dist/{qr-cli-B45dCV0o.js → qr-cli-GsR8n1cm.js} +1 -1
- package/dist/{qr-cli-CMlAIzrD.js → qr-cli-kAKgaL-T.js} +1 -1
- package/dist/{qr-cli-CySNSEFj.js → qr-cli-uyxNf-cQ.js} +1 -1
- package/dist/{register.agent-BA6LIJSb.js → register.agent-BwTCfyeJ.js} +1 -1
- package/dist/{register.agent-D2uCH8jZ.js → register.agent-Dhdo3_7k.js} +1 -1
- package/dist/register.configure-B0m0G3ot.js +1 -0
- package/dist/register.configure-D3cbjmTz.js +1 -0
- package/dist/{register.maintenance-BELfCO_C.js → register.maintenance-C6ocMld2.js} +1 -1
- package/dist/{register.maintenance-DukWFS_D.js → register.maintenance-CbE2zSyc.js} +1 -1
- package/dist/{register.message-DiZRRAE5.js → register.message-Jn4u533_.js} +1 -1
- package/dist/{register.message-8iGDhO8h.js → register.message-Tu1hlM0m.js} +1 -1
- package/dist/{register.onboard-B9DMNfHE.js → register.onboard-B34211N6.js} +1 -1
- package/dist/{register.onboard-Dt7rzAq-.js → register.onboard-S1d2WAE4.js} +1 -1
- package/dist/{register.setup-CSF-2ImP.js → register.setup-CJPyAwCQ.js} +1 -1
- package/dist/{register.setup-BRRVPrx7.js → register.setup-Sg8f3nsH.js} +1 -1
- package/dist/{register.status-health-sessions-D6wdwPwV.js → register.status-health-sessions-BlgVxoZ4.js} +1 -1
- package/dist/{register.status-health-sessions-ZSufYw5j.js → register.status-health-sessions-DwADQJ74.js} +1 -1
- package/dist/{register.subclis-4eDV9jKH.js → register.subclis-C9V_M-Lk.js} +1 -1
- package/dist/{register.subclis-Cr9DoYcv.js → register.subclis-pWn9XObB.js} +1 -1
- package/dist/{replies-DbkT_5BV.js → replies-BOGMDhSN.js} +1 -1
- package/dist/{replies-CzV-RFUG.js → replies-BXbV02ik.js} +1 -1
- package/dist/{replies-DIBQzxGp.js → replies-CUv671JF.js} +1 -1
- package/dist/{replies-Bd2RPZwQ.js → replies-DokbEfJD.js} +1 -1
- package/dist/{reply-Cd3vVnD7.js → reply-GY1C8tcv.js} +10 -10
- package/dist/{routes-BzfLvF8W.js → routes-DZntyPY6.js} +1 -1
- package/dist/{routes-lclJHOYY.js → routes-_iZdG1Fo.js} +1 -1
- package/dist/{rpc-BLqXRn5R.js → rpc-CbUnwStf.js} +1 -1
- package/dist/{rpc-DcQNGQlj.js → rpc-Cwm4gchc.js} +1 -1
- package/dist/{run-main-DLcDEJgv.js → run-main-DQMbgbcF.js} +1 -1
- package/dist/{runner-DwWmciCt.js → runner-Cu9NJouV.js} +1 -1
- package/dist/{runner-SxCr9kXD.js → runner-eTTUbLAK.js} +1 -1
- package/dist/{sandbox-BZibn6PX.js → sandbox-C4AKi2EX.js} +1 -1
- package/dist/{sandbox-z9t_PRf9.js → sandbox-DvKMuAXL.js} +1 -1
- package/dist/{sandbox-cli-BtGs0dBR.js → sandbox-cli-C0LhzYq_.js} +1 -1
- package/dist/{sandbox-cli-B8FpLgyY.js → sandbox-cli-De0iaoHB.js} +1 -1
- package/dist/{security-cli-D8Q8I7fn.js → security-cli-BvEfiO8m.js} +1 -1
- package/dist/{security-cli-IIMR7Pb4.js → security-cli-BzsQ0XQh.js} +1 -1
- package/dist/{send-DnMzjS7L.js → send-2dRKMWtl.js} +1 -1
- package/dist/{send-DerUBvXW.js → send-Aw8wK3vK.js} +1 -1
- package/dist/{send-BvroeIQ6.js → send-B7H8Ae5j.js} +1 -1
- package/dist/{send-4d9NswaD.js → send-BP5osGBo.js} +1 -1
- package/dist/{send-BU_-BGmf.js → send-BVal50Bi.js} +1 -1
- package/dist/{send-CxG2suVM.js → send-Bbo7TXLx.js} +1 -1
- package/dist/{send-CBBziNqM.js → send-BxoVLIy1.js} +1 -1
- package/dist/{send-dDpSBSBo.js → send-COKUbcqs.js} +1 -1
- package/dist/{send--12DIueA.js → send-CTw3PqN4.js} +1 -1
- package/dist/{send-UFtylOiq.js → send-CYGOPcKq.js} +1 -1
- package/dist/{send-DyF1Xy9K.js → send-ChGpVO3O.js} +1 -1
- package/dist/{send-Q-uTkSFE.js → send-Cqea2UFo.js} +1 -1
- package/dist/{send-j15662lv.js → send-CrFWgJKx.js} +1 -1
- package/dist/{send-gDb60Hk-.js → send-CwK8QBR3.js} +1 -1
- package/dist/{send-CceNWtYE.js → send-DqR7Rxzm.js} +1 -1
- package/dist/{send-CJHXQvVl.js → send-DxwfUIN-.js} +1 -1
- package/dist/{send-ByCVQQVz.js → send-KgN1P41U.js} +1 -1
- package/dist/{send-B1rJLLpr.js → send-bNp87SIq.js} +1 -1
- package/dist/{send-B_1BtyfA.js → send-kkm_zrHQ.js} +1 -1
- package/dist/{send-BJDzwYJN.js → send-l3ge4wkC.js} +1 -1
- package/dist/{server-context-DJZT7Upf.js → server-context-CQ2v4BAx.js} +1 -1
- package/dist/{server-context-owOmmyUM.js → server-context-CttALzrW.js} +1 -1
- package/dist/{server-node-events-54d8Rmjl.js → server-node-events-CIMO6Vae.js} +1 -1
- package/dist/{server-node-events-CSFVqgxX.js → server-node-events-iCF2ngcN.js} +1 -1
- package/dist/{session-BzQdcCqN.js → session-BJHsjD3z.js} +1 -1
- package/dist/{session-4FpEJvkE.js → session-C_b1ttHJ.js} +1 -1
- package/dist/{session-dirs-OxQuIvJW.js → session-dirs-Bvbgw0GC.js} +1 -1
- package/dist/{session-dirs-D_ARkyw0.js → session-dirs-DHaoq7zc.js} +1 -1
- package/dist/{session-utils-GMvum00v.js → session-utils-Dxou8SbO.js} +1 -1
- package/dist/{sessions-Bl1wwotX.js → sessions-BA8Se_bT.js} +1 -1
- package/dist/{sessions-CdanN_ZI.js → sessions-BuZVmOWt.js} +1 -1
- package/dist/{sessions-B5dwRhUC.js → sessions-DvbW0FNJ.js} +1 -1
- package/dist/{sessions-B1t7qeEn.js → sessions-DvqsIg0M.js} +1 -1
- package/dist/{shared-xj-xaKFi.js → shared-BBOiNdjf.js} +1 -1
- package/dist/{shared-BPN3qd7G.js → shared-C2orjbTD.js} +1 -1
- package/dist/{skill-scanner-U3AJgjqc.js → skill-scanner-BEvov9QH.js} +1 -1
- package/dist/{skill-scanner-DEmbPsRh.js → skill-scanner-OTLeRZ_p.js} +1 -1
- package/dist/{skills-cli-CIdnXa3B.js → skills-cli-C1BOgB3y.js} +1 -1
- package/dist/{skills-cli-BXbGr7vl.js → skills-cli-CFT2Aq5R.js} +1 -1
- package/dist/{skills-install-Btw_GHbI.js → skills-install-LlKntDHa.js} +1 -1
- package/dist/{skills-install-DMHQRpIl.js → skills-install-tx5Mahav.js} +1 -1
- package/dist/{status-DXaDS_0w.js → status-Bh8V7kjv.js} +1 -1
- package/dist/{status-BxeKmkVr.js → status-BtBHmhQh.js} +1 -1
- package/dist/{status-BkcmeZg6.js → status-CpwD4y9B.js} +1 -1
- package/dist/status-CqaTmyih.js +1 -0
- package/dist/{status-DouJcFzf.js → status-yXz8PUbL.js} +1 -1
- package/dist/{status.update-C9iy31xr.js → status.update-CdgsLBPg.js} +1 -1
- package/dist/{status.update-KYyRSDZY.js → status.update-hzMro-BT.js} +1 -1
- package/dist/{subagent-registry-Dr20nzwk.js → subagent-registry-CaRUNwCj.js} +1 -1
- package/dist/{subagent-registry-CyGxu3kP.js → subagent-registry-DDEN4oJi.js} +10 -10
- package/dist/{subagent-registry-BiXkIDeh.js → subagent-registry-DYYfeIc3.js} +1 -1
- package/dist/{system-cli-b4YgXPHv.js → system-cli-4aii1JYf.js} +1 -1
- package/dist/{system-cli-C7YzJeP4.js → system-cli-CfkDD3FV.js} +1 -1
- package/dist/{tui-DylWbrDx.js → tui-DnVRxfI8.js} +2 -2
- package/dist/{tui-BwWMByVp.js → tui-JfWoLGIV.js} +2 -2
- package/dist/{tui-cli-C_TTgabr.js → tui-cli-CGjg2Eb5.js} +1 -1
- package/dist/{tui-cli-Bh1V8-w9.js → tui-cli-cd7Efw5u.js} +1 -1
- package/dist/{tui-setup-check-DJZCJokQ.js → tui-setup-check-BEHm9wwo.js} +1 -1
- package/dist/{tui-setup-check-BABAyl-e.js → tui-setup-check-DK8vdhLI.js} +1 -1
- package/dist/{tui-stream-assembler-ign_cPkv.js → tui-stream-assembler-8ud9oyMK.js} +1 -1
- package/dist/{tui-stream-assembler-q9GANTDr.js → tui-stream-assembler-Br15rhRH.js} +1 -1
- package/dist/{update-BUzcmoDf.js → update-B5yKFeGO.js} +1 -1
- package/dist/{update-D6U-V8Au.js → update-DodoQDCk.js} +1 -1
- package/dist/{update-cli-DUrUIrYQ.js → update-cli-CfJJcSUS.js} +1 -1
- package/dist/{update-cli-CA3LuuJ7.js → update-cli-x8Ocbf-0.js} +1 -1
- package/dist/{usage-cli-CfEg1_NZ.js → usage-cli-CN7L1YRG.js} +1 -1
- package/dist/{usage-cli-CpbYMXxS.js → usage-cli-CQmokGkG.js} +1 -1
- package/dist/{web-D-NSyF6b.js → web-BXLk9UT2.js} +1 -1
- package/dist/web-Btgs8oWv.js +1 -0
- package/dist/{webhooks-cli-B_f61rq7.js → webhooks-cli-DIo8p3lk.js} +1 -1
- package/dist/{webhooks-cli-Bi0t3w6P.js → webhooks-cli-DhxEtiFt.js} +1 -1
- package/dist/{whatsapp-actions-JbF2MrTV.js → whatsapp-actions-B7r9AyZN.js} +1 -1
- package/dist/{whatsapp-actions-BkCMhD9X.js → whatsapp-actions-DX2QU6Gs.js} +1 -1
- package/dist/{with-timeout-T07SJo4N.js → with-timeout-B_p5pWDv.js} +1 -1
- package/dist/{with-timeout-Bwq-GyUQ.js → with-timeout-GDLpcjW7.js} +1 -1
- package/dist/workflow-telemetry-BMTg5lPd.js +1 -0
- package/dist/workflow-telemetry-Bg8MVUr_.js +2 -0
- package/dist/workflow-telemetry-Do1UsYwM.js +1 -0
- package/dist/workflow-telemetry-DqBPhVL4.js +2 -0
- package/package.json +1 -1
- package/dist/agents-DsZ5vLKE.js +0 -1
- package/dist/auth-choice-Btd2Rxxd.js +0 -1
- package/dist/auth-choice-CVV9wRFN.js +0 -1
- package/dist/auth-choice.apply-BOK9XRCQ.js +0 -1
- package/dist/auth-choice.apply-Cv-BiV5Q.js +0 -1
- package/dist/auth-choice.apply.transformers-CXywS3GZ.js +0 -1
- package/dist/builderforce-onboarding-Dq6VUSKZ.js +0 -24
- package/dist/builderforce-onboarding-DuUfZ6oL.js +0 -24
- package/dist/configure-CWBBFk3F.js +0 -1
- package/dist/configure-fHVOAucW.js +0 -1
- package/dist/health-GLcAfqDz.js +0 -1
- package/dist/login-CPyEf5h6.js +0 -1
- package/dist/model-catalog-J7R-tJDu.js +0 -1
- package/dist/model-picker-D2bcWrtu.js +0 -1
- package/dist/model-picker-DO1HtEEm.js +0 -1
- package/dist/onboard-channels-CmqKsAoW.js +0 -1
- package/dist/onboard-channels-Db0P4iWl.js +0 -1
- package/dist/onboard-custom-BABqIYa4.js +0 -1
- package/dist/onboard-custom-VpW3UC8u.js +0 -1
- package/dist/plugin-registry-B-UOeWqM.js +0 -1
- package/dist/plugin-registry-BjMr3yXM.js +0 -1
- package/dist/plugin-sdk/web-CThgoHQp.js +0 -1
- package/dist/provider-dispatcher-C4nHaNqn.js +0 -1
- package/dist/register.configure-DAL38e7r.js +0 -1
- package/dist/register.configure-DZG7-WVi.js +0 -1
- package/dist/status-BTYqHVha.js +0 -1
- package/dist/web-P6QsgmSD.js +0 -1
- package/dist/workflow-telemetry-B8Im0mPk.js +0 -1
- package/dist/workflow-telemetry-DLEnm5TI.js +0 -2
- package/dist/workflow-telemetry-Dc_oseV7.js +0 -2
- package/dist/workflow-telemetry-Dkm3mofI.js +0 -1
- /package/dist/{devtools-CI7JyCXv.js → devtools-Cg4F-l9O.js} +0 -0
- /package/dist/{devtools-eMFaIsAT.js → devtools-Dl2DACSO.js} +0 -0
- /package/dist/{github-copilot-token-D3gHtNUu.js → github-copilot-token-BlyiXyTy.js} +0 -0
- /package/dist/{github-copilot-token-DHP2kAiN.js → github-copilot-token-D5sB2AUI.js} +0 -0
- /package/dist/{onboard-hooks-Cenav0eW.js → onboard-hooks-BaOSgxs9.js} +0 -0
- /package/dist/{onboard-hooks-Ce20rwpW.js → onboard-hooks-fO5eeDe_.js} +0 -0
- /package/dist/{qmd-manager-DVd_aWEV.js → qmd-manager-BgplOjHN.js} +0 -0
- /package/dist/{qmd-manager-keHvLmvP.js → qmd-manager-COUi_Fqb.js} +0 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{d as resolveIsNixMode,g as resolveStateDir}from"./paths-BHg-VHB4.js";import"./registry-Cv7CoWAs.js";import{L as colorize,z as theme}from"./utils-BP60e80M.js";import{p as defaultRuntime}from"./subsystem-C4b1Von0.js";import"./boolean-ssGoaBPk.js";import"./env-BoE8QSib.js";import"./auth-profiles-C1VbcUOm.js";import{t as formatCliCommand}from"./command-format-DTMaGKs7.js";import"./src-DvWaTze9.js";import"./logger-wuOr7HKl.js";import"./session-key-CksCYipj.js";import"./builderforce-root-DY1qbWNX.js";import"./exec-COgsU9ql.js";import{r as resolveAgentConfig}from"./agent-scope-CufEmNj_.js";import"./env-file-DeS6x2OL.js";import"./src-HrLX5bhG.js";import{U as VERSION,r as loadConfig}from"./io-CohJffHG.js";import"./manifest-registry-009gLJ4l.js";import"./config-toczWD3q.js";import{Bt as loadOrCreateDeviceIdentity,t as GatewayClient}from"./client-CGgp3zkQ.js";import{h as GATEWAY_CLIENT_NAMES,m as GATEWAY_CLIENT_MODES}from"./message-channel-z5YRpR2d.js";import{n as createBrowserRouteDispatcher,r as getMachineDisplayName,t as withTimeout}from"./with-timeout-T07SJo4N.js";import{c as detectMime}from"./image-ops-CotJhwRR.js";import"./redact-CgO7wehS.js";import"./errors-tAt19c1E.js";import"./chrome-BnEbJV3D.js";import"./tailscale-DV-yOmYe.js";import"./auth-ChecwOXS.js";import{i as resolveBrowserConfig}from"./server-context-owOmmyUM.js";import"./routes-lclJHOYY.js";import"./paths-BnOjueoX.js";import"./ssrf-DJXLYZ0d.js";import"./store-DHD2IEgd.js";import"./ports-DTku9NSx.js";import"./trash-C3zmJ_O7.js";import{g as resolveNodeWindowsTaskName,h as resolveNodeSystemdServiceName,m as resolveNodeLaunchAgentLabel,s as formatNodeServiceDescription}from"./constants-D2th5NXV.js";import{_ as analyzeArgvCommand,a as mergeExecApprovalsSocketDefaults,b as requestJsonlSocket,c as readExecApprovalsSnapshot,d as resolveExecApprovals,g as resolveSafeBins,h as evaluateShellAllowlist,l as recordAllowlistUse,m as evaluateExecAllowlist,n as addAllowlistEntry,p as saveExecApprovals,r as ensureExecApprovals,s as normalizeExecApprovals,u as requiresExecApproval}from"./exec-approvals-D7ZPAZpt.js";import{r as startBrowserControlServiceFromConfig,t as createBrowserControlContext}from"./control-service-CJuuqNOE.js";import{t as formatDocsLink}from"./links-BKzP7VVP.js";import{t as formatHelpExamples}from"./help-format-CfFf-w62.js";import{t as ensureBuilderForceAgentsCliOnPath}from"./path-env-Gmzpaha-.js";import{c as buildNodeServiceEnvironment,g as resolveNodeProgramArguments,o as resolveGatewayDevMode,p as resolvePreferredNodePath,r as isGatewayDaemonRuntime,s as emitNodeRuntimeWarning,t as DEFAULT_GATEWAY_DAEMON_RUNTIME}from"./daemon-runtime-B4UjqdyJ.js";import"./runtime-guard-Bi8k55v9.js";import"./systemd-DdVd5Yet.js";import{s as resolveGatewayLogPaths}from"./service-EKJG69M3.js";import{S as installDaemonServiceAndEmit,_ as resolveRuntimeStatusColor,b as buildDaemonServiceSnapshot,i as runServiceUninstall,r as runServiceStop,t as runServiceRestart,u as createCliStatusTextStyles,x as createDaemonActionContext,y as formatRuntimeStatus}from"./lifecycle-core-BpMvDXy1.js";import"./diagnostics-DamNPi4e.js";import{t as parsePort}from"./parse-port-FgIKmqqb.js";import{t as resolveNodeService}from"./node-service-77UF0ACm.js";import{n as validateSystemRunCommandConsistency}from"./system-run-command-rlCfXRWt.js";import{spawn}from"node:child_process";import path from"node:path";import fs from"node:fs";import crypto from"node:crypto";import fs$1 from"node:fs/promises";function resolveNodeHostConfigPath(){return path.join(resolveStateDir(),`node.json`)}function normalizeConfig(config){let base={version:1,nodeId:``,token:config?.token,displayName:config?.displayName,gateway:config?.gateway};return config?.version===1&&typeof config.nodeId==`string`&&(base.nodeId=config.nodeId.trim()),base.nodeId||=crypto.randomUUID(),base}async function loadNodeHostConfig(){let filePath=resolveNodeHostConfigPath();try{let raw=await fs$1.readFile(filePath,`utf8`);return normalizeConfig(JSON.parse(raw))}catch{return null}}async function saveNodeHostConfig(config){let filePath=resolveNodeHostConfigPath();await fs$1.mkdir(path.dirname(filePath),{recursive:!0});let payload=JSON.stringify(config,null,2);await fs$1.writeFile(filePath,`${payload}\n`,{mode:384});try{await fs$1.chmod(filePath,384)}catch{}}async function ensureNodeHostConfig(){let normalized=normalizeConfig(await loadNodeHostConfig());return await saveNodeHostConfig(normalized),normalized}async function requestExecHostViaSocket(params){let{socketPath,token,request}=params;if(!socketPath||!token)return null;let timeoutMs=params.timeoutMs??2e4,requestJson=JSON.stringify(request),nonce=crypto.randomBytes(16).toString(`hex`),ts=Date.now(),hmac=crypto.createHmac(`sha256`,token).update(`${nonce}:${ts}:${requestJson}`).digest(`hex`);return await requestJsonlSocket({socketPath,payload:JSON.stringify({type:`exec`,id:crypto.randomUUID(),nonce,ts,hmac,requestJson}),timeoutMs,accept:value=>{let msg=value;if(msg?.type===`exec-res`)return msg.ok===!0&&msg.payload?{ok:!0,payload:msg.payload}:msg.ok===!1&&msg.error?{ok:!1,error:msg.error}:null}})}const BROWSER_PROXY_MAX_FILE_BYTES=10*1024*1024;function normalizeProfileAllowlist(raw){return Array.isArray(raw)?raw.map(entry=>entry.trim()).filter(Boolean):[]}function resolveBrowserProxyConfig(){let proxy=loadConfig().nodeHost?.browserProxy,allowProfiles=normalizeProfileAllowlist(proxy?.allowProfiles);return{enabled:proxy?.enabled!==!1,allowProfiles}}let browserControlReady=null;async function ensureBrowserControlService(){return browserControlReady||(browserControlReady=(async()=>{let cfg=loadConfig();if(!resolveBrowserConfig(cfg.browser,cfg).enabled||!await startBrowserControlServiceFromConfig())throw Error(`browser control disabled`)})(),browserControlReady)}function isProfileAllowed(params){let{allowProfiles,profile}=params;return allowProfiles.length?profile?allowProfiles.includes(profile.trim()):!1:!0}function collectBrowserProxyPaths(payload){let paths=new Set,obj=typeof payload==`object`&&payload?payload:null;if(!obj)return[];typeof obj.path==`string`&&obj.path.trim()&&paths.add(obj.path.trim()),typeof obj.imagePath==`string`&&obj.imagePath.trim()&&paths.add(obj.imagePath.trim());let download=obj.download;if(download&&typeof download==`object`){let dlPath=download.path;typeof dlPath==`string`&&dlPath.trim()&&paths.add(dlPath.trim())}return[...paths]}async function readBrowserProxyFile(filePath){let stat=await fs$1.stat(filePath).catch(()=>null);if(!stat||!stat.isFile())return null;if(stat.size>BROWSER_PROXY_MAX_FILE_BYTES)throw Error(`browser proxy file exceeds ${Math.round(BROWSER_PROXY_MAX_FILE_BYTES/(1024*1024))}MB`);let buffer=await fs$1.readFile(filePath),mimeType=await detectMime({buffer,filePath});return{path:filePath,base64:buffer.toString(`base64`),mimeType}}function decodeParams$1(raw){if(!raw)throw Error(`INVALID_REQUEST: paramsJSON required`);return JSON.parse(raw)}async function runBrowserProxyCommand(paramsJSON){let params=decodeParams$1(paramsJSON),pathValue=typeof params.path==`string`?params.path.trim():``;if(!pathValue)throw Error(`INVALID_REQUEST: path required`);let proxyConfig=resolveBrowserProxyConfig();if(!proxyConfig.enabled)throw Error(`UNAVAILABLE: node browser proxy disabled`);await ensureBrowserControlService();let cfg=loadConfig(),resolved=resolveBrowserConfig(cfg.browser,cfg),requestedProfile=typeof params.profile==`string`?params.profile.trim():``,allowedProfiles=proxyConfig.allowProfiles;if(allowedProfiles.length>0){if(pathValue!==`/profiles`){if(!isProfileAllowed({allowProfiles:allowedProfiles,profile:requestedProfile||resolved.defaultProfile}))throw Error(`INVALID_REQUEST: browser profile not allowed`)}else if(requestedProfile&&!isProfileAllowed({allowProfiles:allowedProfiles,profile:requestedProfile}))throw Error(`INVALID_REQUEST: browser profile not allowed`)}let method=typeof params.method==`string`?params.method.toUpperCase():`GET`,path=pathValue.startsWith(`/`)?pathValue:`/${pathValue}`,body=params.body,query={};requestedProfile&&(query.profile=requestedProfile);let rawQuery=params.query??{};for(let[key,value]of Object.entries(rawQuery))value!=null&&(query[key]=typeof value==`string`?value:String(value));let dispatcher=createBrowserRouteDispatcher(createBrowserControlContext()),response=await withTimeout(signal=>dispatcher.dispatch({method:method===`DELETE`?`DELETE`:method===`POST`?`POST`:`GET`,path,query,body,signal}),params.timeoutMs,`browser proxy request`);if(response.status>=400){let message=response.body&&typeof response.body==`object`&&`error`in response.body?String(response.body.error):`HTTP ${response.status}`;throw Error(message)}let result=response.body;if(allowedProfiles.length>0&&path===`/profiles`){let obj=typeof result==`object`&&result?result:{};obj.profiles=(Array.isArray(obj.profiles)?obj.profiles:[]).filter(entry=>{if(!entry||typeof entry!=`object`)return!1;let name=entry.name;return typeof name==`string`&&allowedProfiles.includes(name)})}let files,paths=collectBrowserProxyPaths(result);if(paths.length>0){let loaded=await Promise.all(paths.map(async p=>{try{let file=await readBrowserProxyFile(p);if(!file)throw Error(`file not found`);return file}catch(err){throw Error(`browser proxy file read failed for ${p}: ${String(err)}`,{cause:err})}}));loaded.length>0&&(files=loaded)}let payload=files?{result,files}:{result};return JSON.stringify(payload)}const OUTPUT_CAP=2e5,execHostEnforced=process.env.BUILDERFORCE_AGENTS_NODE_EXEC_HOST?.trim().toLowerCase()===`app`,execHostFallbackAllowed=process.env.BUILDERFORCE_AGENTS_NODE_EXEC_FALLBACK?.trim().toLowerCase()!==`0`,blockedEnvKeys=new Set([`NODE_OPTIONS`,`PYTHONHOME`,`PYTHONPATH`,`PERL5LIB`,`PERL5OPT`,`RUBYOPT`]),blockedEnvPrefixes=[`DYLD_`,`LD_`];function resolveExecSecurity(value){return value===`deny`||value===`allowlist`||value===`full`?value:`allowlist`}function isCmdExeInvocation(argv){let token=argv[0]?.trim();if(!token)return!1;let base=path.win32.basename(token).toLowerCase();return base===`cmd.exe`||base===`cmd`}function resolveExecAsk(value){return value===`off`||value===`on-miss`||value===`always`?value:`on-miss`}function sanitizeEnv(overrides){if(!overrides)return;let merged={...process.env};for(let[rawKey,value]of Object.entries(overrides)){let key=rawKey.trim();if(!key)continue;let upper=key.toUpperCase();upper!==`PATH`&&(blockedEnvKeys.has(upper)||blockedEnvPrefixes.some(prefix=>upper.startsWith(prefix))||(merged[key]=value))}return merged}function truncateOutput(raw,maxChars){return raw.length<=maxChars?{text:raw,truncated:!1}:{text:`... (truncated) ${raw.slice(raw.length-maxChars)}`,truncated:!0}}function redactExecApprovals(file){let socketPath=file.socket?.path?.trim();return{...file,socket:socketPath?{path:socketPath}:void 0}}function requireExecApprovalsBaseHash(params,snapshot){if(!snapshot.exists)return;if(!snapshot.hash)throw Error(`INVALID_REQUEST: exec approvals base hash unavailable; reload and retry`);let baseHash=typeof params.baseHash==`string`?params.baseHash.trim():``;if(!baseHash)throw Error(`INVALID_REQUEST: exec approvals base hash required; reload and retry`);if(baseHash!==snapshot.hash)throw Error(`INVALID_REQUEST: exec approvals changed; reload and retry`)}async function runCommand(argv,cwd,env,timeoutMs){return await new Promise(resolve=>{let stdout=``,stderr=``,outputLen=0,truncated=!1,timedOut=!1,settled=!1,child=spawn(argv[0],argv.slice(1),{cwd,env,stdio:[`ignore`,`pipe`,`pipe`],windowsHide:!0}),onChunk=(chunk,target)=>{if(outputLen>=OUTPUT_CAP){truncated=!0;return}let remaining=OUTPUT_CAP-outputLen,slice=chunk.length>remaining?chunk.subarray(0,remaining):chunk,str=slice.toString(`utf8`);outputLen+=slice.length,target===`stdout`?stdout+=str:stderr+=str,chunk.length>remaining&&(truncated=!0)};child.stdout?.on(`data`,chunk=>onChunk(chunk,`stdout`)),child.stderr?.on(`data`,chunk=>onChunk(chunk,`stderr`));let timer;timeoutMs&&timeoutMs>0&&(timer=setTimeout(()=>{timedOut=!0;try{child.kill(`SIGKILL`)}catch{}},timeoutMs));let finalize=(exitCode,error)=>{settled||(settled=!0,timer&&clearTimeout(timer),resolve({exitCode,timedOut,success:exitCode===0&&!timedOut&&!error,stdout,stderr,error:error??null,truncated}))};child.on(`error`,err=>{finalize(void 0,err.message)}),child.on(`exit`,code=>{finalize(code===null?void 0:code,null)})})}function resolveEnvPath(env){return(env?.PATH??env?.Path??process.env.PATH??process.env.Path??`/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin`).split(path.delimiter).filter(Boolean)}function resolveExecutable(bin,env){if(bin.includes(`/`)||bin.includes(`\\`))return null;let extensions=process.platform===`win32`?(process.env.PATHEXT??process.env.PathExt??`.EXE;.CMD;.BAT;.COM`).split(`;`).map(ext=>ext.toLowerCase()):[``];for(let dir of resolveEnvPath(env))for(let ext of extensions){let candidate=path.join(dir,bin+ext);if(fs.existsSync(candidate))return candidate}return null}async function handleSystemWhich(params,env){let bins=params.bins.map(bin=>bin.trim()).filter(Boolean),found={};for(let bin of bins){let path=resolveExecutable(bin,env);path&&(found[bin]=path)}return{bins:found}}function buildExecEventPayload(payload){if(!payload.output)return payload;let trimmed=payload.output.trim();if(!trimmed)return payload;let{text}=truncateOutput(trimmed,2e4);return{...payload,output:text}}async function sendExecFinishedEvent(params){let combined=[params.result.stdout,params.result.stderr,params.result.error].filter(Boolean).join(`
|
|
1
|
+
import{d as resolveIsNixMode,g as resolveStateDir}from"./paths-BHg-VHB4.js";import"./registry-Cv7CoWAs.js";import{L as colorize,z as theme}from"./utils-BP60e80M.js";import{p as defaultRuntime}from"./subsystem-C4b1Von0.js";import"./boolean-ssGoaBPk.js";import"./env-BoE8QSib.js";import"./auth-profiles-pt7Tr4HA.js";import{t as formatCliCommand}from"./command-format-DTMaGKs7.js";import"./src-DvWaTze9.js";import"./logger-wuOr7HKl.js";import"./session-key-CksCYipj.js";import"./builderforce-root-DY1qbWNX.js";import"./exec-COgsU9ql.js";import{r as resolveAgentConfig}from"./agent-scope-CufEmNj_.js";import"./env-file-DeS6x2OL.js";import"./src-HrLX5bhG.js";import{U as VERSION,r as loadConfig}from"./io-D9hC2aG0.js";import"./manifest-registry-009gLJ4l.js";import"./config-BpChMIJ6.js";import{Bt as loadOrCreateDeviceIdentity,t as GatewayClient}from"./client-CGgp3zkQ.js";import{h as GATEWAY_CLIENT_NAMES,m as GATEWAY_CLIENT_MODES}from"./message-channel-z5YRpR2d.js";import{n as createBrowserRouteDispatcher,r as getMachineDisplayName,t as withTimeout}from"./with-timeout-B_p5pWDv.js";import{c as detectMime}from"./image-ops-CotJhwRR.js";import"./redact-CgO7wehS.js";import"./errors-tAt19c1E.js";import"./chrome-CFmcixaE.js";import"./tailscale-DV-yOmYe.js";import"./auth-ChecwOXS.js";import{i as resolveBrowserConfig}from"./server-context-CttALzrW.js";import"./routes-_iZdG1Fo.js";import"./paths-BnOjueoX.js";import"./ssrf-DJXLYZ0d.js";import"./store-DHD2IEgd.js";import"./ports-DTku9NSx.js";import"./trash-C3zmJ_O7.js";import{g as resolveNodeWindowsTaskName,h as resolveNodeSystemdServiceName,m as resolveNodeLaunchAgentLabel,s as formatNodeServiceDescription}from"./constants-D2th5NXV.js";import{_ as analyzeArgvCommand,a as mergeExecApprovalsSocketDefaults,b as requestJsonlSocket,c as readExecApprovalsSnapshot,d as resolveExecApprovals,g as resolveSafeBins,h as evaluateShellAllowlist,l as recordAllowlistUse,m as evaluateExecAllowlist,n as addAllowlistEntry,p as saveExecApprovals,r as ensureExecApprovals,s as normalizeExecApprovals,u as requiresExecApproval}from"./exec-approvals-D7ZPAZpt.js";import{r as startBrowserControlServiceFromConfig,t as createBrowserControlContext}from"./control-service-2PkCt256.js";import{t as formatDocsLink}from"./links-BKzP7VVP.js";import{t as formatHelpExamples}from"./help-format-CfFf-w62.js";import{t as ensureBuilderForceAgentsCliOnPath}from"./path-env-Gmzpaha-.js";import{c as buildNodeServiceEnvironment,g as resolveNodeProgramArguments,o as resolveGatewayDevMode,p as resolvePreferredNodePath,r as isGatewayDaemonRuntime,s as emitNodeRuntimeWarning,t as DEFAULT_GATEWAY_DAEMON_RUNTIME}from"./daemon-runtime-Dx800VUt.js";import"./runtime-guard-Bi8k55v9.js";import"./systemd-DdVd5Yet.js";import{s as resolveGatewayLogPaths}from"./service-EKJG69M3.js";import{S as installDaemonServiceAndEmit,_ as resolveRuntimeStatusColor,b as buildDaemonServiceSnapshot,i as runServiceUninstall,r as runServiceStop,t as runServiceRestart,u as createCliStatusTextStyles,x as createDaemonActionContext,y as formatRuntimeStatus}from"./lifecycle-core-D9Dg5Qps.js";import"./diagnostics-DamNPi4e.js";import{t as parsePort}from"./parse-port-FgIKmqqb.js";import{t as resolveNodeService}from"./node-service-77UF0ACm.js";import{n as validateSystemRunCommandConsistency}from"./system-run-command-rlCfXRWt.js";import{spawn}from"node:child_process";import path from"node:path";import fs from"node:fs";import crypto from"node:crypto";import fs$1 from"node:fs/promises";function resolveNodeHostConfigPath(){return path.join(resolveStateDir(),`node.json`)}function normalizeConfig(config){let base={version:1,nodeId:``,token:config?.token,displayName:config?.displayName,gateway:config?.gateway};return config?.version===1&&typeof config.nodeId==`string`&&(base.nodeId=config.nodeId.trim()),base.nodeId||=crypto.randomUUID(),base}async function loadNodeHostConfig(){let filePath=resolveNodeHostConfigPath();try{let raw=await fs$1.readFile(filePath,`utf8`);return normalizeConfig(JSON.parse(raw))}catch{return null}}async function saveNodeHostConfig(config){let filePath=resolveNodeHostConfigPath();await fs$1.mkdir(path.dirname(filePath),{recursive:!0});let payload=JSON.stringify(config,null,2);await fs$1.writeFile(filePath,`${payload}\n`,{mode:384});try{await fs$1.chmod(filePath,384)}catch{}}async function ensureNodeHostConfig(){let normalized=normalizeConfig(await loadNodeHostConfig());return await saveNodeHostConfig(normalized),normalized}async function requestExecHostViaSocket(params){let{socketPath,token,request}=params;if(!socketPath||!token)return null;let timeoutMs=params.timeoutMs??2e4,requestJson=JSON.stringify(request),nonce=crypto.randomBytes(16).toString(`hex`),ts=Date.now(),hmac=crypto.createHmac(`sha256`,token).update(`${nonce}:${ts}:${requestJson}`).digest(`hex`);return await requestJsonlSocket({socketPath,payload:JSON.stringify({type:`exec`,id:crypto.randomUUID(),nonce,ts,hmac,requestJson}),timeoutMs,accept:value=>{let msg=value;if(msg?.type===`exec-res`)return msg.ok===!0&&msg.payload?{ok:!0,payload:msg.payload}:msg.ok===!1&&msg.error?{ok:!1,error:msg.error}:null}})}const BROWSER_PROXY_MAX_FILE_BYTES=10*1024*1024;function normalizeProfileAllowlist(raw){return Array.isArray(raw)?raw.map(entry=>entry.trim()).filter(Boolean):[]}function resolveBrowserProxyConfig(){let proxy=loadConfig().nodeHost?.browserProxy,allowProfiles=normalizeProfileAllowlist(proxy?.allowProfiles);return{enabled:proxy?.enabled!==!1,allowProfiles}}let browserControlReady=null;async function ensureBrowserControlService(){return browserControlReady||(browserControlReady=(async()=>{let cfg=loadConfig();if(!resolveBrowserConfig(cfg.browser,cfg).enabled||!await startBrowserControlServiceFromConfig())throw Error(`browser control disabled`)})(),browserControlReady)}function isProfileAllowed(params){let{allowProfiles,profile}=params;return allowProfiles.length?profile?allowProfiles.includes(profile.trim()):!1:!0}function collectBrowserProxyPaths(payload){let paths=new Set,obj=typeof payload==`object`&&payload?payload:null;if(!obj)return[];typeof obj.path==`string`&&obj.path.trim()&&paths.add(obj.path.trim()),typeof obj.imagePath==`string`&&obj.imagePath.trim()&&paths.add(obj.imagePath.trim());let download=obj.download;if(download&&typeof download==`object`){let dlPath=download.path;typeof dlPath==`string`&&dlPath.trim()&&paths.add(dlPath.trim())}return[...paths]}async function readBrowserProxyFile(filePath){let stat=await fs$1.stat(filePath).catch(()=>null);if(!stat||!stat.isFile())return null;if(stat.size>BROWSER_PROXY_MAX_FILE_BYTES)throw Error(`browser proxy file exceeds ${Math.round(BROWSER_PROXY_MAX_FILE_BYTES/(1024*1024))}MB`);let buffer=await fs$1.readFile(filePath),mimeType=await detectMime({buffer,filePath});return{path:filePath,base64:buffer.toString(`base64`),mimeType}}function decodeParams$1(raw){if(!raw)throw Error(`INVALID_REQUEST: paramsJSON required`);return JSON.parse(raw)}async function runBrowserProxyCommand(paramsJSON){let params=decodeParams$1(paramsJSON),pathValue=typeof params.path==`string`?params.path.trim():``;if(!pathValue)throw Error(`INVALID_REQUEST: path required`);let proxyConfig=resolveBrowserProxyConfig();if(!proxyConfig.enabled)throw Error(`UNAVAILABLE: node browser proxy disabled`);await ensureBrowserControlService();let cfg=loadConfig(),resolved=resolveBrowserConfig(cfg.browser,cfg),requestedProfile=typeof params.profile==`string`?params.profile.trim():``,allowedProfiles=proxyConfig.allowProfiles;if(allowedProfiles.length>0){if(pathValue!==`/profiles`){if(!isProfileAllowed({allowProfiles:allowedProfiles,profile:requestedProfile||resolved.defaultProfile}))throw Error(`INVALID_REQUEST: browser profile not allowed`)}else if(requestedProfile&&!isProfileAllowed({allowProfiles:allowedProfiles,profile:requestedProfile}))throw Error(`INVALID_REQUEST: browser profile not allowed`)}let method=typeof params.method==`string`?params.method.toUpperCase():`GET`,path=pathValue.startsWith(`/`)?pathValue:`/${pathValue}`,body=params.body,query={};requestedProfile&&(query.profile=requestedProfile);let rawQuery=params.query??{};for(let[key,value]of Object.entries(rawQuery))value!=null&&(query[key]=typeof value==`string`?value:String(value));let dispatcher=createBrowserRouteDispatcher(createBrowserControlContext()),response=await withTimeout(signal=>dispatcher.dispatch({method:method===`DELETE`?`DELETE`:method===`POST`?`POST`:`GET`,path,query,body,signal}),params.timeoutMs,`browser proxy request`);if(response.status>=400){let message=response.body&&typeof response.body==`object`&&`error`in response.body?String(response.body.error):`HTTP ${response.status}`;throw Error(message)}let result=response.body;if(allowedProfiles.length>0&&path===`/profiles`){let obj=typeof result==`object`&&result?result:{};obj.profiles=(Array.isArray(obj.profiles)?obj.profiles:[]).filter(entry=>{if(!entry||typeof entry!=`object`)return!1;let name=entry.name;return typeof name==`string`&&allowedProfiles.includes(name)})}let files,paths=collectBrowserProxyPaths(result);if(paths.length>0){let loaded=await Promise.all(paths.map(async p=>{try{let file=await readBrowserProxyFile(p);if(!file)throw Error(`file not found`);return file}catch(err){throw Error(`browser proxy file read failed for ${p}: ${String(err)}`,{cause:err})}}));loaded.length>0&&(files=loaded)}let payload=files?{result,files}:{result};return JSON.stringify(payload)}const OUTPUT_CAP=2e5,execHostEnforced=process.env.BUILDERFORCE_AGENTS_NODE_EXEC_HOST?.trim().toLowerCase()===`app`,execHostFallbackAllowed=process.env.BUILDERFORCE_AGENTS_NODE_EXEC_FALLBACK?.trim().toLowerCase()!==`0`,blockedEnvKeys=new Set([`NODE_OPTIONS`,`PYTHONHOME`,`PYTHONPATH`,`PERL5LIB`,`PERL5OPT`,`RUBYOPT`]),blockedEnvPrefixes=[`DYLD_`,`LD_`];function resolveExecSecurity(value){return value===`deny`||value===`allowlist`||value===`full`?value:`allowlist`}function isCmdExeInvocation(argv){let token=argv[0]?.trim();if(!token)return!1;let base=path.win32.basename(token).toLowerCase();return base===`cmd.exe`||base===`cmd`}function resolveExecAsk(value){return value===`off`||value===`on-miss`||value===`always`?value:`on-miss`}function sanitizeEnv(overrides){if(!overrides)return;let merged={...process.env};for(let[rawKey,value]of Object.entries(overrides)){let key=rawKey.trim();if(!key)continue;let upper=key.toUpperCase();upper!==`PATH`&&(blockedEnvKeys.has(upper)||blockedEnvPrefixes.some(prefix=>upper.startsWith(prefix))||(merged[key]=value))}return merged}function truncateOutput(raw,maxChars){return raw.length<=maxChars?{text:raw,truncated:!1}:{text:`... (truncated) ${raw.slice(raw.length-maxChars)}`,truncated:!0}}function redactExecApprovals(file){let socketPath=file.socket?.path?.trim();return{...file,socket:socketPath?{path:socketPath}:void 0}}function requireExecApprovalsBaseHash(params,snapshot){if(!snapshot.exists)return;if(!snapshot.hash)throw Error(`INVALID_REQUEST: exec approvals base hash unavailable; reload and retry`);let baseHash=typeof params.baseHash==`string`?params.baseHash.trim():``;if(!baseHash)throw Error(`INVALID_REQUEST: exec approvals base hash required; reload and retry`);if(baseHash!==snapshot.hash)throw Error(`INVALID_REQUEST: exec approvals changed; reload and retry`)}async function runCommand(argv,cwd,env,timeoutMs){return await new Promise(resolve=>{let stdout=``,stderr=``,outputLen=0,truncated=!1,timedOut=!1,settled=!1,child=spawn(argv[0],argv.slice(1),{cwd,env,stdio:[`ignore`,`pipe`,`pipe`],windowsHide:!0}),onChunk=(chunk,target)=>{if(outputLen>=OUTPUT_CAP){truncated=!0;return}let remaining=OUTPUT_CAP-outputLen,slice=chunk.length>remaining?chunk.subarray(0,remaining):chunk,str=slice.toString(`utf8`);outputLen+=slice.length,target===`stdout`?stdout+=str:stderr+=str,chunk.length>remaining&&(truncated=!0)};child.stdout?.on(`data`,chunk=>onChunk(chunk,`stdout`)),child.stderr?.on(`data`,chunk=>onChunk(chunk,`stderr`));let timer;timeoutMs&&timeoutMs>0&&(timer=setTimeout(()=>{timedOut=!0;try{child.kill(`SIGKILL`)}catch{}},timeoutMs));let finalize=(exitCode,error)=>{settled||(settled=!0,timer&&clearTimeout(timer),resolve({exitCode,timedOut,success:exitCode===0&&!timedOut&&!error,stdout,stderr,error:error??null,truncated}))};child.on(`error`,err=>{finalize(void 0,err.message)}),child.on(`exit`,code=>{finalize(code===null?void 0:code,null)})})}function resolveEnvPath(env){return(env?.PATH??env?.Path??process.env.PATH??process.env.Path??`/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin`).split(path.delimiter).filter(Boolean)}function resolveExecutable(bin,env){if(bin.includes(`/`)||bin.includes(`\\`))return null;let extensions=process.platform===`win32`?(process.env.PATHEXT??process.env.PathExt??`.EXE;.CMD;.BAT;.COM`).split(`;`).map(ext=>ext.toLowerCase()):[``];for(let dir of resolveEnvPath(env))for(let ext of extensions){let candidate=path.join(dir,bin+ext);if(fs.existsSync(candidate))return candidate}return null}async function handleSystemWhich(params,env){let bins=params.bins.map(bin=>bin.trim()).filter(Boolean),found={};for(let bin of bins){let path=resolveExecutable(bin,env);path&&(found[bin]=path)}return{bins:found}}function buildExecEventPayload(payload){if(!payload.output)return payload;let trimmed=payload.output.trim();if(!trimmed)return payload;let{text}=truncateOutput(trimmed,2e4);return{...payload,output:text}}async function sendExecFinishedEvent(params){let combined=[params.result.stdout,params.result.stderr,params.result.error].filter(Boolean).join(`
|
|
2
2
|
`);await sendNodeEvent(params.client,`exec.finished`,buildExecEventPayload({sessionKey:params.sessionKey,runId:params.runId,host:`node`,command:params.cmdText,exitCode:params.result.exitCode??void 0,timedOut:params.result.timedOut,success:params.result.success,output:combined}))}async function runViaMacAppExecHost(params){let{approvals,request}=params;return await requestExecHostViaSocket({socketPath:approvals.socketPath,token:approvals.token,request})}async function sendJsonPayloadResult(client,frame,payload){await sendInvokeResult(client,frame,{ok:!0,payloadJSON:JSON.stringify(payload)})}async function sendRawPayloadResult(client,frame,payloadJSON){await sendInvokeResult(client,frame,{ok:!0,payloadJSON})}async function sendErrorResult(client,frame,code,message){await sendInvokeResult(client,frame,{ok:!1,error:{code,message}})}async function sendInvalidRequestResult(client,frame,err){await sendErrorResult(client,frame,`INVALID_REQUEST`,String(err))}async function handleInvoke(frame,client,skillBins){let command=String(frame.command??``);if(command===`system.execApprovals.get`){try{ensureExecApprovals();let snapshot=readExecApprovalsSnapshot();await sendJsonPayloadResult(client,frame,{path:snapshot.path,exists:snapshot.exists,hash:snapshot.hash,file:redactExecApprovals(snapshot.file)})}catch(err){let message=String(err);await sendErrorResult(client,frame,message.toLowerCase().includes(`timed out`)?`TIMEOUT`:`INVALID_REQUEST`,message)}return}if(command===`system.execApprovals.set`){try{let params=decodeParams(frame.paramsJSON);if(!params.file||typeof params.file!=`object`)throw Error(`INVALID_REQUEST: exec approvals file required`);ensureExecApprovals();let snapshot=readExecApprovalsSnapshot();requireExecApprovalsBaseHash(params,snapshot),saveExecApprovals(mergeExecApprovalsSocketDefaults({normalized:normalizeExecApprovals(params.file),current:snapshot.file}));let nextSnapshot=readExecApprovalsSnapshot();await sendJsonPayloadResult(client,frame,{path:nextSnapshot.path,exists:nextSnapshot.exists,hash:nextSnapshot.hash,file:redactExecApprovals(nextSnapshot.file)})}catch(err){await sendInvalidRequestResult(client,frame,err)}return}if(command===`system.which`){try{let params=decodeParams(frame.paramsJSON);if(!Array.isArray(params.bins))throw Error(`INVALID_REQUEST: bins required`);await sendJsonPayloadResult(client,frame,await handleSystemWhich(params,sanitizeEnv(void 0)))}catch(err){await sendInvalidRequestResult(client,frame,err)}return}if(command===`browser.proxy`){try{await sendRawPayloadResult(client,frame,await runBrowserProxyCommand(frame.paramsJSON))}catch(err){await sendInvalidRequestResult(client,frame,err)}return}if(command!==`system.run`){await sendErrorResult(client,frame,`UNAVAILABLE`,`command not supported`);return}let params;try{params=decodeParams(frame.paramsJSON)}catch(err){await sendInvalidRequestResult(client,frame,err);return}if(!Array.isArray(params.command)||params.command.length===0){await sendErrorResult(client,frame,`INVALID_REQUEST`,`command required`);return}let argv=params.command.map(item=>String(item)),rawCommand=typeof params.rawCommand==`string`?params.rawCommand.trim():``,consistency=validateSystemRunCommandConsistency({argv,rawCommand:rawCommand||null});if(!consistency.ok){await sendErrorResult(client,frame,`INVALID_REQUEST`,consistency.message);return}let shellCommand=consistency.shellCommand,cmdText=consistency.cmdText,agentId=params.agentId?.trim()||void 0,cfg=loadConfig(),agentExec=agentId?resolveAgentConfig(cfg,agentId)?.tools?.exec:void 0,approvals=resolveExecApprovals(agentId,{security:resolveExecSecurity(agentExec?.security??cfg.tools?.exec?.security),ask:resolveExecAsk(agentExec?.ask??cfg.tools?.exec?.ask)}),security=approvals.agent.security,ask=approvals.agent.ask,autoAllowSkills=approvals.agent.autoAllowSkills,sessionKey=params.sessionKey?.trim()||`node`,runId=params.runId?.trim()||crypto.randomUUID(),env=sanitizeEnv(params.env??void 0),safeBins=resolveSafeBins(agentExec?.safeBins??cfg.tools?.exec?.safeBins),bins=autoAllowSkills?await skillBins.current():new Set,analysisOk=!1,allowlistMatches=[],allowlistSatisfied=!1,segments=[];if(shellCommand){let allowlistEval=evaluateShellAllowlist({command:shellCommand,allowlist:approvals.allowlist,safeBins,cwd:params.cwd??void 0,env,skillBins:bins,autoAllowSkills,platform:process.platform});analysisOk=allowlistEval.analysisOk,allowlistMatches=allowlistEval.allowlistMatches,allowlistSatisfied=security===`allowlist`&&analysisOk?allowlistEval.allowlistSatisfied:!1,segments=allowlistEval.segments}else{let analysis=analyzeArgvCommand({argv,cwd:params.cwd??void 0,env}),allowlistEval=evaluateExecAllowlist({analysis,allowlist:approvals.allowlist,safeBins,cwd:params.cwd??void 0,skillBins:bins,autoAllowSkills});analysisOk=analysis.ok,allowlistMatches=allowlistEval.allowlistMatches,allowlistSatisfied=security===`allowlist`&&analysisOk?allowlistEval.allowlistSatisfied:!1,segments=analysis.segments}let isWindows=process.platform===`win32`,cmdInvocation=isCmdExeInvocation(shellCommand?segments[0]?.argv??[]:argv);if(security===`allowlist`&&isWindows&&cmdInvocation&&(analysisOk=!1,allowlistSatisfied=!1),process.platform===`darwin`){let approvalDecision=params.approvalDecision===`allow-once`||params.approvalDecision===`allow-always`?params.approvalDecision:null,response=await runViaMacAppExecHost({approvals,request:{command:argv,rawCommand:rawCommand||shellCommand||null,cwd:params.cwd??null,env:params.env??null,timeoutMs:params.timeoutMs??null,needsScreenRecording:params.needsScreenRecording??null,agentId:agentId??null,sessionKey:sessionKey??null,approvalDecision}});if(!response){if(execHostEnforced||!execHostFallbackAllowed){await sendNodeEvent(client,`exec.denied`,buildExecEventPayload({sessionKey,runId,host:`node`,command:cmdText,reason:`companion-unavailable`})),await sendInvokeResult(client,frame,{ok:!1,error:{code:`UNAVAILABLE`,message:`COMPANION_APP_UNAVAILABLE: macOS app exec host unreachable`}});return}}else if(response.ok){let result=response.payload;await sendExecFinishedEvent({client,sessionKey,runId,cmdText,result}),await sendInvokeResult(client,frame,{ok:!0,payloadJSON:JSON.stringify(result)});return}else{await sendNodeEvent(client,`exec.denied`,buildExecEventPayload({sessionKey,runId,host:`node`,command:cmdText,reason:response.error.reason??`approval-required`})),await sendInvokeResult(client,frame,{ok:!1,error:{code:`UNAVAILABLE`,message:response.error.message}});return}}if(security===`deny`){await sendNodeEvent(client,`exec.denied`,buildExecEventPayload({sessionKey,runId,host:`node`,command:cmdText,reason:`security=deny`})),await sendInvokeResult(client,frame,{ok:!1,error:{code:`UNAVAILABLE`,message:`SYSTEM_RUN_DISABLED: security=deny`}});return}let requiresAsk=requiresExecApproval({ask,security,analysisOk,allowlistSatisfied}),approvalDecision=params.approvalDecision===`allow-once`||params.approvalDecision===`allow-always`?params.approvalDecision:null,approvedByAsk=approvalDecision!==null||params.approved===!0;if(requiresAsk&&!approvedByAsk){await sendNodeEvent(client,`exec.denied`,buildExecEventPayload({sessionKey,runId,host:`node`,command:cmdText,reason:`approval-required`})),await sendInvokeResult(client,frame,{ok:!1,error:{code:`UNAVAILABLE`,message:`SYSTEM_RUN_DENIED: approval required`}});return}if(approvalDecision===`allow-always`&&security===`allowlist`&&analysisOk)for(let segment of segments){let pattern=segment.resolution?.resolvedPath??``;pattern&&addAllowlistEntry(approvals.file,agentId,pattern)}if(security===`allowlist`&&(!analysisOk||!allowlistSatisfied)&&!approvedByAsk){await sendNodeEvent(client,`exec.denied`,buildExecEventPayload({sessionKey,runId,host:`node`,command:cmdText,reason:`allowlist-miss`})),await sendInvokeResult(client,frame,{ok:!1,error:{code:`UNAVAILABLE`,message:`SYSTEM_RUN_DENIED: allowlist miss`}});return}if(allowlistMatches.length>0){let seen=new Set;for(let match of allowlistMatches)!match?.pattern||seen.has(match.pattern)||(seen.add(match.pattern),recordAllowlistUse(approvals.file,agentId,match,cmdText,segments[0]?.resolution?.resolvedPath))}if(params.needsScreenRecording===!0){await sendNodeEvent(client,`exec.denied`,buildExecEventPayload({sessionKey,runId,host:`node`,command:cmdText,reason:`permission:screenRecording`})),await sendInvokeResult(client,frame,{ok:!1,error:{code:`UNAVAILABLE`,message:`PERMISSION_MISSING: screenRecording`}});return}let execArgv=argv;security===`allowlist`&&isWindows&&!approvedByAsk&&shellCommand&&analysisOk&&allowlistSatisfied&&segments.length===1&&segments[0]?.argv.length>0&&(execArgv=segments[0].argv);let result=await runCommand(execArgv,params.cwd?.trim()||void 0,env,params.timeoutMs??void 0);if(result.truncated){let suffix=`... (truncated)`;result.stderr.trim().length>0?result.stderr=`${result.stderr}\n${suffix}`:result.stdout=`${result.stdout}\n${suffix}`}await sendExecFinishedEvent({client,sessionKey,runId,cmdText,result}),await sendInvokeResult(client,frame,{ok:!0,payloadJSON:JSON.stringify({exitCode:result.exitCode,timedOut:result.timedOut,success:result.success,stdout:result.stdout,stderr:result.stderr,error:result.error??null})})}function decodeParams(raw){if(!raw)throw Error(`INVALID_REQUEST: paramsJSON required`);return JSON.parse(raw)}function coerceNodeInvokePayload(payload){if(!payload||typeof payload!=`object`)return null;let obj=payload,id=typeof obj.id==`string`?obj.id.trim():``,nodeId=typeof obj.nodeId==`string`?obj.nodeId.trim():``,command=typeof obj.command==`string`?obj.command.trim():``;return!id||!nodeId||!command?null:{id,nodeId,command,paramsJSON:typeof obj.paramsJSON==`string`?obj.paramsJSON:obj.params===void 0?null:JSON.stringify(obj.params),timeoutMs:typeof obj.timeoutMs==`number`?obj.timeoutMs:null,idempotencyKey:typeof obj.idempotencyKey==`string`?obj.idempotencyKey:null}}async function sendInvokeResult(client,frame,result){try{await client.request(`node.invoke.result`,buildNodeInvokeResultParams(frame,result))}catch{}}function buildNodeInvokeResultParams(frame,result){let params={id:frame.id,nodeId:frame.nodeId,ok:result.ok};return result.payload!==void 0&&(params.payload=result.payload),typeof result.payloadJSON==`string`&&(params.payloadJSON=result.payloadJSON),result.error&&(params.error=result.error),params}async function sendNodeEvent(client,event,payload){try{await client.request(`node.event`,{event,payloadJSON:payload?JSON.stringify(payload):null})}catch{}}const DEFAULT_NODE_PATH=`/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin`;var SkillBinsCache=class{constructor(fetch){this.bins=new Set,this.lastRefresh=0,this.ttlMs=9e4,this.fetch=fetch}async current(force=!1){return(force||Date.now()-this.lastRefresh>this.ttlMs)&&await this.refresh(),this.bins}async refresh(){try{let bins=await this.fetch();this.bins=new Set(bins),this.lastRefresh=Date.now()}catch{this.lastRefresh||(this.bins=new Set)}}};function ensureNodePathEnv(){ensureBuilderForceAgentsCliOnPath({pathEnv:process.env.PATH??``});let current=process.env.PATH??``;return current.trim()?current:(process.env.PATH=DEFAULT_NODE_PATH,DEFAULT_NODE_PATH)}async function runNodeHost(opts){let config=await ensureNodeHostConfig(),nodeId=opts.nodeId?.trim()||config.nodeId;nodeId!==config.nodeId&&(config.nodeId=nodeId);let displayName=opts.displayName?.trim()||config.displayName||await getMachineDisplayName();config.displayName=displayName;let gateway={host:opts.gatewayHost,port:opts.gatewayPort,tls:opts.gatewayTls??loadConfig().gateway?.tls?.enabled??!1,tlsFingerprint:opts.gatewayTlsFingerprint};config.gateway=gateway,await saveNodeHostConfig(config);let cfg=loadConfig(),resolvedBrowser=resolveBrowserConfig(cfg.browser,cfg),browserProxyEnabled=cfg.nodeHost?.browserProxy?.enabled!==!1&&resolvedBrowser.enabled,isRemoteMode=cfg.gateway?.mode===`remote`,token=process.env.BUILDERFORCE_AGENTS_GATEWAY_TOKEN?.trim()||(isRemoteMode?cfg.gateway?.remote?.token:cfg.gateway?.auth?.token),password=process.env.BUILDERFORCE_AGENTS_GATEWAY_PASSWORD?.trim()||(isRemoteMode?cfg.gateway?.remote?.password:cfg.gateway?.auth?.password),host=gateway.host??`127.0.0.1`,port=gateway.port??18789,url=`${gateway.tls?`wss`:`ws`}://${host}:${port}`,pathEnv=ensureNodePathEnv();console.log(`node host PATH: ${pathEnv}`);let client=new GatewayClient({url,token:token?.trim()||void 0,password:password?.trim()||void 0,instanceId:nodeId,clientName:GATEWAY_CLIENT_NAMES.NODE_HOST,clientDisplayName:displayName,clientVersion:VERSION,platform:process.platform,mode:GATEWAY_CLIENT_MODES.NODE,role:`node`,scopes:[],caps:[`system`,...browserProxyEnabled?[`browser`]:[]],commands:[`system.run`,`system.which`,`system.execApprovals.get`,`system.execApprovals.set`,...browserProxyEnabled?[`browser.proxy`]:[]],pathEnv,permissions:void 0,deviceIdentity:loadOrCreateDeviceIdentity(),tlsFingerprint:gateway.tlsFingerprint,onEvent:evt=>{if(evt.event!==`node.invoke.request`)return;let payload=coerceNodeInvokePayload(evt.payload);payload&&handleInvoke(payload,client,skillBins)},onConnectError:err=>{console.error(`node host gateway connect failed: ${err.message}`)},onClose:(code,reason)=>{console.error(`node host gateway closed (${code}): ${reason}`)}}),skillBins=new SkillBinsCache(async()=>{let res=await client.request(`skills.bins`,{});return Array.isArray(res?.bins)?res.bins.map(bin=>String(bin)):[]});client.start(),await new Promise(()=>{})}async function buildNodeInstallPlan(params){let devMode=params.devMode??resolveGatewayDevMode(),nodePath=params.nodePath??await resolvePreferredNodePath({env:params.env,runtime:params.runtime}),{programArguments,workingDirectory}=await resolveNodeProgramArguments({host:params.host,port:params.port,tls:params.tls,tlsFingerprint:params.tlsFingerprint,nodeId:params.nodeId,displayName:params.displayName,dev:devMode,runtime:params.runtime,nodePath});await emitNodeRuntimeWarning({env:params.env,runtime:params.runtime,nodeProgram:programArguments[0],warn:params.warn,title:`Node daemon runtime`});let environment=buildNodeServiceEnvironment({env:params.env});return{programArguments,workingDirectory,environment,description:formatNodeServiceDescription({version:environment.BUILDERFORCE_AGENTS_SERVICE_VERSION})}}const DEFAULT_NODE_DAEMON_RUNTIME=DEFAULT_GATEWAY_DAEMON_RUNTIME;function isNodeDaemonRuntime(value){return isGatewayDaemonRuntime(value)}function renderNodeServiceStartHints(){let base=[formatCliCommand(`builderforce node install`),formatCliCommand(`builderforce node start`)];switch(process.platform){case`darwin`:return[...base,`launchctl bootstrap gui/$UID ~/Library/LaunchAgents/${resolveNodeLaunchAgentLabel()}.plist`];case`linux`:return[...base,`systemctl --user start ${resolveNodeSystemdServiceName()}.service`];case`win32`:return[...base,`schtasks /Run /TN "${resolveNodeWindowsTaskName()}"`];default:return base}}function buildNodeRuntimeHints(env=process.env){if(process.platform===`darwin`){let logs=resolveGatewayLogPaths(env);return[`Launchd stdout (if installed): ${logs.stdoutPath}`,`Launchd stderr (if installed): ${logs.stderrPath}`]}return process.platform===`linux`?[`Logs: journalctl --user -u ${resolveNodeSystemdServiceName()}.service -n 200 --no-pager`]:process.platform===`win32`?[`Logs: schtasks /Query /TN "${resolveNodeWindowsTaskName()}" /V /FO LIST`]:[]}function resolveNodeDefaults(opts,config){let host=opts.host?.trim()||config?.gateway?.host||`127.0.0.1`,portOverride=parsePort(opts.port);return opts.port!==void 0&&portOverride===null?{host,port:null}:{host,port:portOverride??config?.gateway?.port??18789}}async function runNodeDaemonInstall(opts){let json=!!opts.json,{stdout,warnings,emit,fail}=createDaemonActionContext({action:`install`,json});if(resolveIsNixMode(process.env)){fail(`Nix mode detected; service install is disabled.`);return}let config=await loadNodeHostConfig(),{host,port}=resolveNodeDefaults(opts,config);if(!Number.isFinite(port??NaN)||(port??0)<=0){fail(`Invalid port`);return}let runtimeRaw=opts.runtime?String(opts.runtime):DEFAULT_NODE_DAEMON_RUNTIME;if(!isNodeDaemonRuntime(runtimeRaw)){fail(`Invalid --runtime (use "node" or "bun")`);return}let service=resolveNodeService(),loaded=!1;try{loaded=await service.isLoaded({env:process.env})}catch(err){fail(`Node service check failed: ${String(err)}`);return}if(loaded&&!opts.force){emit({ok:!0,result:`already-installed`,message:`Node service already ${service.loadedText}.`,service:buildDaemonServiceSnapshot(service,loaded),warnings:warnings.length?warnings:void 0}),json||(defaultRuntime.log(`Node service already ${service.loadedText}.`),defaultRuntime.log(`Reinstall with: ${formatCliCommand(`builderforce node install --force`)}`));return}let tlsFingerprint=opts.tlsFingerprint?.trim()||config?.gateway?.tlsFingerprint,tls=!!opts.tls||!!tlsFingerprint||!!config?.gateway?.tls,{programArguments,workingDirectory,environment,description}=await buildNodeInstallPlan({env:process.env,host,port:port??18789,tls,tlsFingerprint:tlsFingerprint||void 0,nodeId:opts.nodeId,displayName:opts.displayName,runtime:runtimeRaw,warn:message=>{json?warnings.push(message):defaultRuntime.log(message)}});await installDaemonServiceAndEmit({serviceNoun:`Node`,service,warnings,emit,fail,install:async()=>{await service.install({env:process.env,stdout,programArguments,workingDirectory,environment,description})}})}async function runNodeDaemonUninstall(opts={}){return await runServiceUninstall({serviceNoun:`Node`,service:resolveNodeService(),opts,stopBeforeUninstall:!1,assertNotLoadedAfterUninstall:!1})}async function runNodeDaemonRestart(opts={}){await runServiceRestart({serviceNoun:`Node`,service:resolveNodeService(),renderStartHints:renderNodeServiceStartHints,opts})}async function runNodeDaemonStop(opts={}){return await runServiceStop({serviceNoun:`Node`,service:resolveNodeService(),opts})}async function runNodeDaemonStatus(opts={}){let json=!!opts.json,service=resolveNodeService(),[loaded,command,runtime]=await Promise.all([service.isLoaded({env:process.env}).catch(()=>!1),service.readCommand(process.env).catch(()=>null),service.readRuntime(process.env).catch(err=>({status:`unknown`,detail:String(err)}))]),payload={service:{...buildDaemonServiceSnapshot(service,loaded),command,runtime}};if(json){defaultRuntime.log(JSON.stringify(payload,null,2));return}let{rich,label,accent,infoText,okText,warnText,errorText}=createCliStatusTextStyles(),serviceStatus=loaded?okText(service.loadedText):warnText(service.notLoadedText);defaultRuntime.log(`${label(`Service:`)} ${accent(service.label)} (${serviceStatus})`),command?.programArguments?.length&&defaultRuntime.log(`${label(`Command:`)} ${infoText(command.programArguments.join(` `))}`),command?.sourcePath&&defaultRuntime.log(`${label(`Service file:`)} ${infoText(command.sourcePath)}`),command?.workingDirectory&&defaultRuntime.log(`${label(`Working dir:`)} ${infoText(command.workingDirectory)}`);let runtimeLine=formatRuntimeStatus(runtime);if(runtimeLine){let runtimeColor=resolveRuntimeStatusColor(runtime?.status);defaultRuntime.log(`${label(`Runtime:`)} ${colorize(rich,runtimeColor,runtimeLine)}`)}if(!loaded){defaultRuntime.log(``);for(let hint of renderNodeServiceStartHints())defaultRuntime.log(`${warnText(`Start with:`)} ${infoText(hint)}`);return}let baseEnv={...process.env,...command?.environment??void 0},hintEnv={...baseEnv,BUILDERFORCE_AGENTS_LOG_PREFIX:baseEnv.BUILDERFORCE_AGENTS_LOG_PREFIX??`node`};if(runtime?.missingUnit){defaultRuntime.error(errorText(`Service unit not found.`));for(let hint of buildNodeRuntimeHints(hintEnv))defaultRuntime.error(errorText(hint));return}if(runtime?.status===`stopped`){defaultRuntime.error(errorText(`Service is loaded but not running.`));for(let hint of buildNodeRuntimeHints(hintEnv))defaultRuntime.error(errorText(hint))}}function parsePortWithFallback(value,fallback){return parsePort(value)??fallback}function registerNodeCli(program){let node=program.command(`node`).description(`Run and manage the headless node host service`).addHelpText(`after`,()=>`\n${theme.heading(`Examples:`)}\n${formatHelpExamples([[`builderforce node run --host 127.0.0.1 --port 18789`,`Run the node host in the foreground.`],[`builderforce node status`,`Check node host service status.`],[`builderforce node install`,`Install the node host service.`],[`builderforce node restart`,`Restart the installed node host service.`]])}\n\n${theme.muted(`Docs:`)} ${formatDocsLink(`/cli/node`,`docs.builderforce.ai/cli/node`)}\n`);node.command(`run`).description(`Run the headless node host (foreground)`).option(`--host <host>`,`Gateway host`).option(`--port <port>`,`Gateway port`).option(`--tls`,`Use TLS for the gateway connection`,!1).option(`--tls-fingerprint <sha256>`,`Expected TLS certificate fingerprint (sha256)`).option(`--node-id <id>`,`Override node id (clears pairing token)`).option(`--display-name <name>`,`Override node display name`).action(async opts=>{let existing=await loadNodeHostConfig();await runNodeHost({gatewayHost:opts.host?.trim()||existing?.gateway?.host||`127.0.0.1`,gatewayPort:parsePortWithFallback(opts.port,existing?.gateway?.port??18789),gatewayTls:!!opts.tls||!!opts.tlsFingerprint,gatewayTlsFingerprint:opts.tlsFingerprint,nodeId:opts.nodeId,displayName:opts.displayName})}),node.command(`status`).description(`Show node host status`).option(`--json`,`Output JSON`,!1).action(async opts=>{await runNodeDaemonStatus(opts)}),node.command(`install`).description(`Install the node host service (launchd/systemd/schtasks)`).option(`--host <host>`,`Gateway host`).option(`--port <port>`,`Gateway port`).option(`--tls`,`Use TLS for the gateway connection`,!1).option(`--tls-fingerprint <sha256>`,`Expected TLS certificate fingerprint (sha256)`).option(`--node-id <id>`,`Override node id (clears pairing token)`).option(`--display-name <name>`,`Override node display name`).option(`--runtime <runtime>`,`Service runtime (node|bun). Default: node`).option(`--force`,`Reinstall/overwrite if already installed`,!1).option(`--json`,`Output JSON`,!1).action(async opts=>{await runNodeDaemonInstall(opts)}),node.command(`uninstall`).description(`Uninstall the node host service (launchd/systemd/schtasks)`).option(`--json`,`Output JSON`,!1).action(async opts=>{await runNodeDaemonUninstall(opts)}),node.command(`stop`).description(`Stop the node host service (launchd/systemd/schtasks)`).option(`--json`,`Output JSON`,!1).action(async opts=>{await runNodeDaemonStop(opts)}),node.command(`restart`).description(`Restart the node host service (launchd/systemd/schtasks)`).option(`--json`,`Output JSON`,!1).action(async opts=>{await runNodeDaemonRestart(opts)})}export{registerNodeCli};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{d as resolveIsNixMode,g as resolveStateDir}from"./paths-5FcIFMsj.js";import{B as theme,R as colorize}from"./utils-DbaBVFaK.js";import"./session-key-EoB0qaG9.js";import"./builderforce-root-D64_sXEi.js";import{i as defaultRuntime}from"./subsystem-B3TqcCrZ.js";import"./registry-TdK-aV05.js";import"./logger-Bch0bx9c.js";import"./exec-DdcIjeyn.js";import{r as resolveAgentConfig}from"./agent-scope-DPtjOxzp.js";import"./src-CA0fU67C.js";import"./model-selection-9bRFKBI_.js";import{t as formatCliCommand}from"./command-format-D806O2pt.js";import"./env-file-D1MDi-AM.js";import"./boolean-Cnh1KNl1.js";import"./env-BIdU5BAp.js";import"./src-DTFqOIQD.js";import{U as VERSION,r as loadConfig}from"./io-3R_ZyUxB.js";import"./manifest-registry-BJCfNV1a.js";import"./config-_1Ca6jGb.js";import"./chrome-a3X9_-nf.js";import"./tailscale-DLkpGquM.js";import"./auth-lebUHrkd.js";import{i as resolveBrowserConfig}from"./server-context-DJZT7Upf.js";import"./routes-BzfLvF8W.js";import"./redact-BHdfp2MZ.js";import"./errors-B1MIg3g-.js";import"./paths-cR8ct-Y3.js";import"./ssrf-p9k-iapc.js";import{c as detectMime}from"./image-ops-C8IUQKjn.js";import"./store-CmHBQ-yX.js";import"./ports-DgmEDNOm.js";import"./trash-DD2Hc5oq.js";import{h as GATEWAY_CLIENT_NAMES,m as GATEWAY_CLIENT_MODES}from"./message-channel-D_jXxXQj.js";import{n as createBrowserRouteDispatcher,r as getMachineDisplayName,t as withTimeout}from"./with-timeout-Bwq-GyUQ.js";import{g as resolveNodeWindowsTaskName,h as resolveNodeSystemdServiceName,m as resolveNodeLaunchAgentLabel,s as formatNodeServiceDescription}from"./constants-BBbGeL3t.js";import{Bt as loadOrCreateDeviceIdentity,t as GatewayClient}from"./client-xfoidwPI.js";import{t as formatDocsLink}from"./links-BgWWaaOT.js";import{t as formatHelpExamples}from"./help-format-Qfk2vDNX.js";import{_ as analyzeArgvCommand,a as mergeExecApprovalsSocketDefaults,b as requestJsonlSocket,c as readExecApprovalsSnapshot,d as resolveExecApprovals,g as resolveSafeBins,h as evaluateShellAllowlist,l as recordAllowlistUse,m as evaluateExecAllowlist,n as addAllowlistEntry,p as saveExecApprovals,r as ensureExecApprovals,s as normalizeExecApprovals,u as requiresExecApproval}from"./exec-approvals-BpVPDVtV.js";import{r as startBrowserControlServiceFromConfig,t as createBrowserControlContext}from"./control-service-BbsswoMy.js";import{t as ensureBuilderForceAgentsCliOnPath}from"./path-env-Cy9l1Ba9.js";import"./runtime-guard-DhksRHci.js";import{c as buildNodeServiceEnvironment,g as resolveNodeProgramArguments,o as resolveGatewayDevMode,p as resolvePreferredNodePath,r as isGatewayDaemonRuntime,s as emitNodeRuntimeWarning,t as DEFAULT_GATEWAY_DAEMON_RUNTIME}from"./daemon-runtime-CtOr1ncS.js";import"./systemd-BG3_QT6W.js";import{s as resolveGatewayLogPaths}from"./service-D-NLDyK3.js";import{S as installDaemonServiceAndEmit,_ as resolveRuntimeStatusColor,b as buildDaemonServiceSnapshot,i as runServiceUninstall,r as runServiceStop,t as runServiceRestart,u as createCliStatusTextStyles,x as createDaemonActionContext,y as formatRuntimeStatus}from"./lifecycle-core-Dwb4gHjZ.js";import"./diagnostics-DCjg0nBH.js";import{t as parsePort}from"./parse-port-nw1R44xn.js";import{t as resolveNodeService}from"./node-service-DZg9i98f.js";import{n as validateSystemRunCommandConsistency}from"./system-run-command-B2_VsnKm.js";import fs from"node:fs";import path from"node:path";import crypto from"node:crypto";import fs$1 from"node:fs/promises";import{spawn}from"node:child_process";function resolveNodeHostConfigPath(){return path.join(resolveStateDir(),`node.json`)}function normalizeConfig(config){let base={version:1,nodeId:``,token:config?.token,displayName:config?.displayName,gateway:config?.gateway};return config?.version===1&&typeof config.nodeId==`string`&&(base.nodeId=config.nodeId.trim()),base.nodeId||=crypto.randomUUID(),base}async function loadNodeHostConfig(){let filePath=resolveNodeHostConfigPath();try{let raw=await fs$1.readFile(filePath,`utf8`);return normalizeConfig(JSON.parse(raw))}catch{return null}}async function saveNodeHostConfig(config){let filePath=resolveNodeHostConfigPath();await fs$1.mkdir(path.dirname(filePath),{recursive:!0});let payload=JSON.stringify(config,null,2);await fs$1.writeFile(filePath,`${payload}\n`,{mode:384});try{await fs$1.chmod(filePath,384)}catch{}}async function ensureNodeHostConfig(){let normalized=normalizeConfig(await loadNodeHostConfig());return await saveNodeHostConfig(normalized),normalized}async function requestExecHostViaSocket(params){let{socketPath,token,request}=params;if(!socketPath||!token)return null;let timeoutMs=params.timeoutMs??2e4,requestJson=JSON.stringify(request),nonce=crypto.randomBytes(16).toString(`hex`),ts=Date.now(),hmac=crypto.createHmac(`sha256`,token).update(`${nonce}:${ts}:${requestJson}`).digest(`hex`);return await requestJsonlSocket({socketPath,payload:JSON.stringify({type:`exec`,id:crypto.randomUUID(),nonce,ts,hmac,requestJson}),timeoutMs,accept:value=>{let msg=value;if(msg?.type===`exec-res`)return msg.ok===!0&&msg.payload?{ok:!0,payload:msg.payload}:msg.ok===!1&&msg.error?{ok:!1,error:msg.error}:null}})}const BROWSER_PROXY_MAX_FILE_BYTES=10*1024*1024;function normalizeProfileAllowlist(raw){return Array.isArray(raw)?raw.map(entry=>entry.trim()).filter(Boolean):[]}function resolveBrowserProxyConfig(){let proxy=loadConfig().nodeHost?.browserProxy,allowProfiles=normalizeProfileAllowlist(proxy?.allowProfiles);return{enabled:proxy?.enabled!==!1,allowProfiles}}let browserControlReady=null;async function ensureBrowserControlService(){return browserControlReady||(browserControlReady=(async()=>{let cfg=loadConfig();if(!resolveBrowserConfig(cfg.browser,cfg).enabled||!await startBrowserControlServiceFromConfig())throw Error(`browser control disabled`)})(),browserControlReady)}function isProfileAllowed(params){let{allowProfiles,profile}=params;return allowProfiles.length?profile?allowProfiles.includes(profile.trim()):!1:!0}function collectBrowserProxyPaths(payload){let paths=new Set,obj=typeof payload==`object`&&payload?payload:null;if(!obj)return[];typeof obj.path==`string`&&obj.path.trim()&&paths.add(obj.path.trim()),typeof obj.imagePath==`string`&&obj.imagePath.trim()&&paths.add(obj.imagePath.trim());let download=obj.download;if(download&&typeof download==`object`){let dlPath=download.path;typeof dlPath==`string`&&dlPath.trim()&&paths.add(dlPath.trim())}return[...paths]}async function readBrowserProxyFile(filePath){let stat=await fs$1.stat(filePath).catch(()=>null);if(!stat||!stat.isFile())return null;if(stat.size>BROWSER_PROXY_MAX_FILE_BYTES)throw Error(`browser proxy file exceeds ${Math.round(BROWSER_PROXY_MAX_FILE_BYTES/(1024*1024))}MB`);let buffer=await fs$1.readFile(filePath),mimeType=await detectMime({buffer,filePath});return{path:filePath,base64:buffer.toString(`base64`),mimeType}}function decodeParams$1(raw){if(!raw)throw Error(`INVALID_REQUEST: paramsJSON required`);return JSON.parse(raw)}async function runBrowserProxyCommand(paramsJSON){let params=decodeParams$1(paramsJSON),pathValue=typeof params.path==`string`?params.path.trim():``;if(!pathValue)throw Error(`INVALID_REQUEST: path required`);let proxyConfig=resolveBrowserProxyConfig();if(!proxyConfig.enabled)throw Error(`UNAVAILABLE: node browser proxy disabled`);await ensureBrowserControlService();let cfg=loadConfig(),resolved=resolveBrowserConfig(cfg.browser,cfg),requestedProfile=typeof params.profile==`string`?params.profile.trim():``,allowedProfiles=proxyConfig.allowProfiles;if(allowedProfiles.length>0){if(pathValue!==`/profiles`){if(!isProfileAllowed({allowProfiles:allowedProfiles,profile:requestedProfile||resolved.defaultProfile}))throw Error(`INVALID_REQUEST: browser profile not allowed`)}else if(requestedProfile&&!isProfileAllowed({allowProfiles:allowedProfiles,profile:requestedProfile}))throw Error(`INVALID_REQUEST: browser profile not allowed`)}let method=typeof params.method==`string`?params.method.toUpperCase():`GET`,path=pathValue.startsWith(`/`)?pathValue:`/${pathValue}`,body=params.body,query={};requestedProfile&&(query.profile=requestedProfile);let rawQuery=params.query??{};for(let[key,value]of Object.entries(rawQuery))value!=null&&(query[key]=typeof value==`string`?value:String(value));let dispatcher=createBrowserRouteDispatcher(createBrowserControlContext()),response=await withTimeout(signal=>dispatcher.dispatch({method:method===`DELETE`?`DELETE`:method===`POST`?`POST`:`GET`,path,query,body,signal}),params.timeoutMs,`browser proxy request`);if(response.status>=400){let message=response.body&&typeof response.body==`object`&&`error`in response.body?String(response.body.error):`HTTP ${response.status}`;throw Error(message)}let result=response.body;if(allowedProfiles.length>0&&path===`/profiles`){let obj=typeof result==`object`&&result?result:{};obj.profiles=(Array.isArray(obj.profiles)?obj.profiles:[]).filter(entry=>{if(!entry||typeof entry!=`object`)return!1;let name=entry.name;return typeof name==`string`&&allowedProfiles.includes(name)})}let files,paths=collectBrowserProxyPaths(result);if(paths.length>0){let loaded=await Promise.all(paths.map(async p=>{try{let file=await readBrowserProxyFile(p);if(!file)throw Error(`file not found`);return file}catch(err){throw Error(`browser proxy file read failed for ${p}: ${String(err)}`,{cause:err})}}));loaded.length>0&&(files=loaded)}let payload=files?{result,files}:{result};return JSON.stringify(payload)}const OUTPUT_CAP=2e5,execHostEnforced=process.env.BUILDERFORCE_AGENTS_NODE_EXEC_HOST?.trim().toLowerCase()===`app`,execHostFallbackAllowed=process.env.BUILDERFORCE_AGENTS_NODE_EXEC_FALLBACK?.trim().toLowerCase()!==`0`,blockedEnvKeys=new Set([`NODE_OPTIONS`,`PYTHONHOME`,`PYTHONPATH`,`PERL5LIB`,`PERL5OPT`,`RUBYOPT`]),blockedEnvPrefixes=[`DYLD_`,`LD_`];function resolveExecSecurity(value){return value===`deny`||value===`allowlist`||value===`full`?value:`allowlist`}function isCmdExeInvocation(argv){let token=argv[0]?.trim();if(!token)return!1;let base=path.win32.basename(token).toLowerCase();return base===`cmd.exe`||base===`cmd`}function resolveExecAsk(value){return value===`off`||value===`on-miss`||value===`always`?value:`on-miss`}function sanitizeEnv(overrides){if(!overrides)return;let merged={...process.env};for(let[rawKey,value]of Object.entries(overrides)){let key=rawKey.trim();if(!key)continue;let upper=key.toUpperCase();upper!==`PATH`&&(blockedEnvKeys.has(upper)||blockedEnvPrefixes.some(prefix=>upper.startsWith(prefix))||(merged[key]=value))}return merged}function truncateOutput(raw,maxChars){return raw.length<=maxChars?{text:raw,truncated:!1}:{text:`... (truncated) ${raw.slice(raw.length-maxChars)}`,truncated:!0}}function redactExecApprovals(file){let socketPath=file.socket?.path?.trim();return{...file,socket:socketPath?{path:socketPath}:void 0}}function requireExecApprovalsBaseHash(params,snapshot){if(!snapshot.exists)return;if(!snapshot.hash)throw Error(`INVALID_REQUEST: exec approvals base hash unavailable; reload and retry`);let baseHash=typeof params.baseHash==`string`?params.baseHash.trim():``;if(!baseHash)throw Error(`INVALID_REQUEST: exec approvals base hash required; reload and retry`);if(baseHash!==snapshot.hash)throw Error(`INVALID_REQUEST: exec approvals changed; reload and retry`)}async function runCommand(argv,cwd,env,timeoutMs){return await new Promise(resolve=>{let stdout=``,stderr=``,outputLen=0,truncated=!1,timedOut=!1,settled=!1,child=spawn(argv[0],argv.slice(1),{cwd,env,stdio:[`ignore`,`pipe`,`pipe`],windowsHide:!0}),onChunk=(chunk,target)=>{if(outputLen>=OUTPUT_CAP){truncated=!0;return}let remaining=OUTPUT_CAP-outputLen,slice=chunk.length>remaining?chunk.subarray(0,remaining):chunk,str=slice.toString(`utf8`);outputLen+=slice.length,target===`stdout`?stdout+=str:stderr+=str,chunk.length>remaining&&(truncated=!0)};child.stdout?.on(`data`,chunk=>onChunk(chunk,`stdout`)),child.stderr?.on(`data`,chunk=>onChunk(chunk,`stderr`));let timer;timeoutMs&&timeoutMs>0&&(timer=setTimeout(()=>{timedOut=!0;try{child.kill(`SIGKILL`)}catch{}},timeoutMs));let finalize=(exitCode,error)=>{settled||(settled=!0,timer&&clearTimeout(timer),resolve({exitCode,timedOut,success:exitCode===0&&!timedOut&&!error,stdout,stderr,error:error??null,truncated}))};child.on(`error`,err=>{finalize(void 0,err.message)}),child.on(`exit`,code=>{finalize(code===null?void 0:code,null)})})}function resolveEnvPath(env){return(env?.PATH??env?.Path??process.env.PATH??process.env.Path??`/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin`).split(path.delimiter).filter(Boolean)}function resolveExecutable(bin,env){if(bin.includes(`/`)||bin.includes(`\\`))return null;let extensions=process.platform===`win32`?(process.env.PATHEXT??process.env.PathExt??`.EXE;.CMD;.BAT;.COM`).split(`;`).map(ext=>ext.toLowerCase()):[``];for(let dir of resolveEnvPath(env))for(let ext of extensions){let candidate=path.join(dir,bin+ext);if(fs.existsSync(candidate))return candidate}return null}async function handleSystemWhich(params,env){let bins=params.bins.map(bin=>bin.trim()).filter(Boolean),found={};for(let bin of bins){let path=resolveExecutable(bin,env);path&&(found[bin]=path)}return{bins:found}}function buildExecEventPayload(payload){if(!payload.output)return payload;let trimmed=payload.output.trim();if(!trimmed)return payload;let{text}=truncateOutput(trimmed,2e4);return{...payload,output:text}}async function sendExecFinishedEvent(params){let combined=[params.result.stdout,params.result.stderr,params.result.error].filter(Boolean).join(`
|
|
1
|
+
import{d as resolveIsNixMode,g as resolveStateDir}from"./paths-5FcIFMsj.js";import{B as theme,R as colorize}from"./utils-DbaBVFaK.js";import"./session-key-EoB0qaG9.js";import"./builderforce-root-D64_sXEi.js";import{i as defaultRuntime}from"./subsystem-B3TqcCrZ.js";import"./registry-TdK-aV05.js";import"./logger-Bch0bx9c.js";import"./exec-DdcIjeyn.js";import{r as resolveAgentConfig}from"./agent-scope-DPtjOxzp.js";import"./src-CA0fU67C.js";import"./model-selection-DG9J_VTz.js";import{t as formatCliCommand}from"./command-format-D806O2pt.js";import"./env-file-D1MDi-AM.js";import"./boolean-Cnh1KNl1.js";import"./env-BIdU5BAp.js";import"./src-DTFqOIQD.js";import{U as VERSION,r as loadConfig}from"./io-BLBq4T2o.js";import"./manifest-registry-BJCfNV1a.js";import"./config-BgV_FYSq.js";import"./chrome-DXt86tmV.js";import"./tailscale-DLkpGquM.js";import"./auth-lebUHrkd.js";import{i as resolveBrowserConfig}from"./server-context-CQ2v4BAx.js";import"./routes-DZntyPY6.js";import"./redact-BHdfp2MZ.js";import"./errors-B1MIg3g-.js";import"./paths-cR8ct-Y3.js";import"./ssrf-p9k-iapc.js";import{c as detectMime}from"./image-ops-C8IUQKjn.js";import"./store-CmHBQ-yX.js";import"./ports-DgmEDNOm.js";import"./trash-DD2Hc5oq.js";import{h as GATEWAY_CLIENT_NAMES,m as GATEWAY_CLIENT_MODES}from"./message-channel-D_jXxXQj.js";import{n as createBrowserRouteDispatcher,r as getMachineDisplayName,t as withTimeout}from"./with-timeout-GDLpcjW7.js";import{g as resolveNodeWindowsTaskName,h as resolveNodeSystemdServiceName,m as resolveNodeLaunchAgentLabel,s as formatNodeServiceDescription}from"./constants-BBbGeL3t.js";import{Bt as loadOrCreateDeviceIdentity,t as GatewayClient}from"./client-xfoidwPI.js";import{t as formatDocsLink}from"./links-BgWWaaOT.js";import{t as formatHelpExamples}from"./help-format-Qfk2vDNX.js";import{_ as analyzeArgvCommand,a as mergeExecApprovalsSocketDefaults,b as requestJsonlSocket,c as readExecApprovalsSnapshot,d as resolveExecApprovals,g as resolveSafeBins,h as evaluateShellAllowlist,l as recordAllowlistUse,m as evaluateExecAllowlist,n as addAllowlistEntry,p as saveExecApprovals,r as ensureExecApprovals,s as normalizeExecApprovals,u as requiresExecApproval}from"./exec-approvals-BpVPDVtV.js";import{r as startBrowserControlServiceFromConfig,t as createBrowserControlContext}from"./control-service-y3GYvIBg.js";import{t as ensureBuilderForceAgentsCliOnPath}from"./path-env-Cy9l1Ba9.js";import"./runtime-guard-DhksRHci.js";import{c as buildNodeServiceEnvironment,g as resolveNodeProgramArguments,o as resolveGatewayDevMode,p as resolvePreferredNodePath,r as isGatewayDaemonRuntime,s as emitNodeRuntimeWarning,t as DEFAULT_GATEWAY_DAEMON_RUNTIME}from"./daemon-runtime-9XitJmIL.js";import"./systemd-BG3_QT6W.js";import{s as resolveGatewayLogPaths}from"./service-D-NLDyK3.js";import{S as installDaemonServiceAndEmit,_ as resolveRuntimeStatusColor,b as buildDaemonServiceSnapshot,i as runServiceUninstall,r as runServiceStop,t as runServiceRestart,u as createCliStatusTextStyles,x as createDaemonActionContext,y as formatRuntimeStatus}from"./lifecycle-core-uxjxTzFv.js";import"./diagnostics-DCjg0nBH.js";import{t as parsePort}from"./parse-port-nw1R44xn.js";import{t as resolveNodeService}from"./node-service-DZg9i98f.js";import{n as validateSystemRunCommandConsistency}from"./system-run-command-B2_VsnKm.js";import fs from"node:fs";import path from"node:path";import crypto from"node:crypto";import fs$1 from"node:fs/promises";import{spawn}from"node:child_process";function resolveNodeHostConfigPath(){return path.join(resolveStateDir(),`node.json`)}function normalizeConfig(config){let base={version:1,nodeId:``,token:config?.token,displayName:config?.displayName,gateway:config?.gateway};return config?.version===1&&typeof config.nodeId==`string`&&(base.nodeId=config.nodeId.trim()),base.nodeId||=crypto.randomUUID(),base}async function loadNodeHostConfig(){let filePath=resolveNodeHostConfigPath();try{let raw=await fs$1.readFile(filePath,`utf8`);return normalizeConfig(JSON.parse(raw))}catch{return null}}async function saveNodeHostConfig(config){let filePath=resolveNodeHostConfigPath();await fs$1.mkdir(path.dirname(filePath),{recursive:!0});let payload=JSON.stringify(config,null,2);await fs$1.writeFile(filePath,`${payload}\n`,{mode:384});try{await fs$1.chmod(filePath,384)}catch{}}async function ensureNodeHostConfig(){let normalized=normalizeConfig(await loadNodeHostConfig());return await saveNodeHostConfig(normalized),normalized}async function requestExecHostViaSocket(params){let{socketPath,token,request}=params;if(!socketPath||!token)return null;let timeoutMs=params.timeoutMs??2e4,requestJson=JSON.stringify(request),nonce=crypto.randomBytes(16).toString(`hex`),ts=Date.now(),hmac=crypto.createHmac(`sha256`,token).update(`${nonce}:${ts}:${requestJson}`).digest(`hex`);return await requestJsonlSocket({socketPath,payload:JSON.stringify({type:`exec`,id:crypto.randomUUID(),nonce,ts,hmac,requestJson}),timeoutMs,accept:value=>{let msg=value;if(msg?.type===`exec-res`)return msg.ok===!0&&msg.payload?{ok:!0,payload:msg.payload}:msg.ok===!1&&msg.error?{ok:!1,error:msg.error}:null}})}const BROWSER_PROXY_MAX_FILE_BYTES=10*1024*1024;function normalizeProfileAllowlist(raw){return Array.isArray(raw)?raw.map(entry=>entry.trim()).filter(Boolean):[]}function resolveBrowserProxyConfig(){let proxy=loadConfig().nodeHost?.browserProxy,allowProfiles=normalizeProfileAllowlist(proxy?.allowProfiles);return{enabled:proxy?.enabled!==!1,allowProfiles}}let browserControlReady=null;async function ensureBrowserControlService(){return browserControlReady||(browserControlReady=(async()=>{let cfg=loadConfig();if(!resolveBrowserConfig(cfg.browser,cfg).enabled||!await startBrowserControlServiceFromConfig())throw Error(`browser control disabled`)})(),browserControlReady)}function isProfileAllowed(params){let{allowProfiles,profile}=params;return allowProfiles.length?profile?allowProfiles.includes(profile.trim()):!1:!0}function collectBrowserProxyPaths(payload){let paths=new Set,obj=typeof payload==`object`&&payload?payload:null;if(!obj)return[];typeof obj.path==`string`&&obj.path.trim()&&paths.add(obj.path.trim()),typeof obj.imagePath==`string`&&obj.imagePath.trim()&&paths.add(obj.imagePath.trim());let download=obj.download;if(download&&typeof download==`object`){let dlPath=download.path;typeof dlPath==`string`&&dlPath.trim()&&paths.add(dlPath.trim())}return[...paths]}async function readBrowserProxyFile(filePath){let stat=await fs$1.stat(filePath).catch(()=>null);if(!stat||!stat.isFile())return null;if(stat.size>BROWSER_PROXY_MAX_FILE_BYTES)throw Error(`browser proxy file exceeds ${Math.round(BROWSER_PROXY_MAX_FILE_BYTES/(1024*1024))}MB`);let buffer=await fs$1.readFile(filePath),mimeType=await detectMime({buffer,filePath});return{path:filePath,base64:buffer.toString(`base64`),mimeType}}function decodeParams$1(raw){if(!raw)throw Error(`INVALID_REQUEST: paramsJSON required`);return JSON.parse(raw)}async function runBrowserProxyCommand(paramsJSON){let params=decodeParams$1(paramsJSON),pathValue=typeof params.path==`string`?params.path.trim():``;if(!pathValue)throw Error(`INVALID_REQUEST: path required`);let proxyConfig=resolveBrowserProxyConfig();if(!proxyConfig.enabled)throw Error(`UNAVAILABLE: node browser proxy disabled`);await ensureBrowserControlService();let cfg=loadConfig(),resolved=resolveBrowserConfig(cfg.browser,cfg),requestedProfile=typeof params.profile==`string`?params.profile.trim():``,allowedProfiles=proxyConfig.allowProfiles;if(allowedProfiles.length>0){if(pathValue!==`/profiles`){if(!isProfileAllowed({allowProfiles:allowedProfiles,profile:requestedProfile||resolved.defaultProfile}))throw Error(`INVALID_REQUEST: browser profile not allowed`)}else if(requestedProfile&&!isProfileAllowed({allowProfiles:allowedProfiles,profile:requestedProfile}))throw Error(`INVALID_REQUEST: browser profile not allowed`)}let method=typeof params.method==`string`?params.method.toUpperCase():`GET`,path=pathValue.startsWith(`/`)?pathValue:`/${pathValue}`,body=params.body,query={};requestedProfile&&(query.profile=requestedProfile);let rawQuery=params.query??{};for(let[key,value]of Object.entries(rawQuery))value!=null&&(query[key]=typeof value==`string`?value:String(value));let dispatcher=createBrowserRouteDispatcher(createBrowserControlContext()),response=await withTimeout(signal=>dispatcher.dispatch({method:method===`DELETE`?`DELETE`:method===`POST`?`POST`:`GET`,path,query,body,signal}),params.timeoutMs,`browser proxy request`);if(response.status>=400){let message=response.body&&typeof response.body==`object`&&`error`in response.body?String(response.body.error):`HTTP ${response.status}`;throw Error(message)}let result=response.body;if(allowedProfiles.length>0&&path===`/profiles`){let obj=typeof result==`object`&&result?result:{};obj.profiles=(Array.isArray(obj.profiles)?obj.profiles:[]).filter(entry=>{if(!entry||typeof entry!=`object`)return!1;let name=entry.name;return typeof name==`string`&&allowedProfiles.includes(name)})}let files,paths=collectBrowserProxyPaths(result);if(paths.length>0){let loaded=await Promise.all(paths.map(async p=>{try{let file=await readBrowserProxyFile(p);if(!file)throw Error(`file not found`);return file}catch(err){throw Error(`browser proxy file read failed for ${p}: ${String(err)}`,{cause:err})}}));loaded.length>0&&(files=loaded)}let payload=files?{result,files}:{result};return JSON.stringify(payload)}const OUTPUT_CAP=2e5,execHostEnforced=process.env.BUILDERFORCE_AGENTS_NODE_EXEC_HOST?.trim().toLowerCase()===`app`,execHostFallbackAllowed=process.env.BUILDERFORCE_AGENTS_NODE_EXEC_FALLBACK?.trim().toLowerCase()!==`0`,blockedEnvKeys=new Set([`NODE_OPTIONS`,`PYTHONHOME`,`PYTHONPATH`,`PERL5LIB`,`PERL5OPT`,`RUBYOPT`]),blockedEnvPrefixes=[`DYLD_`,`LD_`];function resolveExecSecurity(value){return value===`deny`||value===`allowlist`||value===`full`?value:`allowlist`}function isCmdExeInvocation(argv){let token=argv[0]?.trim();if(!token)return!1;let base=path.win32.basename(token).toLowerCase();return base===`cmd.exe`||base===`cmd`}function resolveExecAsk(value){return value===`off`||value===`on-miss`||value===`always`?value:`on-miss`}function sanitizeEnv(overrides){if(!overrides)return;let merged={...process.env};for(let[rawKey,value]of Object.entries(overrides)){let key=rawKey.trim();if(!key)continue;let upper=key.toUpperCase();upper!==`PATH`&&(blockedEnvKeys.has(upper)||blockedEnvPrefixes.some(prefix=>upper.startsWith(prefix))||(merged[key]=value))}return merged}function truncateOutput(raw,maxChars){return raw.length<=maxChars?{text:raw,truncated:!1}:{text:`... (truncated) ${raw.slice(raw.length-maxChars)}`,truncated:!0}}function redactExecApprovals(file){let socketPath=file.socket?.path?.trim();return{...file,socket:socketPath?{path:socketPath}:void 0}}function requireExecApprovalsBaseHash(params,snapshot){if(!snapshot.exists)return;if(!snapshot.hash)throw Error(`INVALID_REQUEST: exec approvals base hash unavailable; reload and retry`);let baseHash=typeof params.baseHash==`string`?params.baseHash.trim():``;if(!baseHash)throw Error(`INVALID_REQUEST: exec approvals base hash required; reload and retry`);if(baseHash!==snapshot.hash)throw Error(`INVALID_REQUEST: exec approvals changed; reload and retry`)}async function runCommand(argv,cwd,env,timeoutMs){return await new Promise(resolve=>{let stdout=``,stderr=``,outputLen=0,truncated=!1,timedOut=!1,settled=!1,child=spawn(argv[0],argv.slice(1),{cwd,env,stdio:[`ignore`,`pipe`,`pipe`],windowsHide:!0}),onChunk=(chunk,target)=>{if(outputLen>=OUTPUT_CAP){truncated=!0;return}let remaining=OUTPUT_CAP-outputLen,slice=chunk.length>remaining?chunk.subarray(0,remaining):chunk,str=slice.toString(`utf8`);outputLen+=slice.length,target===`stdout`?stdout+=str:stderr+=str,chunk.length>remaining&&(truncated=!0)};child.stdout?.on(`data`,chunk=>onChunk(chunk,`stdout`)),child.stderr?.on(`data`,chunk=>onChunk(chunk,`stderr`));let timer;timeoutMs&&timeoutMs>0&&(timer=setTimeout(()=>{timedOut=!0;try{child.kill(`SIGKILL`)}catch{}},timeoutMs));let finalize=(exitCode,error)=>{settled||(settled=!0,timer&&clearTimeout(timer),resolve({exitCode,timedOut,success:exitCode===0&&!timedOut&&!error,stdout,stderr,error:error??null,truncated}))};child.on(`error`,err=>{finalize(void 0,err.message)}),child.on(`exit`,code=>{finalize(code===null?void 0:code,null)})})}function resolveEnvPath(env){return(env?.PATH??env?.Path??process.env.PATH??process.env.Path??`/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin`).split(path.delimiter).filter(Boolean)}function resolveExecutable(bin,env){if(bin.includes(`/`)||bin.includes(`\\`))return null;let extensions=process.platform===`win32`?(process.env.PATHEXT??process.env.PathExt??`.EXE;.CMD;.BAT;.COM`).split(`;`).map(ext=>ext.toLowerCase()):[``];for(let dir of resolveEnvPath(env))for(let ext of extensions){let candidate=path.join(dir,bin+ext);if(fs.existsSync(candidate))return candidate}return null}async function handleSystemWhich(params,env){let bins=params.bins.map(bin=>bin.trim()).filter(Boolean),found={};for(let bin of bins){let path=resolveExecutable(bin,env);path&&(found[bin]=path)}return{bins:found}}function buildExecEventPayload(payload){if(!payload.output)return payload;let trimmed=payload.output.trim();if(!trimmed)return payload;let{text}=truncateOutput(trimmed,2e4);return{...payload,output:text}}async function sendExecFinishedEvent(params){let combined=[params.result.stdout,params.result.stderr,params.result.error].filter(Boolean).join(`
|
|
2
2
|
`);await sendNodeEvent(params.client,`exec.finished`,buildExecEventPayload({sessionKey:params.sessionKey,runId:params.runId,host:`node`,command:params.cmdText,exitCode:params.result.exitCode??void 0,timedOut:params.result.timedOut,success:params.result.success,output:combined}))}async function runViaMacAppExecHost(params){let{approvals,request}=params;return await requestExecHostViaSocket({socketPath:approvals.socketPath,token:approvals.token,request})}async function sendJsonPayloadResult(client,frame,payload){await sendInvokeResult(client,frame,{ok:!0,payloadJSON:JSON.stringify(payload)})}async function sendRawPayloadResult(client,frame,payloadJSON){await sendInvokeResult(client,frame,{ok:!0,payloadJSON})}async function sendErrorResult(client,frame,code,message){await sendInvokeResult(client,frame,{ok:!1,error:{code,message}})}async function sendInvalidRequestResult(client,frame,err){await sendErrorResult(client,frame,`INVALID_REQUEST`,String(err))}async function handleInvoke(frame,client,skillBins){let command=String(frame.command??``);if(command===`system.execApprovals.get`){try{ensureExecApprovals();let snapshot=readExecApprovalsSnapshot();await sendJsonPayloadResult(client,frame,{path:snapshot.path,exists:snapshot.exists,hash:snapshot.hash,file:redactExecApprovals(snapshot.file)})}catch(err){let message=String(err);await sendErrorResult(client,frame,message.toLowerCase().includes(`timed out`)?`TIMEOUT`:`INVALID_REQUEST`,message)}return}if(command===`system.execApprovals.set`){try{let params=decodeParams(frame.paramsJSON);if(!params.file||typeof params.file!=`object`)throw Error(`INVALID_REQUEST: exec approvals file required`);ensureExecApprovals();let snapshot=readExecApprovalsSnapshot();requireExecApprovalsBaseHash(params,snapshot),saveExecApprovals(mergeExecApprovalsSocketDefaults({normalized:normalizeExecApprovals(params.file),current:snapshot.file}));let nextSnapshot=readExecApprovalsSnapshot();await sendJsonPayloadResult(client,frame,{path:nextSnapshot.path,exists:nextSnapshot.exists,hash:nextSnapshot.hash,file:redactExecApprovals(nextSnapshot.file)})}catch(err){await sendInvalidRequestResult(client,frame,err)}return}if(command===`system.which`){try{let params=decodeParams(frame.paramsJSON);if(!Array.isArray(params.bins))throw Error(`INVALID_REQUEST: bins required`);await sendJsonPayloadResult(client,frame,await handleSystemWhich(params,sanitizeEnv(void 0)))}catch(err){await sendInvalidRequestResult(client,frame,err)}return}if(command===`browser.proxy`){try{await sendRawPayloadResult(client,frame,await runBrowserProxyCommand(frame.paramsJSON))}catch(err){await sendInvalidRequestResult(client,frame,err)}return}if(command!==`system.run`){await sendErrorResult(client,frame,`UNAVAILABLE`,`command not supported`);return}let params;try{params=decodeParams(frame.paramsJSON)}catch(err){await sendInvalidRequestResult(client,frame,err);return}if(!Array.isArray(params.command)||params.command.length===0){await sendErrorResult(client,frame,`INVALID_REQUEST`,`command required`);return}let argv=params.command.map(item=>String(item)),rawCommand=typeof params.rawCommand==`string`?params.rawCommand.trim():``,consistency=validateSystemRunCommandConsistency({argv,rawCommand:rawCommand||null});if(!consistency.ok){await sendErrorResult(client,frame,`INVALID_REQUEST`,consistency.message);return}let shellCommand=consistency.shellCommand,cmdText=consistency.cmdText,agentId=params.agentId?.trim()||void 0,cfg=loadConfig(),agentExec=agentId?resolveAgentConfig(cfg,agentId)?.tools?.exec:void 0,approvals=resolveExecApprovals(agentId,{security:resolveExecSecurity(agentExec?.security??cfg.tools?.exec?.security),ask:resolveExecAsk(agentExec?.ask??cfg.tools?.exec?.ask)}),security=approvals.agent.security,ask=approvals.agent.ask,autoAllowSkills=approvals.agent.autoAllowSkills,sessionKey=params.sessionKey?.trim()||`node`,runId=params.runId?.trim()||crypto.randomUUID(),env=sanitizeEnv(params.env??void 0),safeBins=resolveSafeBins(agentExec?.safeBins??cfg.tools?.exec?.safeBins),bins=autoAllowSkills?await skillBins.current():new Set,analysisOk=!1,allowlistMatches=[],allowlistSatisfied=!1,segments=[];if(shellCommand){let allowlistEval=evaluateShellAllowlist({command:shellCommand,allowlist:approvals.allowlist,safeBins,cwd:params.cwd??void 0,env,skillBins:bins,autoAllowSkills,platform:process.platform});analysisOk=allowlistEval.analysisOk,allowlistMatches=allowlistEval.allowlistMatches,allowlistSatisfied=security===`allowlist`&&analysisOk?allowlistEval.allowlistSatisfied:!1,segments=allowlistEval.segments}else{let analysis=analyzeArgvCommand({argv,cwd:params.cwd??void 0,env}),allowlistEval=evaluateExecAllowlist({analysis,allowlist:approvals.allowlist,safeBins,cwd:params.cwd??void 0,skillBins:bins,autoAllowSkills});analysisOk=analysis.ok,allowlistMatches=allowlistEval.allowlistMatches,allowlistSatisfied=security===`allowlist`&&analysisOk?allowlistEval.allowlistSatisfied:!1,segments=analysis.segments}let isWindows=process.platform===`win32`,cmdInvocation=isCmdExeInvocation(shellCommand?segments[0]?.argv??[]:argv);if(security===`allowlist`&&isWindows&&cmdInvocation&&(analysisOk=!1,allowlistSatisfied=!1),process.platform===`darwin`){let approvalDecision=params.approvalDecision===`allow-once`||params.approvalDecision===`allow-always`?params.approvalDecision:null,response=await runViaMacAppExecHost({approvals,request:{command:argv,rawCommand:rawCommand||shellCommand||null,cwd:params.cwd??null,env:params.env??null,timeoutMs:params.timeoutMs??null,needsScreenRecording:params.needsScreenRecording??null,agentId:agentId??null,sessionKey:sessionKey??null,approvalDecision}});if(!response){if(execHostEnforced||!execHostFallbackAllowed){await sendNodeEvent(client,`exec.denied`,buildExecEventPayload({sessionKey,runId,host:`node`,command:cmdText,reason:`companion-unavailable`})),await sendInvokeResult(client,frame,{ok:!1,error:{code:`UNAVAILABLE`,message:`COMPANION_APP_UNAVAILABLE: macOS app exec host unreachable`}});return}}else if(response.ok){let result=response.payload;await sendExecFinishedEvent({client,sessionKey,runId,cmdText,result}),await sendInvokeResult(client,frame,{ok:!0,payloadJSON:JSON.stringify(result)});return}else{await sendNodeEvent(client,`exec.denied`,buildExecEventPayload({sessionKey,runId,host:`node`,command:cmdText,reason:response.error.reason??`approval-required`})),await sendInvokeResult(client,frame,{ok:!1,error:{code:`UNAVAILABLE`,message:response.error.message}});return}}if(security===`deny`){await sendNodeEvent(client,`exec.denied`,buildExecEventPayload({sessionKey,runId,host:`node`,command:cmdText,reason:`security=deny`})),await sendInvokeResult(client,frame,{ok:!1,error:{code:`UNAVAILABLE`,message:`SYSTEM_RUN_DISABLED: security=deny`}});return}let requiresAsk=requiresExecApproval({ask,security,analysisOk,allowlistSatisfied}),approvalDecision=params.approvalDecision===`allow-once`||params.approvalDecision===`allow-always`?params.approvalDecision:null,approvedByAsk=approvalDecision!==null||params.approved===!0;if(requiresAsk&&!approvedByAsk){await sendNodeEvent(client,`exec.denied`,buildExecEventPayload({sessionKey,runId,host:`node`,command:cmdText,reason:`approval-required`})),await sendInvokeResult(client,frame,{ok:!1,error:{code:`UNAVAILABLE`,message:`SYSTEM_RUN_DENIED: approval required`}});return}if(approvalDecision===`allow-always`&&security===`allowlist`&&analysisOk)for(let segment of segments){let pattern=segment.resolution?.resolvedPath??``;pattern&&addAllowlistEntry(approvals.file,agentId,pattern)}if(security===`allowlist`&&(!analysisOk||!allowlistSatisfied)&&!approvedByAsk){await sendNodeEvent(client,`exec.denied`,buildExecEventPayload({sessionKey,runId,host:`node`,command:cmdText,reason:`allowlist-miss`})),await sendInvokeResult(client,frame,{ok:!1,error:{code:`UNAVAILABLE`,message:`SYSTEM_RUN_DENIED: allowlist miss`}});return}if(allowlistMatches.length>0){let seen=new Set;for(let match of allowlistMatches)!match?.pattern||seen.has(match.pattern)||(seen.add(match.pattern),recordAllowlistUse(approvals.file,agentId,match,cmdText,segments[0]?.resolution?.resolvedPath))}if(params.needsScreenRecording===!0){await sendNodeEvent(client,`exec.denied`,buildExecEventPayload({sessionKey,runId,host:`node`,command:cmdText,reason:`permission:screenRecording`})),await sendInvokeResult(client,frame,{ok:!1,error:{code:`UNAVAILABLE`,message:`PERMISSION_MISSING: screenRecording`}});return}let execArgv=argv;security===`allowlist`&&isWindows&&!approvedByAsk&&shellCommand&&analysisOk&&allowlistSatisfied&&segments.length===1&&segments[0]?.argv.length>0&&(execArgv=segments[0].argv);let result=await runCommand(execArgv,params.cwd?.trim()||void 0,env,params.timeoutMs??void 0);if(result.truncated){let suffix=`... (truncated)`;result.stderr.trim().length>0?result.stderr=`${result.stderr}\n${suffix}`:result.stdout=`${result.stdout}\n${suffix}`}await sendExecFinishedEvent({client,sessionKey,runId,cmdText,result}),await sendInvokeResult(client,frame,{ok:!0,payloadJSON:JSON.stringify({exitCode:result.exitCode,timedOut:result.timedOut,success:result.success,stdout:result.stdout,stderr:result.stderr,error:result.error??null})})}function decodeParams(raw){if(!raw)throw Error(`INVALID_REQUEST: paramsJSON required`);return JSON.parse(raw)}function coerceNodeInvokePayload(payload){if(!payload||typeof payload!=`object`)return null;let obj=payload,id=typeof obj.id==`string`?obj.id.trim():``,nodeId=typeof obj.nodeId==`string`?obj.nodeId.trim():``,command=typeof obj.command==`string`?obj.command.trim():``;return!id||!nodeId||!command?null:{id,nodeId,command,paramsJSON:typeof obj.paramsJSON==`string`?obj.paramsJSON:obj.params===void 0?null:JSON.stringify(obj.params),timeoutMs:typeof obj.timeoutMs==`number`?obj.timeoutMs:null,idempotencyKey:typeof obj.idempotencyKey==`string`?obj.idempotencyKey:null}}async function sendInvokeResult(client,frame,result){try{await client.request(`node.invoke.result`,buildNodeInvokeResultParams(frame,result))}catch{}}function buildNodeInvokeResultParams(frame,result){let params={id:frame.id,nodeId:frame.nodeId,ok:result.ok};return result.payload!==void 0&&(params.payload=result.payload),typeof result.payloadJSON==`string`&&(params.payloadJSON=result.payloadJSON),result.error&&(params.error=result.error),params}async function sendNodeEvent(client,event,payload){try{await client.request(`node.event`,{event,payloadJSON:payload?JSON.stringify(payload):null})}catch{}}const DEFAULT_NODE_PATH=`/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin`;var SkillBinsCache=class{constructor(fetch){this.bins=new Set,this.lastRefresh=0,this.ttlMs=9e4,this.fetch=fetch}async current(force=!1){return(force||Date.now()-this.lastRefresh>this.ttlMs)&&await this.refresh(),this.bins}async refresh(){try{let bins=await this.fetch();this.bins=new Set(bins),this.lastRefresh=Date.now()}catch{this.lastRefresh||(this.bins=new Set)}}};function ensureNodePathEnv(){ensureBuilderForceAgentsCliOnPath({pathEnv:process.env.PATH??``});let current=process.env.PATH??``;return current.trim()?current:(process.env.PATH=DEFAULT_NODE_PATH,DEFAULT_NODE_PATH)}async function runNodeHost(opts){let config=await ensureNodeHostConfig(),nodeId=opts.nodeId?.trim()||config.nodeId;nodeId!==config.nodeId&&(config.nodeId=nodeId);let displayName=opts.displayName?.trim()||config.displayName||await getMachineDisplayName();config.displayName=displayName;let gateway={host:opts.gatewayHost,port:opts.gatewayPort,tls:opts.gatewayTls??loadConfig().gateway?.tls?.enabled??!1,tlsFingerprint:opts.gatewayTlsFingerprint};config.gateway=gateway,await saveNodeHostConfig(config);let cfg=loadConfig(),resolvedBrowser=resolveBrowserConfig(cfg.browser,cfg),browserProxyEnabled=cfg.nodeHost?.browserProxy?.enabled!==!1&&resolvedBrowser.enabled,isRemoteMode=cfg.gateway?.mode===`remote`,token=process.env.BUILDERFORCE_AGENTS_GATEWAY_TOKEN?.trim()||(isRemoteMode?cfg.gateway?.remote?.token:cfg.gateway?.auth?.token),password=process.env.BUILDERFORCE_AGENTS_GATEWAY_PASSWORD?.trim()||(isRemoteMode?cfg.gateway?.remote?.password:cfg.gateway?.auth?.password),host=gateway.host??`127.0.0.1`,port=gateway.port??18789,url=`${gateway.tls?`wss`:`ws`}://${host}:${port}`,pathEnv=ensureNodePathEnv();console.log(`node host PATH: ${pathEnv}`);let client=new GatewayClient({url,token:token?.trim()||void 0,password:password?.trim()||void 0,instanceId:nodeId,clientName:GATEWAY_CLIENT_NAMES.NODE_HOST,clientDisplayName:displayName,clientVersion:VERSION,platform:process.platform,mode:GATEWAY_CLIENT_MODES.NODE,role:`node`,scopes:[],caps:[`system`,...browserProxyEnabled?[`browser`]:[]],commands:[`system.run`,`system.which`,`system.execApprovals.get`,`system.execApprovals.set`,...browserProxyEnabled?[`browser.proxy`]:[]],pathEnv,permissions:void 0,deviceIdentity:loadOrCreateDeviceIdentity(),tlsFingerprint:gateway.tlsFingerprint,onEvent:evt=>{if(evt.event!==`node.invoke.request`)return;let payload=coerceNodeInvokePayload(evt.payload);payload&&handleInvoke(payload,client,skillBins)},onConnectError:err=>{console.error(`node host gateway connect failed: ${err.message}`)},onClose:(code,reason)=>{console.error(`node host gateway closed (${code}): ${reason}`)}}),skillBins=new SkillBinsCache(async()=>{let res=await client.request(`skills.bins`,{});return Array.isArray(res?.bins)?res.bins.map(bin=>String(bin)):[]});client.start(),await new Promise(()=>{})}async function buildNodeInstallPlan(params){let devMode=params.devMode??resolveGatewayDevMode(),nodePath=params.nodePath??await resolvePreferredNodePath({env:params.env,runtime:params.runtime}),{programArguments,workingDirectory}=await resolveNodeProgramArguments({host:params.host,port:params.port,tls:params.tls,tlsFingerprint:params.tlsFingerprint,nodeId:params.nodeId,displayName:params.displayName,dev:devMode,runtime:params.runtime,nodePath});await emitNodeRuntimeWarning({env:params.env,runtime:params.runtime,nodeProgram:programArguments[0],warn:params.warn,title:`Node daemon runtime`});let environment=buildNodeServiceEnvironment({env:params.env});return{programArguments,workingDirectory,environment,description:formatNodeServiceDescription({version:environment.BUILDERFORCE_AGENTS_SERVICE_VERSION})}}const DEFAULT_NODE_DAEMON_RUNTIME=DEFAULT_GATEWAY_DAEMON_RUNTIME;function isNodeDaemonRuntime(value){return isGatewayDaemonRuntime(value)}function renderNodeServiceStartHints(){let base=[formatCliCommand(`builderforce node install`),formatCliCommand(`builderforce node start`)];switch(process.platform){case`darwin`:return[...base,`launchctl bootstrap gui/$UID ~/Library/LaunchAgents/${resolveNodeLaunchAgentLabel()}.plist`];case`linux`:return[...base,`systemctl --user start ${resolveNodeSystemdServiceName()}.service`];case`win32`:return[...base,`schtasks /Run /TN "${resolveNodeWindowsTaskName()}"`];default:return base}}function buildNodeRuntimeHints(env=process.env){if(process.platform===`darwin`){let logs=resolveGatewayLogPaths(env);return[`Launchd stdout (if installed): ${logs.stdoutPath}`,`Launchd stderr (if installed): ${logs.stderrPath}`]}return process.platform===`linux`?[`Logs: journalctl --user -u ${resolveNodeSystemdServiceName()}.service -n 200 --no-pager`]:process.platform===`win32`?[`Logs: schtasks /Query /TN "${resolveNodeWindowsTaskName()}" /V /FO LIST`]:[]}function resolveNodeDefaults(opts,config){let host=opts.host?.trim()||config?.gateway?.host||`127.0.0.1`,portOverride=parsePort(opts.port);return opts.port!==void 0&&portOverride===null?{host,port:null}:{host,port:portOverride??config?.gateway?.port??18789}}async function runNodeDaemonInstall(opts){let json=!!opts.json,{stdout,warnings,emit,fail}=createDaemonActionContext({action:`install`,json});if(resolveIsNixMode(process.env)){fail(`Nix mode detected; service install is disabled.`);return}let config=await loadNodeHostConfig(),{host,port}=resolveNodeDefaults(opts,config);if(!Number.isFinite(port??NaN)||(port??0)<=0){fail(`Invalid port`);return}let runtimeRaw=opts.runtime?String(opts.runtime):DEFAULT_NODE_DAEMON_RUNTIME;if(!isNodeDaemonRuntime(runtimeRaw)){fail(`Invalid --runtime (use "node" or "bun")`);return}let service=resolveNodeService(),loaded=!1;try{loaded=await service.isLoaded({env:process.env})}catch(err){fail(`Node service check failed: ${String(err)}`);return}if(loaded&&!opts.force){emit({ok:!0,result:`already-installed`,message:`Node service already ${service.loadedText}.`,service:buildDaemonServiceSnapshot(service,loaded),warnings:warnings.length?warnings:void 0}),json||(defaultRuntime.log(`Node service already ${service.loadedText}.`),defaultRuntime.log(`Reinstall with: ${formatCliCommand(`builderforce node install --force`)}`));return}let tlsFingerprint=opts.tlsFingerprint?.trim()||config?.gateway?.tlsFingerprint,tls=!!opts.tls||!!tlsFingerprint||!!config?.gateway?.tls,{programArguments,workingDirectory,environment,description}=await buildNodeInstallPlan({env:process.env,host,port:port??18789,tls,tlsFingerprint:tlsFingerprint||void 0,nodeId:opts.nodeId,displayName:opts.displayName,runtime:runtimeRaw,warn:message=>{json?warnings.push(message):defaultRuntime.log(message)}});await installDaemonServiceAndEmit({serviceNoun:`Node`,service,warnings,emit,fail,install:async()=>{await service.install({env:process.env,stdout,programArguments,workingDirectory,environment,description})}})}async function runNodeDaemonUninstall(opts={}){return await runServiceUninstall({serviceNoun:`Node`,service:resolveNodeService(),opts,stopBeforeUninstall:!1,assertNotLoadedAfterUninstall:!1})}async function runNodeDaemonRestart(opts={}){await runServiceRestart({serviceNoun:`Node`,service:resolveNodeService(),renderStartHints:renderNodeServiceStartHints,opts})}async function runNodeDaemonStop(opts={}){return await runServiceStop({serviceNoun:`Node`,service:resolveNodeService(),opts})}async function runNodeDaemonStatus(opts={}){let json=!!opts.json,service=resolveNodeService(),[loaded,command,runtime]=await Promise.all([service.isLoaded({env:process.env}).catch(()=>!1),service.readCommand(process.env).catch(()=>null),service.readRuntime(process.env).catch(err=>({status:`unknown`,detail:String(err)}))]),payload={service:{...buildDaemonServiceSnapshot(service,loaded),command,runtime}};if(json){defaultRuntime.log(JSON.stringify(payload,null,2));return}let{rich,label,accent,infoText,okText,warnText,errorText}=createCliStatusTextStyles(),serviceStatus=loaded?okText(service.loadedText):warnText(service.notLoadedText);defaultRuntime.log(`${label(`Service:`)} ${accent(service.label)} (${serviceStatus})`),command?.programArguments?.length&&defaultRuntime.log(`${label(`Command:`)} ${infoText(command.programArguments.join(` `))}`),command?.sourcePath&&defaultRuntime.log(`${label(`Service file:`)} ${infoText(command.sourcePath)}`),command?.workingDirectory&&defaultRuntime.log(`${label(`Working dir:`)} ${infoText(command.workingDirectory)}`);let runtimeLine=formatRuntimeStatus(runtime);if(runtimeLine){let runtimeColor=resolveRuntimeStatusColor(runtime?.status);defaultRuntime.log(`${label(`Runtime:`)} ${colorize(rich,runtimeColor,runtimeLine)}`)}if(!loaded){defaultRuntime.log(``);for(let hint of renderNodeServiceStartHints())defaultRuntime.log(`${warnText(`Start with:`)} ${infoText(hint)}`);return}let baseEnv={...process.env,...command?.environment??void 0},hintEnv={...baseEnv,BUILDERFORCE_AGENTS_LOG_PREFIX:baseEnv.BUILDERFORCE_AGENTS_LOG_PREFIX??`node`};if(runtime?.missingUnit){defaultRuntime.error(errorText(`Service unit not found.`));for(let hint of buildNodeRuntimeHints(hintEnv))defaultRuntime.error(errorText(hint));return}if(runtime?.status===`stopped`){defaultRuntime.error(errorText(`Service is loaded but not running.`));for(let hint of buildNodeRuntimeHints(hintEnv))defaultRuntime.error(errorText(hint))}}function parsePortWithFallback(value,fallback){return parsePort(value)??fallback}function registerNodeCli(program){let node=program.command(`node`).description(`Run and manage the headless node host service`).addHelpText(`after`,()=>`\n${theme.heading(`Examples:`)}\n${formatHelpExamples([[`builderforce node run --host 127.0.0.1 --port 18789`,`Run the node host in the foreground.`],[`builderforce node status`,`Check node host service status.`],[`builderforce node install`,`Install the node host service.`],[`builderforce node restart`,`Restart the installed node host service.`]])}\n\n${theme.muted(`Docs:`)} ${formatDocsLink(`/cli/node`,`docs.builderforce.ai/cli/node`)}\n`);node.command(`run`).description(`Run the headless node host (foreground)`).option(`--host <host>`,`Gateway host`).option(`--port <port>`,`Gateway port`).option(`--tls`,`Use TLS for the gateway connection`,!1).option(`--tls-fingerprint <sha256>`,`Expected TLS certificate fingerprint (sha256)`).option(`--node-id <id>`,`Override node id (clears pairing token)`).option(`--display-name <name>`,`Override node display name`).action(async opts=>{let existing=await loadNodeHostConfig();await runNodeHost({gatewayHost:opts.host?.trim()||existing?.gateway?.host||`127.0.0.1`,gatewayPort:parsePortWithFallback(opts.port,existing?.gateway?.port??18789),gatewayTls:!!opts.tls||!!opts.tlsFingerprint,gatewayTlsFingerprint:opts.tlsFingerprint,nodeId:opts.nodeId,displayName:opts.displayName})}),node.command(`status`).description(`Show node host status`).option(`--json`,`Output JSON`,!1).action(async opts=>{await runNodeDaemonStatus(opts)}),node.command(`install`).description(`Install the node host service (launchd/systemd/schtasks)`).option(`--host <host>`,`Gateway host`).option(`--port <port>`,`Gateway port`).option(`--tls`,`Use TLS for the gateway connection`,!1).option(`--tls-fingerprint <sha256>`,`Expected TLS certificate fingerprint (sha256)`).option(`--node-id <id>`,`Override node id (clears pairing token)`).option(`--display-name <name>`,`Override node display name`).option(`--runtime <runtime>`,`Service runtime (node|bun). Default: node`).option(`--force`,`Reinstall/overwrite if already installed`,!1).option(`--json`,`Output JSON`,!1).action(async opts=>{await runNodeDaemonInstall(opts)}),node.command(`uninstall`).description(`Uninstall the node host service (launchd/systemd/schtasks)`).option(`--json`,`Output JSON`,!1).action(async opts=>{await runNodeDaemonUninstall(opts)}),node.command(`stop`).description(`Stop the node host service (launchd/systemd/schtasks)`).option(`--json`,`Output JSON`,!1).action(async opts=>{await runNodeDaemonStop(opts)}),node.command(`restart`).description(`Restart the node host service (launchd/systemd/schtasks)`).option(`--json`,`Output JSON`,!1).action(async opts=>{await runNodeDaemonRestart(opts)})}export{registerNodeCli};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import"./paths-5FcIFMsj.js";import{B as theme,C as shortenHomePath,S as shortenHomeInString,z as isRich}from"./utils-DbaBVFaK.js";import"./session-key-EoB0qaG9.js";import"./builderforce-root-D64_sXEi.js";import{i as defaultRuntime}from"./subsystem-B3TqcCrZ.js";import"./registry-TdK-aV05.js";import"./logger-Bch0bx9c.js";import"./exec-DdcIjeyn.js";import{l as resolveDefaultAgentId,r as resolveAgentConfig}from"./agent-scope-DPtjOxzp.js";import"./src-CA0fU67C.js";import"./model-selection-
|
|
1
|
+
import"./paths-5FcIFMsj.js";import{B as theme,C as shortenHomePath,S as shortenHomeInString,z as isRich}from"./utils-DbaBVFaK.js";import"./session-key-EoB0qaG9.js";import"./builderforce-root-D64_sXEi.js";import{i as defaultRuntime}from"./subsystem-B3TqcCrZ.js";import"./registry-TdK-aV05.js";import"./logger-Bch0bx9c.js";import"./exec-DdcIjeyn.js";import{l as resolveDefaultAgentId,r as resolveAgentConfig}from"./agent-scope-DPtjOxzp.js";import"./src-CA0fU67C.js";import"./model-selection-DG9J_VTz.js";import"./env-file-D1MDi-AM.js";import"./boolean-Cnh1KNl1.js";import"./env-BIdU5BAp.js";import"./src-DTFqOIQD.js";import{r as loadConfig,y as parseDurationMs}from"./io-BLBq4T2o.js";import"./manifest-registry-BJCfNV1a.js";import"./config-BgV_FYSq.js";import"./redact-BHdfp2MZ.js";import"./errors-B1MIg3g-.js";import"./message-channel-D_jXxXQj.js";import"./client-xfoidwPI.js";import{i as randomIdempotencyKey}from"./call-T8ciwMTA.js";import{n as formatTimeAgo}from"./format-relative-niF9gXss.js";import{t as formatDocsLink}from"./links-BgWWaaOT.js";import{n as runCommandWithRuntime}from"./cli-utils-LBYKdNFb.js";import{t as formatHelpExamples}from"./help-format-Qfk2vDNX.js";import"./progress-BfOtdN6b.js";import{f as resolveExecApprovalsFromFile,i as maxAsk,o as minSecurity,t as DEFAULT_EXEC_APPROVAL_TIMEOUT_MS}from"./exec-approvals-BpVPDVtV.js";import{a as canvasSnapshotTempPath,c as parseCameraClipPayload,d as writeCameraClipPayloadToFile,f as writeUrlToFile,g as buildNodeShellCommand,i as parseEnvPairs,l as parseCameraSnapPayload,n as screenRecordTempPath,o as parseCanvasSnapshotPayload,p as applyPathPrepend,r as writeScreenRecordToFile,s as cameraTempPath,t as parseScreenRecordPayload,u as writeBase64ToFile}from"./nodes-screen-C3TDIi8d.js";import{n as parseNodeList,r as parsePairingList}from"./node-match-CpP4SXUp.js";import{t as parseTimeoutMs}from"./parse-timeout-DgbvuHbz.js";import{t as renderTable}from"./table-BoCHYKoQ.js";import{a as unauthorizedHintForMessage,i as resolveNodeId,n as callGatewayCli,o as formatPermissions,r as nodesCallOpts,t as buildNodeInvokeParams}from"./rpc-CbUnwStf.js";import fs from"node:fs/promises";function getNodesTheme(){let rich=isRich(),color=fn=>value=>rich?fn(value):value;return{rich,heading:color(theme.heading),ok:color(theme.success),warn:color(theme.warn),muted:color(theme.muted),error:color(theme.error)}}function runNodesCommand(label,action){return runCommandWithRuntime(defaultRuntime,action,err=>{let message=String(err),{error,warn}=getNodesTheme();defaultRuntime.error(error(`nodes ${label} failed: ${message}`));let hint=unauthorizedHintForMessage(message);hint&&defaultRuntime.error(warn(hint)),defaultRuntime.exit(1)})}const parseFacing=value=>{let v=String(value??``).trim().toLowerCase();if(v===`front`||v===`back`)return v;throw Error(`invalid facing: ${value} (expected front|back)`)};function registerNodesCameraCommands(nodes){let camera=nodes.command(`camera`).description(`Capture camera media from a paired node`);nodesCallOpts(camera.command(`list`).description(`List available cameras on a node`).requiredOption(`--node <idOrNameOrIp>`,`Node id, name, or IP`).action(async opts=>{await runNodesCommand(`camera list`,async()=>{let raw=await callGatewayCli(`node.invoke`,opts,buildNodeInvokeParams({nodeId:await resolveNodeId(opts,String(opts.node??``)),command:`camera.list`,params:{}})),res=typeof raw==`object`&&raw?raw:{},payload=typeof res.payload==`object`&&res.payload!==null?res.payload:{},devices=Array.isArray(payload.devices)?payload.devices:[];if(opts.json){defaultRuntime.log(JSON.stringify(devices,null,2));return}if(devices.length===0){let{muted}=getNodesTheme();defaultRuntime.log(muted(`No cameras reported.`));return}let{heading,muted}=getNodesTheme(),tableWidth=Math.max(60,(process.stdout.columns??120)-1),rows=devices.map(device=>({Name:typeof device.name==`string`?device.name:`Unknown Camera`,Position:typeof device.position==`string`?device.position:muted(`unspecified`),ID:typeof device.id==`string`?device.id:``}));defaultRuntime.log(heading(`Cameras`)),defaultRuntime.log(renderTable({width:tableWidth,columns:[{key:`Name`,header:`Name`,minWidth:14,flex:!0},{key:`Position`,header:`Position`,minWidth:10},{key:`ID`,header:`ID`,minWidth:10,flex:!0}],rows}).trimEnd())})}),{timeoutMs:6e4}),nodesCallOpts(camera.command(`snap`).description(`Capture a photo from a node camera (prints MEDIA:<path>)`).requiredOption(`--node <idOrNameOrIp>`,`Node id, name, or IP`).option(`--facing <front|back|both>`,`Camera facing`,`both`).option(`--device-id <id>`,`Camera device id (from nodes camera list)`).option(`--max-width <px>`,`Max width in px (optional)`).option(`--quality <0-1>`,`JPEG quality (default 0.9)`).option(`--delay-ms <ms>`,`Delay before capture in ms (macOS default 2000)`).option(`--invoke-timeout <ms>`,`Node invoke timeout in ms (default 20000)`,`20000`).action(async opts=>{await runNodesCommand(`camera snap`,async()=>{let nodeId=await resolveNodeId(opts,String(opts.node??``)),facingOpt=String(opts.facing??`both`).trim().toLowerCase(),facings=facingOpt===`both`?[`front`,`back`]:facingOpt===`front`||facingOpt===`back`?[facingOpt]:(()=>{throw Error(`invalid facing: ${String(opts.facing)} (expected front|back|both)`)})(),maxWidth=opts.maxWidth?Number.parseInt(String(opts.maxWidth),10):void 0,quality=opts.quality?Number.parseFloat(String(opts.quality)):void 0,delayMs=opts.delayMs?Number.parseInt(String(opts.delayMs),10):void 0,deviceId=opts.deviceId?String(opts.deviceId).trim():void 0,timeoutMs=opts.invokeTimeout?Number.parseInt(String(opts.invokeTimeout),10):void 0,results=[];for(let facing of facings){let raw=await callGatewayCli(`node.invoke`,opts,buildNodeInvokeParams({nodeId,command:`camera.snap`,params:{facing,maxWidth:Number.isFinite(maxWidth)?maxWidth:void 0,quality:Number.isFinite(quality)?quality:void 0,format:`jpg`,delayMs:Number.isFinite(delayMs)?delayMs:void 0,deviceId:deviceId||void 0},timeoutMs})),payload=parseCameraSnapPayload((typeof raw==`object`&&raw?raw:{}).payload),filePath=cameraTempPath({kind:`snap`,facing,ext:payload.format===`jpeg`?`jpg`:payload.format});payload.url?await writeUrlToFile(filePath,payload.url):payload.base64&&await writeBase64ToFile(filePath,payload.base64),results.push({facing,path:filePath,width:payload.width,height:payload.height})}if(opts.json){defaultRuntime.log(JSON.stringify({files:results},null,2));return}defaultRuntime.log(results.map(r=>`MEDIA:${shortenHomePath(r.path)}`).join(`
|
|
2
2
|
`))})}),{timeoutMs:6e4}),nodesCallOpts(camera.command(`clip`).description(`Capture a short video clip from a node camera (prints MEDIA:<path>)`).requiredOption(`--node <idOrNameOrIp>`,`Node id, name, or IP`).option(`--facing <front|back>`,`Camera facing`,`front`).option(`--device-id <id>`,`Camera device id (from nodes camera list)`).option(`--duration <ms|10s|1m>`,`Duration (default 3000ms; supports ms/s/m, e.g. 10s)`,`3000`).option(`--no-audio`,`Disable audio capture`).option(`--invoke-timeout <ms>`,`Node invoke timeout in ms (default 90000)`,`90000`).action(async opts=>{await runNodesCommand(`camera clip`,async()=>{let nodeId=await resolveNodeId(opts,String(opts.node??``)),facing=parseFacing(String(opts.facing??`front`)),durationMs=parseDurationMs(String(opts.duration??`3000`)),includeAudio=opts.audio!==!1,timeoutMs=opts.invokeTimeout?Number.parseInt(String(opts.invokeTimeout),10):void 0,deviceId=opts.deviceId?String(opts.deviceId).trim():void 0,raw=await callGatewayCli(`node.invoke`,opts,buildNodeInvokeParams({nodeId,command:`camera.clip`,params:{facing,durationMs:Number.isFinite(durationMs)?durationMs:void 0,includeAudio,format:`mp4`,deviceId:deviceId||void 0},timeoutMs})),payload=parseCameraClipPayload((typeof raw==`object`&&raw?raw:{}).payload),filePath=await writeCameraClipPayloadToFile({payload,facing});if(opts.json){defaultRuntime.log(JSON.stringify({file:{facing,path:filePath,durationMs:payload.durationMs,hasAudio:payload.hasAudio}},null,2));return}defaultRuntime.log(`MEDIA:${shortenHomePath(filePath)}`)})}),{timeoutMs:9e4})}const A2UI_ACTION_KEYS=[`beginRendering`,`surfaceUpdate`,`dataModelUpdate`,`deleteSurface`,`createSurface`];function buildA2UITextJsonl(text){let surfaceId=`main`,rootId=`root`,textId=`text`;return[{surfaceUpdate:{surfaceId,components:[{id:rootId,component:{Column:{children:{explicitList:[textId]}}}},{id:textId,component:{Text:{text:{literalString:text},usageHint:`body`}}}]}},{beginRendering:{surfaceId,root:rootId}}].map(payload=>JSON.stringify(payload)).join(`
|
|
3
3
|
`)}function validateA2UIJsonl(jsonl){let lines=jsonl.split(/\r?\n/),errors=[],sawV08=!1,sawV09=!1,messageCount=0;if(lines.forEach((line,idx)=>{let trimmed=line.trim();if(!trimmed)return;messageCount+=1;let obj;try{obj=JSON.parse(trimmed)}catch(err){errors.push(`line ${idx+1}: ${String(err)}`);return}if(!obj||typeof obj!=`object`||Array.isArray(obj)){errors.push(`line ${idx+1}: expected JSON object`);return}let record=obj,actionKeys=A2UI_ACTION_KEYS.filter(key=>key in record);if(actionKeys.length!==1){errors.push(`line ${idx+1}: expected exactly one action key (${A2UI_ACTION_KEYS.join(`, `)})`);return}actionKeys[0]===`createSurface`?sawV09=!0:sawV08=!0}),messageCount===0&&errors.push(`no JSONL messages found`),sawV08&&sawV09&&errors.push(`mixed A2UI v0.8 and v0.9 messages in one file`),errors.length>0)throw Error(`Invalid A2UI JSONL:\n- ${errors.join(`
|
|
4
4
|
- `)}`);return{version:sawV09?`v0.9`:`v0.8`,messageCount}}async function invokeCanvas(opts,command,params){let nodeId=await resolveNodeId(opts,String(opts.node??``)),timeoutMs=parseTimeoutMs(opts.invokeTimeout);return await callGatewayCli(`node.invoke`,opts,buildNodeInvokeParams({nodeId,command,params,timeoutMs:typeof timeoutMs==`number`?timeoutMs:void 0}))}function registerNodesCanvasCommands(nodes){let canvas=nodes.command(`canvas`).description(`Capture or render canvas content from a paired node`);nodesCallOpts(canvas.command(`snapshot`).description(`Capture a canvas snapshot (prints MEDIA:<path>)`).requiredOption(`--node <idOrNameOrIp>`,`Node id, name, or IP`).option(`--format <png|jpg|jpeg>`,`Image format`,`jpg`).option(`--max-width <px>`,`Max width in px (optional)`).option(`--quality <0-1>`,`JPEG quality (optional)`).option(`--invoke-timeout <ms>`,`Node invoke timeout in ms (default 20000)`,`20000`).action(async opts=>{await runNodesCommand(`canvas snapshot`,async()=>{let formatOpt=String(opts.format??`jpg`).trim().toLowerCase(),formatForParams=formatOpt===`jpg`||formatOpt===`jpeg`?`jpeg`:`png`;if(formatForParams!==`png`&&formatForParams!==`jpeg`)throw Error(`invalid format: ${String(opts.format)} (expected png|jpg|jpeg)`);let maxWidth=opts.maxWidth?Number.parseInt(String(opts.maxWidth),10):void 0,quality=opts.quality?Number.parseFloat(String(opts.quality)):void 0,raw=await invokeCanvas(opts,`canvas.snapshot`,{format:formatForParams,maxWidth:Number.isFinite(maxWidth)?maxWidth:void 0,quality:Number.isFinite(quality)?quality:void 0}),payload=parseCanvasSnapshotPayload((typeof raw==`object`&&raw?raw:{}).payload),filePath=canvasSnapshotTempPath({ext:payload.format===`jpeg`?`jpg`:payload.format});if(await writeBase64ToFile(filePath,payload.base64),opts.json){defaultRuntime.log(JSON.stringify({file:{path:filePath,format:payload.format}},null,2));return}defaultRuntime.log(`MEDIA:${shortenHomePath(filePath)}`)})}),{timeoutMs:6e4}),nodesCallOpts(canvas.command(`present`).description(`Show the canvas (optionally with a target URL/path)`).requiredOption(`--node <idOrNameOrIp>`,`Node id, name, or IP`).option(`--target <urlOrPath>`,`Target URL/path (optional)`).option(`--x <px>`,`Placement x coordinate`).option(`--y <px>`,`Placement y coordinate`).option(`--width <px>`,`Placement width`).option(`--height <px>`,`Placement height`).option(`--invoke-timeout <ms>`,`Node invoke timeout in ms`).action(async opts=>{await runNodesCommand(`canvas present`,async()=>{let placement={x:opts.x?Number.parseFloat(opts.x):void 0,y:opts.y?Number.parseFloat(opts.y):void 0,width:opts.width?Number.parseFloat(opts.width):void 0,height:opts.height?Number.parseFloat(opts.height):void 0},params={};if(opts.target&&(params.url=String(opts.target)),(Number.isFinite(placement.x)||Number.isFinite(placement.y)||Number.isFinite(placement.width)||Number.isFinite(placement.height))&&(params.placement=placement),await invokeCanvas(opts,`canvas.present`,params),!opts.json){let{ok}=getNodesTheme();defaultRuntime.log(ok(`canvas present ok`))}})})),nodesCallOpts(canvas.command(`hide`).description(`Hide the canvas`).requiredOption(`--node <idOrNameOrIp>`,`Node id, name, or IP`).option(`--invoke-timeout <ms>`,`Node invoke timeout in ms`).action(async opts=>{await runNodesCommand(`canvas hide`,async()=>{if(await invokeCanvas(opts,`canvas.hide`,void 0),!opts.json){let{ok}=getNodesTheme();defaultRuntime.log(ok(`canvas hide ok`))}})})),nodesCallOpts(canvas.command(`navigate`).description(`Navigate the canvas to a URL`).argument(`<url>`,`Target URL/path`).requiredOption(`--node <idOrNameOrIp>`,`Node id, name, or IP`).option(`--invoke-timeout <ms>`,`Node invoke timeout in ms`).action(async(url,opts)=>{await runNodesCommand(`canvas navigate`,async()=>{if(await invokeCanvas(opts,`canvas.navigate`,{url}),!opts.json){let{ok}=getNodesTheme();defaultRuntime.log(ok(`canvas navigate ok`))}})})),nodesCallOpts(canvas.command(`eval`).description(`Evaluate JavaScript in the canvas`).argument(`[js]`,`JavaScript to evaluate`).option(`--js <code>`,`JavaScript to evaluate`).requiredOption(`--node <idOrNameOrIp>`,`Node id, name, or IP`).option(`--invoke-timeout <ms>`,`Node invoke timeout in ms`).action(async(jsArg,opts)=>{await runNodesCommand(`canvas eval`,async()=>{let js=opts.js??jsArg;if(!js)throw Error(`missing --js or <js>`);let raw=await invokeCanvas(opts,`canvas.eval`,{javaScript:js});if(opts.json){defaultRuntime.log(JSON.stringify(raw,null,2));return}let payload=typeof raw==`object`&&raw?raw.payload:void 0;if(payload?.result)defaultRuntime.log(payload.result);else{let{ok}=getNodesTheme();defaultRuntime.log(ok(`canvas eval ok`))}})}));let a2ui=canvas.command(`a2ui`).description(`Render A2UI content on the canvas`);nodesCallOpts(a2ui.command(`push`).description(`Push A2UI JSONL to the canvas`).option(`--jsonl <path>`,`Path to JSONL payload`).option(`--text <text>`,`Render a quick A2UI text payload`).requiredOption(`--node <idOrNameOrIp>`,`Node id, name, or IP`).option(`--invoke-timeout <ms>`,`Node invoke timeout in ms`).action(async opts=>{await runNodesCommand(`canvas a2ui push`,async()=>{let hasJsonl=!!opts.jsonl,hasText=typeof opts.text==`string`;if(hasJsonl===hasText)throw Error(`provide exactly one of --jsonl or --text`);let jsonl=hasText?buildA2UITextJsonl(String(opts.text??``)):await fs.readFile(String(opts.jsonl),`utf8`),{version,messageCount}=validateA2UIJsonl(jsonl);if(version===`v0.9`)throw Error(`Detected A2UI v0.9 JSONL (createSurface). BuilderForceAgents currently supports v0.8 only.`);if(await invokeCanvas(opts,`canvas.a2ui.pushJSONL`,{jsonl}),!opts.json){let{ok}=getNodesTheme();defaultRuntime.log(ok(`canvas a2ui push ok (v0.8, ${messageCount} message${messageCount===1?``:`s`})`))}})})),nodesCallOpts(a2ui.command(`reset`).description(`Reset A2UI renderer state`).requiredOption(`--node <idOrNameOrIp>`,`Node id, name, or IP`).option(`--invoke-timeout <ms>`,`Node invoke timeout in ms`).action(async opts=>{await runNodesCommand(`canvas a2ui reset`,async()=>{if(await invokeCanvas(opts,`canvas.a2ui.reset`,void 0),!opts.json){let{ok}=getNodesTheme();defaultRuntime.log(ok(`canvas a2ui reset ok`))}})}))}function normalizeExecSecurity(value){let normalized=value?.trim().toLowerCase();return normalized===`deny`||normalized===`allowlist`||normalized===`full`?normalized:null}function normalizeExecAsk(value){let normalized=value?.trim().toLowerCase();return normalized===`off`||normalized===`on-miss`||normalized===`always`?normalized:null}function resolveExecDefaults(cfg,agentId){let globalExec=cfg?.tools?.exec;if(!agentId)return globalExec?{security:globalExec.security,ask:globalExec.ask,node:globalExec.node,pathPrepend:globalExec.pathPrepend,safeBins:globalExec.safeBins}:void 0;let agentExec=resolveAgentConfig(cfg,agentId)?.tools?.exec;return{security:agentExec?.security??globalExec?.security,ask:agentExec?.ask??globalExec?.ask,node:agentExec?.node??globalExec?.node,pathPrepend:agentExec?.pathPrepend??globalExec?.pathPrepend,safeBins:agentExec?.safeBins??globalExec?.safeBins}}async function resolveNodePlatform(opts,nodeId){try{let match=parseNodeList(await callGatewayCli(`node.list`,opts,{})).find(node=>node.nodeId===nodeId);return typeof match?.platform==`string`?match.platform:null}catch{return null}}function registerNodesInvokeCommands(nodes){nodesCallOpts(nodes.command(`invoke`).description(`Invoke a command on a paired node`).requiredOption(`--node <idOrNameOrIp>`,`Node id, name, or IP`).requiredOption(`--command <command>`,`Command (e.g. canvas.eval)`).option(`--params <json>`,`JSON object string for params`,`{}`).option(`--invoke-timeout <ms>`,`Node invoke timeout in ms (default 15000)`,`15000`).option(`--idempotency-key <key>`,`Idempotency key (optional)`).action(async opts=>{await runNodesCommand(`invoke`,async()=>{let nodeId=await resolveNodeId(opts,String(opts.node??``)),command=String(opts.command??``).trim();if(!nodeId||!command){let{error}=getNodesTheme();defaultRuntime.error(error(`--node and --command required`)),defaultRuntime.exit(1);return}let params=JSON.parse(String(opts.params??`{}`)),timeoutMs=opts.invokeTimeout?Number.parseInt(String(opts.invokeTimeout),10):void 0,invokeParams={nodeId,command,params,idempotencyKey:String(opts.idempotencyKey??randomIdempotencyKey())};typeof timeoutMs==`number`&&Number.isFinite(timeoutMs)&&(invokeParams.timeoutMs=timeoutMs);let result=await callGatewayCli(`node.invoke`,opts,invokeParams);defaultRuntime.log(JSON.stringify(result,null,2))})}),{timeoutMs:3e4}),nodesCallOpts(nodes.command(`run`).description(`Run a shell command on a node (mac only)`).option(`--node <idOrNameOrIp>`,`Node id, name, or IP`).option(`--cwd <path>`,`Working directory`).option(`--env <key=val>`,`Environment override (repeatable)`,(value,prev=[])=>[...prev,value]).option(`--raw <command>`,`Run a raw shell command string (sh -lc / cmd.exe /c)`).option(`--agent <id>`,`Agent id (default: configured default agent)`).option(`--ask <mode>`,`Exec ask mode (off|on-miss|always)`).option(`--security <mode>`,`Exec security mode (deny|allowlist|full)`).option(`--command-timeout <ms>`,`Command timeout (ms)`).option(`--needs-screen-recording`,`Require screen recording permission`).option(`--invoke-timeout <ms>`,`Node invoke timeout in ms (default 30000)`,`30000`).argument(`[command...]`,`Command and args`).action(async(command,opts)=>{await runNodesCommand(`run`,async()=>{let cfg=loadConfig(),agentId=opts.agent?.trim()||resolveDefaultAgentId(cfg),execDefaults=resolveExecDefaults(cfg,agentId),raw=typeof opts.raw==`string`?opts.raw.trim():``;if(raw&&Array.isArray(command)&&command.length>0)throw Error(`use --raw or argv, not both`);if(!raw&&(!Array.isArray(command)||command.length===0))throw Error(`command required`);let nodeQuery=String(opts.node??``).trim()||execDefaults?.node?.trim()||``;if(!nodeQuery)throw Error(`node required (set --node or tools.exec.node)`);let nodeId=await resolveNodeId(opts,nodeQuery),env=parseEnvPairs(opts.env),timeoutMs=parseTimeoutMs(opts.commandTimeout),invokeTimeout=parseTimeoutMs(opts.invokeTimeout),argv=Array.isArray(command)?command:[],rawCommand;if(raw){rawCommand=raw;let platform=await resolveNodePlatform(opts,nodeId);argv=buildNodeShellCommand(rawCommand,platform??void 0)}let nodeEnv=env?{...env}:void 0;nodeEnv&&applyPathPrepend(nodeEnv,execDefaults?.pathPrepend,{requireExisting:!0});let approvedByAsk=!1,approvalDecision=null,configuredSecurity=normalizeExecSecurity(execDefaults?.security)??`allowlist`,requestedSecurity=normalizeExecSecurity(opts.security);if(opts.security&&!requestedSecurity)throw Error(`invalid --security (use deny|allowlist|full)`);let configuredAsk=normalizeExecAsk(execDefaults?.ask)??`on-miss`,requestedAsk=normalizeExecAsk(opts.ask);if(opts.ask&&!requestedAsk)throw Error(`invalid --ask (use off|on-miss|always)`);let security=minSecurity(configuredSecurity,requestedSecurity??configuredSecurity),ask=maxAsk(configuredAsk,requestedAsk??configuredAsk),approvalsSnapshot=await callGatewayCli(`exec.approvals.node.get`,opts,{nodeId}),approvalsFile=approvalsSnapshot&&typeof approvalsSnapshot==`object`?approvalsSnapshot.file:void 0;if(!approvalsFile||typeof approvalsFile!=`object`)throw Error(`exec approvals unavailable`);let approvals=resolveExecApprovalsFromFile({file:approvalsFile,agentId,overrides:{security,ask}}),hostSecurity=minSecurity(security,approvals.agent.security),hostAsk=maxAsk(ask,approvals.agent.ask),askFallback=approvals.agent.askFallback;if(hostSecurity===`deny`)throw Error(`exec denied: host=node security=deny`);let requiresAsk=hostAsk===`always`||hostAsk===`on-miss`,approvalId=null;if(requiresAsk){approvalId=crypto.randomUUID();let approvalTimeoutMs=DEFAULT_EXEC_APPROVAL_TIMEOUT_MS,transportTimeoutMs=Math.max(parseTimeoutMs(opts.timeout)??0,approvalTimeoutMs+1e4),decisionResult=await callGatewayCli(`exec.approval.request`,opts,{id:approvalId,command:rawCommand??argv.join(` `),cwd:opts.cwd,host:`node`,security:hostSecurity,ask:hostAsk,agentId,resolvedPath:void 0,sessionKey:void 0,timeoutMs:approvalTimeoutMs},{transportTimeoutMs}),decision=decisionResult&&typeof decisionResult==`object`?decisionResult.decision??null:null;if(decision===`deny`)throw Error(`exec denied: user denied`);if(!decision){if(askFallback===`full`)approvedByAsk=!0,approvalDecision=`allow-once`;else if(askFallback!==`allowlist`)throw Error(`exec denied: approval required (approval UI not available)`)}decision===`allow-once`&&(approvedByAsk=!0,approvalDecision=`allow-once`),decision===`allow-always`&&(approvedByAsk=!0,approvalDecision=`allow-always`)}let invokeParams={nodeId,command:`system.run`,params:{command:argv,cwd:opts.cwd,env:nodeEnv,timeoutMs,needsScreenRecording:opts.needsScreenRecording===!0},idempotencyKey:String(opts.idempotencyKey??randomIdempotencyKey())};agentId&&(invokeParams.params.agentId=agentId),rawCommand&&(invokeParams.params.rawCommand=rawCommand),invokeParams.params.approved=approvedByAsk,approvalDecision&&(invokeParams.params.approvalDecision=approvalDecision),approvedByAsk&&approvalId&&(invokeParams.params.runId=approvalId),invokeTimeout!==void 0&&(invokeParams.timeoutMs=invokeTimeout);let result=await callGatewayCli(`node.invoke`,opts,invokeParams);if(opts.json){defaultRuntime.log(JSON.stringify(result,null,2));return}let payload=typeof result==`object`&&result?result.payload:void 0,stdout=typeof payload?.stdout==`string`?payload.stdout:``,stderr=typeof payload?.stderr==`string`?payload.stderr:``,exitCode=typeof payload?.exitCode==`number`?payload.exitCode:null,timedOut=payload?.timedOut===!0,success=payload?.success===!0;if(stdout&&process.stdout.write(stdout),stderr&&process.stderr.write(stderr),timedOut){let{error}=getNodesTheme();defaultRuntime.error(error(`run timed out`)),defaultRuntime.exit(1);return}if(exitCode!==null&&exitCode!==0){let hint=unauthorizedHintForMessage(`${stderr}\n${stdout}`);if(hint){let{warn}=getNodesTheme();defaultRuntime.error(warn(hint))}}if(exitCode!==null&&exitCode!==0&&!success){let{error}=getNodesTheme();defaultRuntime.error(error(`run exit ${exitCode}`)),defaultRuntime.exit(1);return}})}),{timeoutMs:35e3})}function registerNodesLocationCommands(nodes){nodesCallOpts(nodes.command(`location`).description(`Fetch location from a paired node`).command(`get`).description(`Fetch the current location from a node`).requiredOption(`--node <idOrNameOrIp>`,`Node id, name, or IP`).option(`--max-age <ms>`,`Use cached location newer than this (ms)`).option(`--accuracy <coarse|balanced|precise>`,`Desired accuracy (default: balanced/precise depending on node setting)`).option(`--location-timeout <ms>`,`Location fix timeout (ms)`,`10000`).option(`--invoke-timeout <ms>`,`Node invoke timeout in ms (default 20000)`,`20000`).action(async opts=>{await runNodesCommand(`location get`,async()=>{let nodeId=await resolveNodeId(opts,String(opts.node??``)),maxAgeMs=opts.maxAge?Number.parseInt(String(opts.maxAge),10):void 0,desiredAccuracyRaw=typeof opts.accuracy==`string`?opts.accuracy.trim().toLowerCase():void 0,desiredAccuracy=desiredAccuracyRaw===`coarse`||desiredAccuracyRaw===`balanced`||desiredAccuracyRaw===`precise`?desiredAccuracyRaw:void 0,timeoutMs=opts.locationTimeout?Number.parseInt(String(opts.locationTimeout),10):void 0,invokeTimeoutMs=opts.invokeTimeout?Number.parseInt(String(opts.invokeTimeout),10):void 0,invokeParams={nodeId,command:`location.get`,params:{maxAgeMs:Number.isFinite(maxAgeMs)?maxAgeMs:void 0,desiredAccuracy,timeoutMs:Number.isFinite(timeoutMs)?timeoutMs:void 0},idempotencyKey:randomIdempotencyKey()};typeof invokeTimeoutMs==`number`&&Number.isFinite(invokeTimeoutMs)&&(invokeParams.timeoutMs=invokeTimeoutMs);let raw=await callGatewayCli(`node.invoke`,opts,invokeParams),res=typeof raw==`object`&&raw?raw:{},payload=res.payload&&typeof res.payload==`object`?res.payload:{};if(opts.json){defaultRuntime.log(JSON.stringify(payload,null,2));return}let lat=payload.lat,lon=payload.lon,acc=payload.accuracyMeters;if(typeof lat==`number`&&typeof lon==`number`){let accText=typeof acc==`number`?` ±${acc.toFixed(1)}m`:``;defaultRuntime.log(`${lat},${lon}${accText}`);return}defaultRuntime.log(JSON.stringify(payload))})}),{timeoutMs:3e4})}function registerNodesNotifyCommand(nodes){nodesCallOpts(nodes.command(`notify`).description(`Send a local notification on a node (mac only)`).requiredOption(`--node <idOrNameOrIp>`,`Node id, name, or IP`).option(`--title <text>`,`Notification title`).option(`--body <text>`,`Notification body`).option(`--sound <name>`,`Notification sound`).option(`--priority <passive|active|timeSensitive>`,`Notification priority`).option(`--delivery <system|overlay|auto>`,`Delivery mode`,`system`).option(`--invoke-timeout <ms>`,`Node invoke timeout in ms (default 15000)`,`15000`).action(async opts=>{await runNodesCommand(`notify`,async()=>{let nodeId=await resolveNodeId(opts,String(opts.node??``)),title=String(opts.title??``).trim(),body=String(opts.body??``).trim();if(!title&&!body)throw Error(`missing --title or --body`);let invokeTimeout=opts.invokeTimeout?Number.parseInt(String(opts.invokeTimeout),10):void 0,invokeParams={nodeId,command:`system.notify`,params:{title,body,sound:opts.sound,priority:opts.priority,delivery:opts.delivery},idempotencyKey:String(opts.idempotencyKey??randomIdempotencyKey())};typeof invokeTimeout==`number`&&Number.isFinite(invokeTimeout)&&(invokeParams.timeoutMs=invokeTimeout);let result=await callGatewayCli(`node.invoke`,opts,invokeParams);if(opts.json){defaultRuntime.log(JSON.stringify(result,null,2));return}let{ok}=getNodesTheme();defaultRuntime.log(ok(`notify ok`))})}))}function renderPendingPairingRequestsTable(params){let{pending,now,tableWidth,theme}=params,rows=pending.map(r=>({Request:r.requestId,Node:r.displayName?.trim()?r.displayName.trim():r.nodeId,IP:r.remoteIp??``,Requested:typeof r.ts==`number`?formatTimeAgo(Math.max(0,now-r.ts)):theme.muted(`unknown`),Repair:r.isRepair?theme.warn(`yes`):``}));return{heading:theme.heading(`Pending`),table:renderTable({width:tableWidth,columns:[{key:`Request`,header:`Request`,minWidth:8},{key:`Node`,header:`Node`,minWidth:14,flex:!0},{key:`IP`,header:`IP`,minWidth:10},{key:`Requested`,header:`Requested`,minWidth:12},{key:`Repair`,header:`Repair`,minWidth:6}],rows}).trimEnd()}}function registerNodesPairingCommands(nodes){nodesCallOpts(nodes.command(`pending`).description(`List pending pairing requests`).action(async opts=>{await runNodesCommand(`pending`,async()=>{let{pending}=parsePairingList(await callGatewayCli(`node.pair.list`,opts,{}));if(opts.json){defaultRuntime.log(JSON.stringify(pending,null,2));return}if(pending.length===0){let{muted}=getNodesTheme();defaultRuntime.log(muted(`No pending pairing requests.`));return}let{heading,warn,muted}=getNodesTheme(),tableWidth=Math.max(60,(process.stdout.columns??120)-1),rendered=renderPendingPairingRequestsTable({pending,now:Date.now(),tableWidth,theme:{heading,warn,muted}});defaultRuntime.log(rendered.heading),defaultRuntime.log(rendered.table)})})),nodesCallOpts(nodes.command(`approve`).description(`Approve a pending pairing request`).argument(`<requestId>`,`Pending request id`).action(async(requestId,opts)=>{await runNodesCommand(`approve`,async()=>{let result=await callGatewayCli(`node.pair.approve`,opts,{requestId});defaultRuntime.log(JSON.stringify(result,null,2))})})),nodesCallOpts(nodes.command(`reject`).description(`Reject a pending pairing request`).argument(`<requestId>`,`Pending request id`).action(async(requestId,opts)=>{await runNodesCommand(`reject`,async()=>{let result=await callGatewayCli(`node.pair.reject`,opts,{requestId});defaultRuntime.log(JSON.stringify(result,null,2))})})),nodesCallOpts(nodes.command(`rename`).description(`Rename a paired node (display name override)`).requiredOption(`--node <idOrNameOrIp>`,`Node id, name, or IP`).requiredOption(`--name <displayName>`,`New display name`).action(async opts=>{await runNodesCommand(`rename`,async()=>{let nodeId=await resolveNodeId(opts,String(opts.node??``)),name=String(opts.name??``).trim();if(!nodeId||!name){defaultRuntime.error(`--node and --name required`),defaultRuntime.exit(1);return}let result=await callGatewayCli(`node.rename`,opts,{nodeId,displayName:name});if(opts.json){defaultRuntime.log(JSON.stringify(result,null,2));return}let{ok}=getNodesTheme();defaultRuntime.log(ok(`node rename ok: ${nodeId} -> ${name}`))})}))}function normalizeEnvironment(value){if(typeof value!=`string`)return null;let normalized=value.trim().toLowerCase();return normalized===`sandbox`||normalized===`production`?normalized:null}function registerNodesPushCommand(nodes){nodesCallOpts(nodes.command(`push`).description(`Send an APNs test push to an iOS node`).requiredOption(`--node <idOrNameOrIp>`,`Node id, name, or IP`).option(`--title <text>`,`Push title`,`BuilderForceAgents`).option(`--body <text>`,`Push body`).option(`--environment <sandbox|production>`,`Override APNs environment`).action(async opts=>{await runNodesCommand(`push`,async()=>{let nodeId=await resolveNodeId(opts,String(opts.node??``)),title=String(opts.title??``).trim()||`BuilderForceAgents`,body=String(opts.body??``).trim()||`Push test for node ${nodeId}`,environment=normalizeEnvironment(opts.environment);if(opts.environment&&!environment)throw Error(`invalid --environment (use sandbox|production)`);let params={nodeId,title,body};environment&&(params.environment=environment);let result=await callGatewayCli(`push.test`,opts,params);if(opts.json){defaultRuntime.log(JSON.stringify(result,null,2));return}let parsed=typeof result==`object`&&result?result:{},ok=parsed.ok===!0,status=typeof parsed.status==`number`?parsed.status:0,reason=typeof parsed.reason==`string`&&parsed.reason.trim().length>0?parsed.reason.trim():void 0,env=typeof parsed.environment==`string`&&parsed.environment.trim().length>0?parsed.environment.trim():`unknown`,{ok:okLabel,error:errorLabel}=getNodesTheme(),label=ok?okLabel:errorLabel;defaultRuntime.log(label(`push.test status=${status} ok=${ok} env=${env}`)),reason&&defaultRuntime.log(`reason: ${reason}`)})}),{timeoutMs:25e3})}function registerNodesScreenCommands(nodes){nodesCallOpts(nodes.command(`screen`).description(`Capture screen recordings from a paired node`).command(`record`).description(`Capture a short screen recording from a node (prints MEDIA:<path>)`).requiredOption(`--node <idOrNameOrIp>`,`Node id, name, or IP`).option(`--screen <index>`,`Screen index (0 = primary)`,`0`).option(`--duration <ms|10s>`,`Clip duration (ms or 10s)`,`10000`).option(`--fps <fps>`,`Frames per second`,`10`).option(`--no-audio`,`Disable microphone audio capture`).option(`--out <path>`,`Output path`).option(`--invoke-timeout <ms>`,`Node invoke timeout in ms (default 120000)`,`120000`).action(async opts=>{await runNodesCommand(`screen record`,async()=>{let nodeId=await resolveNodeId(opts,String(opts.node??``)),durationMs=parseDurationMs(opts.duration??``),screenIndex=Number.parseInt(String(opts.screen??`0`),10),fps=Number.parseFloat(String(opts.fps??`10`)),timeoutMs=opts.invokeTimeout?Number.parseInt(String(opts.invokeTimeout),10):void 0,raw=await callGatewayCli(`node.invoke`,opts,buildNodeInvokeParams({nodeId,command:`screen.record`,params:{durationMs:Number.isFinite(durationMs)?durationMs:void 0,screenIndex:Number.isFinite(screenIndex)?screenIndex:void 0,fps:Number.isFinite(fps)?fps:void 0,format:`mp4`,includeAudio:opts.audio!==!1},timeoutMs})),parsed=parseScreenRecordPayload((typeof raw==`object`&&raw?raw:{}).payload),written=await writeScreenRecordToFile(opts.out??screenRecordTempPath({ext:parsed.format||`mp4`}),parsed.base64);if(opts.json){defaultRuntime.log(JSON.stringify({file:{path:written.path,durationMs:parsed.durationMs,fps:parsed.fps,screenIndex:parsed.screenIndex,hasAudio:parsed.hasAudio}},null,2));return}defaultRuntime.log(`MEDIA:${shortenHomePath(written.path)}`)})}),{timeoutMs:18e4})}function formatVersionLabel(raw){let trimmed=raw.trim();return trimmed?trimmed.toLowerCase().startsWith(`v`)?trimmed:/^\d/.test(trimmed)?`v${trimmed}`:trimmed:raw}function resolveNodeVersions(node){let core=node.coreVersion?.trim()||void 0,ui=node.uiVersion?.trim()||void 0;if(core||ui)return{core,ui};let legacy=node.version?.trim();if(!legacy)return{core:void 0,ui:void 0};let platform=node.platform?.trim().toLowerCase()??``;return platform===`darwin`||platform===`linux`||platform===`win32`||platform===`windows`?{core:legacy,ui:void 0}:{core:void 0,ui:legacy}}function formatNodeVersions(node){let{core,ui}=resolveNodeVersions(node),parts=[];return core&&parts.push(`core ${formatVersionLabel(core)}`),ui&&parts.push(`ui ${formatVersionLabel(ui)}`),parts.length>0?parts.join(` · `):null}function formatPathEnv(raw){if(typeof raw!=`string`)return null;let trimmed=raw.trim();if(!trimmed)return null;let parts=trimmed.split(`:`).filter(Boolean);return shortenHomeInString(parts.length<=3?trimmed:`${parts.slice(0,2).join(`:`)}:…:${parts.slice(-1)[0]}`)}function parseSinceMs(raw,label){if(raw==null)return;let value=typeof raw==`string`?raw.trim():typeof raw==`number`?String(raw).trim():null;if(value===null){defaultRuntime.error(`${label}: invalid duration value`),defaultRuntime.exit(1);return}if(value)try{return parseDurationMs(value)}catch(err){let message=err instanceof Error?err.message:String(err);defaultRuntime.error(`${label}: ${message}`),defaultRuntime.exit(1);return}}function registerNodesStatusCommands(nodes){nodesCallOpts(nodes.command(`status`).description(`List known nodes with connection status and capabilities`).option(`--connected`,`Only show connected nodes`).option(`--last-connected <duration>`,`Only show nodes connected within duration (e.g. 24h)`).action(async opts=>{await runNodesCommand(`status`,async()=>{let connectedOnly=!!opts.connected,sinceMs=parseSinceMs(opts.lastConnected,`Invalid --last-connected`),result=await callGatewayCli(`node.list`,opts,{}),obj=typeof result==`object`&&result?result:{},{ok,warn,muted}=getNodesTheme(),tableWidth=Math.max(60,(process.stdout.columns??120)-1),now=Date.now(),nodes=parseNodeList(result),lastConnectedById=sinceMs===void 0?null:new Map(parsePairingList(await callGatewayCli(`node.pair.list`,opts,{})).paired.map(entry=>[entry.nodeId,entry])),filtered=nodes.filter(n=>{if(connectedOnly&&!n.connected)return!1;if(sinceMs!==void 0){let paired=lastConnectedById?.get(n.nodeId),lastConnectedAtMs=typeof paired?.lastConnectedAtMs==`number`?paired.lastConnectedAtMs:typeof n.connectedAtMs==`number`?n.connectedAtMs:void 0;if(typeof lastConnectedAtMs!=`number`||now-lastConnectedAtMs>sinceMs)return!1}return!0});if(opts.json){let ts=typeof obj.ts==`number`?obj.ts:Date.now();defaultRuntime.log(JSON.stringify({...obj,ts,nodes:filtered},null,2));return}let pairedCount=filtered.filter(n=>!!n.paired).length,connectedCount=filtered.filter(n=>!!n.connected).length,filteredLabel=filtered.length===nodes.length?``:` (of ${nodes.length})`;if(defaultRuntime.log(`Known: ${filtered.length}${filteredLabel} · Paired: ${pairedCount} · Connected: ${connectedCount}`),filtered.length===0)return;let rows=filtered.map(n=>{let name=n.displayName?.trim()?n.displayName.trim():n.nodeId,perms=formatPermissions(n.permissions),versions=formatNodeVersions(n),pathEnv=formatPathEnv(n.pathEnv),detailParts=[n.deviceFamily?`device: ${n.deviceFamily}`:null,n.modelIdentifier?`hw: ${n.modelIdentifier}`:null,perms?`perms: ${perms}`:null,versions,pathEnv?`path: ${pathEnv}`:null].filter(Boolean),caps=Array.isArray(n.caps)?n.caps.map(String).filter(Boolean).toSorted().join(`, `):`?`,paired=n.paired?ok(`paired`):warn(`unpaired`),connected=n.connected?ok(`connected`):muted(`disconnected`),since=typeof n.connectedAtMs==`number`?` (${formatTimeAgo(Math.max(0,now-n.connectedAtMs))})`:``;return{Node:name,ID:n.nodeId,IP:n.remoteIp??``,Detail:detailParts.join(` · `),Status:`${paired} · ${connected}${since}`,Caps:caps}});defaultRuntime.log(renderTable({width:tableWidth,columns:[{key:`Node`,header:`Node`,minWidth:14,flex:!0},{key:`ID`,header:`ID`,minWidth:10},{key:`IP`,header:`IP`,minWidth:10},{key:`Detail`,header:`Detail`,minWidth:18,flex:!0},{key:`Status`,header:`Status`,minWidth:18},{key:`Caps`,header:`Caps`,minWidth:12,flex:!0}],rows}).trimEnd())})})),nodesCallOpts(nodes.command(`describe`).description(`Describe a node (capabilities + supported invoke commands)`).requiredOption(`--node <idOrNameOrIp>`,`Node id, name, or IP`).action(async opts=>{await runNodesCommand(`describe`,async()=>{let nodeId=await resolveNodeId(opts,String(opts.node??``)),result=await callGatewayCli(`node.describe`,opts,{nodeId});if(opts.json){defaultRuntime.log(JSON.stringify(result,null,2));return}let obj=typeof result==`object`&&result?result:{},displayName=typeof obj.displayName==`string`?obj.displayName:nodeId,connected=!!obj.connected,paired=!!obj.paired,caps=Array.isArray(obj.caps)?obj.caps.map(String).filter(Boolean).toSorted():null,commands=Array.isArray(obj.commands)?obj.commands.map(String).filter(Boolean).toSorted():[],perms=formatPermissions(obj.permissions),family=typeof obj.deviceFamily==`string`?obj.deviceFamily:null,model=typeof obj.modelIdentifier==`string`?obj.modelIdentifier:null,ip=typeof obj.remoteIp==`string`?obj.remoteIp:null,pathEnv=typeof obj.pathEnv==`string`?obj.pathEnv:null,versions=formatNodeVersions(obj),{heading,ok,warn,muted}=getNodesTheme(),status=`${paired?ok(`paired`):warn(`unpaired`)} · ${connected?ok(`connected`):muted(`disconnected`)}`,tableWidth=Math.max(60,(process.stdout.columns??120)-1),rows=[{Field:`ID`,Value:nodeId},displayName?{Field:`Name`,Value:displayName}:null,ip?{Field:`IP`,Value:ip}:null,family?{Field:`Device`,Value:family}:null,model?{Field:`Model`,Value:model}:null,perms?{Field:`Perms`,Value:perms}:null,versions?{Field:`Version`,Value:versions}:null,pathEnv?{Field:`PATH`,Value:pathEnv}:null,{Field:`Status`,Value:status},{Field:`Caps`,Value:caps?caps.join(`, `):`?`}].filter(Boolean);if(defaultRuntime.log(heading(`Node`)),defaultRuntime.log(renderTable({width:tableWidth,columns:[{key:`Field`,header:`Field`,minWidth:8},{key:`Value`,header:`Value`,minWidth:24,flex:!0}],rows}).trimEnd()),defaultRuntime.log(``),defaultRuntime.log(heading(`Commands`)),commands.length===0){defaultRuntime.log(muted(`- (none reported)`));return}for(let c of commands)defaultRuntime.log(`- ${c}`)})})),nodesCallOpts(nodes.command(`list`).description(`List pending and paired nodes`).option(`--connected`,`Only show connected nodes`).option(`--last-connected <duration>`,`Only show nodes connected within duration (e.g. 24h)`).action(async opts=>{await runNodesCommand(`list`,async()=>{let connectedOnly=!!opts.connected,sinceMs=parseSinceMs(opts.lastConnected,`Invalid --last-connected`),{pending,paired}=parsePairingList(await callGatewayCli(`node.pair.list`,opts,{})),{heading,muted,warn}=getNodesTheme(),tableWidth=Math.max(60,(process.stdout.columns??120)-1),now=Date.now(),hasFilters=connectedOnly||sinceMs!==void 0,pendingRows=hasFilters?[]:pending,connectedById=hasFilters?new Map(parseNodeList(await callGatewayCli(`node.list`,opts,{})).map(node=>[node.nodeId,node])):null,filteredPaired=paired.filter(node=>{if(connectedOnly&&!connectedById?.get(node.nodeId)?.connected)return!1;if(sinceMs!==void 0){let live=connectedById?.get(node.nodeId),lastConnectedAtMs=typeof node.lastConnectedAtMs==`number`?node.lastConnectedAtMs:typeof live?.connectedAtMs==`number`?live.connectedAtMs:void 0;if(typeof lastConnectedAtMs!=`number`||now-lastConnectedAtMs>sinceMs)return!1}return!0}),filteredLabel=hasFilters&&filteredPaired.length!==paired.length?` (of ${paired.length})`:``;if(defaultRuntime.log(`Pending: ${pendingRows.length} · Paired: ${filteredPaired.length}${filteredLabel}`),opts.json){defaultRuntime.log(JSON.stringify({pending:pendingRows,paired:filteredPaired},null,2));return}if(pendingRows.length>0){let rendered=renderPendingPairingRequestsTable({pending:pendingRows,now,tableWidth,theme:{heading,warn,muted}});defaultRuntime.log(``),defaultRuntime.log(rendered.heading),defaultRuntime.log(rendered.table)}if(filteredPaired.length>0){let pairedRows=filteredPaired.map(n=>{let live=connectedById?.get(n.nodeId),lastConnectedAtMs=typeof n.lastConnectedAtMs==`number`?n.lastConnectedAtMs:typeof live?.connectedAtMs==`number`?live.connectedAtMs:void 0;return{Node:n.displayName?.trim()?n.displayName.trim():n.nodeId,Id:n.nodeId,IP:n.remoteIp??``,LastConnect:typeof lastConnectedAtMs==`number`?formatTimeAgo(Math.max(0,now-lastConnectedAtMs)):muted(`unknown`)}});defaultRuntime.log(``),defaultRuntime.log(heading(`Paired`)),defaultRuntime.log(renderTable({width:tableWidth,columns:[{key:`Node`,header:`Node`,minWidth:14,flex:!0},{key:`Id`,header:`ID`,minWidth:10},{key:`IP`,header:`IP`,minWidth:10},{key:`LastConnect`,header:`Last Connect`,minWidth:14}],rows:pairedRows}).trimEnd())}})}))}function registerNodesCli(program){let nodes=program.command(`nodes`).description(`Manage gateway-owned nodes (pairing, status, invoke, and media)`).addHelpText(`after`,()=>`\n${theme.heading(`Examples:`)}\n${formatHelpExamples([[`builderforce nodes status`,`List known nodes with live status.`],[`builderforce nodes pairing pending`,`Show pending node pairing requests.`],[`builderforce nodes run --node <id> --raw "uname -a"`,`Run a shell command on a node.`],[`builderforce nodes camera snap --node <id>`,`Capture a photo from a node camera.`]])}\n\n${theme.muted(`Docs:`)} ${formatDocsLink(`/cli/nodes`,`docs.builderforce.ai/cli/nodes`)}\n`);registerNodesStatusCommands(nodes),registerNodesPairingCommands(nodes),registerNodesInvokeCommands(nodes),registerNodesNotifyCommand(nodes),registerNodesPushCommand(nodes),registerNodesCanvasCommands(nodes),registerNodesCameraCommands(nodes),registerNodesScreenCommands(nodes),registerNodesLocationCommands(nodes)}export{registerNodesCli};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import"./paths-BHg-VHB4.js";import"./registry-Cv7CoWAs.js";import{R as isRich,S as shortenHomePath,x as shortenHomeInString,z as theme}from"./utils-BP60e80M.js";import{p as defaultRuntime}from"./subsystem-C4b1Von0.js";import"./boolean-ssGoaBPk.js";import"./env-BoE8QSib.js";import"./auth-profiles-
|
|
1
|
+
import"./paths-BHg-VHB4.js";import"./registry-Cv7CoWAs.js";import{R as isRich,S as shortenHomePath,x as shortenHomeInString,z as theme}from"./utils-BP60e80M.js";import{p as defaultRuntime}from"./subsystem-C4b1Von0.js";import"./boolean-ssGoaBPk.js";import"./env-BoE8QSib.js";import"./auth-profiles-pt7Tr4HA.js";import"./src-DvWaTze9.js";import"./logger-wuOr7HKl.js";import"./session-key-CksCYipj.js";import"./builderforce-root-DY1qbWNX.js";import"./exec-COgsU9ql.js";import{l as resolveDefaultAgentId,r as resolveAgentConfig}from"./agent-scope-CufEmNj_.js";import"./env-file-DeS6x2OL.js";import"./src-HrLX5bhG.js";import{r as loadConfig,y as parseDurationMs}from"./io-D9hC2aG0.js";import"./manifest-registry-009gLJ4l.js";import"./config-BpChMIJ6.js";import"./client-CGgp3zkQ.js";import{i as randomIdempotencyKey}from"./call-Du2LiaX6.js";import"./message-channel-z5YRpR2d.js";import"./redact-CgO7wehS.js";import"./errors-tAt19c1E.js";import{n as formatTimeAgo}from"./format-relative-CruqE52s.js";import{f as resolveExecApprovalsFromFile,i as maxAsk,o as minSecurity,t as DEFAULT_EXEC_APPROVAL_TIMEOUT_MS}from"./exec-approvals-D7ZPAZpt.js";import{a as canvasSnapshotTempPath,c as parseCameraClipPayload,d as writeCameraClipPayloadToFile,f as writeUrlToFile,g as buildNodeShellCommand,i as parseEnvPairs,l as parseCameraSnapPayload,n as screenRecordTempPath,o as parseCanvasSnapshotPayload,p as applyPathPrepend,r as writeScreenRecordToFile,s as cameraTempPath,t as parseScreenRecordPayload,u as writeBase64ToFile}from"./nodes-screen-D6GHv_S0.js";import{n as parseNodeList,r as parsePairingList}from"./node-match-DxosVKnI.js";import{t as parseTimeoutMs}from"./parse-timeout-BvepsazJ.js";import{t as formatDocsLink}from"./links-BKzP7VVP.js";import{n as runCommandWithRuntime}from"./cli-utils-C9pW69LF.js";import{t as formatHelpExamples}from"./help-format-CfFf-w62.js";import"./progress-Cqb-jAjT.js";import{t as renderTable}from"./table-BFCCZDsp.js";import{a as unauthorizedHintForMessage,i as resolveNodeId,n as callGatewayCli,o as formatPermissions,r as nodesCallOpts,t as buildNodeInvokeParams}from"./rpc-Cwm4gchc.js";import fs from"node:fs/promises";function getNodesTheme(){let rich=isRich(),color=fn=>value=>rich?fn(value):value;return{rich,heading:color(theme.heading),ok:color(theme.success),warn:color(theme.warn),muted:color(theme.muted),error:color(theme.error)}}function runNodesCommand(label,action){return runCommandWithRuntime(defaultRuntime,action,err=>{let message=String(err),{error,warn}=getNodesTheme();defaultRuntime.error(error(`nodes ${label} failed: ${message}`));let hint=unauthorizedHintForMessage(message);hint&&defaultRuntime.error(warn(hint)),defaultRuntime.exit(1)})}const parseFacing=value=>{let v=String(value??``).trim().toLowerCase();if(v===`front`||v===`back`)return v;throw Error(`invalid facing: ${value} (expected front|back)`)};function registerNodesCameraCommands(nodes){let camera=nodes.command(`camera`).description(`Capture camera media from a paired node`);nodesCallOpts(camera.command(`list`).description(`List available cameras on a node`).requiredOption(`--node <idOrNameOrIp>`,`Node id, name, or IP`).action(async opts=>{await runNodesCommand(`camera list`,async()=>{let raw=await callGatewayCli(`node.invoke`,opts,buildNodeInvokeParams({nodeId:await resolveNodeId(opts,String(opts.node??``)),command:`camera.list`,params:{}})),res=typeof raw==`object`&&raw?raw:{},payload=typeof res.payload==`object`&&res.payload!==null?res.payload:{},devices=Array.isArray(payload.devices)?payload.devices:[];if(opts.json){defaultRuntime.log(JSON.stringify(devices,null,2));return}if(devices.length===0){let{muted}=getNodesTheme();defaultRuntime.log(muted(`No cameras reported.`));return}let{heading,muted}=getNodesTheme(),tableWidth=Math.max(60,(process.stdout.columns??120)-1),rows=devices.map(device=>({Name:typeof device.name==`string`?device.name:`Unknown Camera`,Position:typeof device.position==`string`?device.position:muted(`unspecified`),ID:typeof device.id==`string`?device.id:``}));defaultRuntime.log(heading(`Cameras`)),defaultRuntime.log(renderTable({width:tableWidth,columns:[{key:`Name`,header:`Name`,minWidth:14,flex:!0},{key:`Position`,header:`Position`,minWidth:10},{key:`ID`,header:`ID`,minWidth:10,flex:!0}],rows}).trimEnd())})}),{timeoutMs:6e4}),nodesCallOpts(camera.command(`snap`).description(`Capture a photo from a node camera (prints MEDIA:<path>)`).requiredOption(`--node <idOrNameOrIp>`,`Node id, name, or IP`).option(`--facing <front|back|both>`,`Camera facing`,`both`).option(`--device-id <id>`,`Camera device id (from nodes camera list)`).option(`--max-width <px>`,`Max width in px (optional)`).option(`--quality <0-1>`,`JPEG quality (default 0.9)`).option(`--delay-ms <ms>`,`Delay before capture in ms (macOS default 2000)`).option(`--invoke-timeout <ms>`,`Node invoke timeout in ms (default 20000)`,`20000`).action(async opts=>{await runNodesCommand(`camera snap`,async()=>{let nodeId=await resolveNodeId(opts,String(opts.node??``)),facingOpt=String(opts.facing??`both`).trim().toLowerCase(),facings=facingOpt===`both`?[`front`,`back`]:facingOpt===`front`||facingOpt===`back`?[facingOpt]:(()=>{throw Error(`invalid facing: ${String(opts.facing)} (expected front|back|both)`)})(),maxWidth=opts.maxWidth?Number.parseInt(String(opts.maxWidth),10):void 0,quality=opts.quality?Number.parseFloat(String(opts.quality)):void 0,delayMs=opts.delayMs?Number.parseInt(String(opts.delayMs),10):void 0,deviceId=opts.deviceId?String(opts.deviceId).trim():void 0,timeoutMs=opts.invokeTimeout?Number.parseInt(String(opts.invokeTimeout),10):void 0,results=[];for(let facing of facings){let raw=await callGatewayCli(`node.invoke`,opts,buildNodeInvokeParams({nodeId,command:`camera.snap`,params:{facing,maxWidth:Number.isFinite(maxWidth)?maxWidth:void 0,quality:Number.isFinite(quality)?quality:void 0,format:`jpg`,delayMs:Number.isFinite(delayMs)?delayMs:void 0,deviceId:deviceId||void 0},timeoutMs})),payload=parseCameraSnapPayload((typeof raw==`object`&&raw?raw:{}).payload),filePath=cameraTempPath({kind:`snap`,facing,ext:payload.format===`jpeg`?`jpg`:payload.format});payload.url?await writeUrlToFile(filePath,payload.url):payload.base64&&await writeBase64ToFile(filePath,payload.base64),results.push({facing,path:filePath,width:payload.width,height:payload.height})}if(opts.json){defaultRuntime.log(JSON.stringify({files:results},null,2));return}defaultRuntime.log(results.map(r=>`MEDIA:${shortenHomePath(r.path)}`).join(`
|
|
2
2
|
`))})}),{timeoutMs:6e4}),nodesCallOpts(camera.command(`clip`).description(`Capture a short video clip from a node camera (prints MEDIA:<path>)`).requiredOption(`--node <idOrNameOrIp>`,`Node id, name, or IP`).option(`--facing <front|back>`,`Camera facing`,`front`).option(`--device-id <id>`,`Camera device id (from nodes camera list)`).option(`--duration <ms|10s|1m>`,`Duration (default 3000ms; supports ms/s/m, e.g. 10s)`,`3000`).option(`--no-audio`,`Disable audio capture`).option(`--invoke-timeout <ms>`,`Node invoke timeout in ms (default 90000)`,`90000`).action(async opts=>{await runNodesCommand(`camera clip`,async()=>{let nodeId=await resolveNodeId(opts,String(opts.node??``)),facing=parseFacing(String(opts.facing??`front`)),durationMs=parseDurationMs(String(opts.duration??`3000`)),includeAudio=opts.audio!==!1,timeoutMs=opts.invokeTimeout?Number.parseInt(String(opts.invokeTimeout),10):void 0,deviceId=opts.deviceId?String(opts.deviceId).trim():void 0,raw=await callGatewayCli(`node.invoke`,opts,buildNodeInvokeParams({nodeId,command:`camera.clip`,params:{facing,durationMs:Number.isFinite(durationMs)?durationMs:void 0,includeAudio,format:`mp4`,deviceId:deviceId||void 0},timeoutMs})),payload=parseCameraClipPayload((typeof raw==`object`&&raw?raw:{}).payload),filePath=await writeCameraClipPayloadToFile({payload,facing});if(opts.json){defaultRuntime.log(JSON.stringify({file:{facing,path:filePath,durationMs:payload.durationMs,hasAudio:payload.hasAudio}},null,2));return}defaultRuntime.log(`MEDIA:${shortenHomePath(filePath)}`)})}),{timeoutMs:9e4})}const A2UI_ACTION_KEYS=[`beginRendering`,`surfaceUpdate`,`dataModelUpdate`,`deleteSurface`,`createSurface`];function buildA2UITextJsonl(text){let surfaceId=`main`,rootId=`root`,textId=`text`;return[{surfaceUpdate:{surfaceId,components:[{id:rootId,component:{Column:{children:{explicitList:[textId]}}}},{id:textId,component:{Text:{text:{literalString:text},usageHint:`body`}}}]}},{beginRendering:{surfaceId,root:rootId}}].map(payload=>JSON.stringify(payload)).join(`
|
|
3
3
|
`)}function validateA2UIJsonl(jsonl){let lines=jsonl.split(/\r?\n/),errors=[],sawV08=!1,sawV09=!1,messageCount=0;if(lines.forEach((line,idx)=>{let trimmed=line.trim();if(!trimmed)return;messageCount+=1;let obj;try{obj=JSON.parse(trimmed)}catch(err){errors.push(`line ${idx+1}: ${String(err)}`);return}if(!obj||typeof obj!=`object`||Array.isArray(obj)){errors.push(`line ${idx+1}: expected JSON object`);return}let record=obj,actionKeys=A2UI_ACTION_KEYS.filter(key=>key in record);if(actionKeys.length!==1){errors.push(`line ${idx+1}: expected exactly one action key (${A2UI_ACTION_KEYS.join(`, `)})`);return}actionKeys[0]===`createSurface`?sawV09=!0:sawV08=!0}),messageCount===0&&errors.push(`no JSONL messages found`),sawV08&&sawV09&&errors.push(`mixed A2UI v0.8 and v0.9 messages in one file`),errors.length>0)throw Error(`Invalid A2UI JSONL:\n- ${errors.join(`
|
|
4
4
|
- `)}`);return{version:sawV09?`v0.9`:`v0.8`,messageCount}}async function invokeCanvas(opts,command,params){let nodeId=await resolveNodeId(opts,String(opts.node??``)),timeoutMs=parseTimeoutMs(opts.invokeTimeout);return await callGatewayCli(`node.invoke`,opts,buildNodeInvokeParams({nodeId,command,params,timeoutMs:typeof timeoutMs==`number`?timeoutMs:void 0}))}function registerNodesCanvasCommands(nodes){let canvas=nodes.command(`canvas`).description(`Capture or render canvas content from a paired node`);nodesCallOpts(canvas.command(`snapshot`).description(`Capture a canvas snapshot (prints MEDIA:<path>)`).requiredOption(`--node <idOrNameOrIp>`,`Node id, name, or IP`).option(`--format <png|jpg|jpeg>`,`Image format`,`jpg`).option(`--max-width <px>`,`Max width in px (optional)`).option(`--quality <0-1>`,`JPEG quality (optional)`).option(`--invoke-timeout <ms>`,`Node invoke timeout in ms (default 20000)`,`20000`).action(async opts=>{await runNodesCommand(`canvas snapshot`,async()=>{let formatOpt=String(opts.format??`jpg`).trim().toLowerCase(),formatForParams=formatOpt===`jpg`||formatOpt===`jpeg`?`jpeg`:`png`;if(formatForParams!==`png`&&formatForParams!==`jpeg`)throw Error(`invalid format: ${String(opts.format)} (expected png|jpg|jpeg)`);let maxWidth=opts.maxWidth?Number.parseInt(String(opts.maxWidth),10):void 0,quality=opts.quality?Number.parseFloat(String(opts.quality)):void 0,raw=await invokeCanvas(opts,`canvas.snapshot`,{format:formatForParams,maxWidth:Number.isFinite(maxWidth)?maxWidth:void 0,quality:Number.isFinite(quality)?quality:void 0}),payload=parseCanvasSnapshotPayload((typeof raw==`object`&&raw?raw:{}).payload),filePath=canvasSnapshotTempPath({ext:payload.format===`jpeg`?`jpg`:payload.format});if(await writeBase64ToFile(filePath,payload.base64),opts.json){defaultRuntime.log(JSON.stringify({file:{path:filePath,format:payload.format}},null,2));return}defaultRuntime.log(`MEDIA:${shortenHomePath(filePath)}`)})}),{timeoutMs:6e4}),nodesCallOpts(canvas.command(`present`).description(`Show the canvas (optionally with a target URL/path)`).requiredOption(`--node <idOrNameOrIp>`,`Node id, name, or IP`).option(`--target <urlOrPath>`,`Target URL/path (optional)`).option(`--x <px>`,`Placement x coordinate`).option(`--y <px>`,`Placement y coordinate`).option(`--width <px>`,`Placement width`).option(`--height <px>`,`Placement height`).option(`--invoke-timeout <ms>`,`Node invoke timeout in ms`).action(async opts=>{await runNodesCommand(`canvas present`,async()=>{let placement={x:opts.x?Number.parseFloat(opts.x):void 0,y:opts.y?Number.parseFloat(opts.y):void 0,width:opts.width?Number.parseFloat(opts.width):void 0,height:opts.height?Number.parseFloat(opts.height):void 0},params={};if(opts.target&&(params.url=String(opts.target)),(Number.isFinite(placement.x)||Number.isFinite(placement.y)||Number.isFinite(placement.width)||Number.isFinite(placement.height))&&(params.placement=placement),await invokeCanvas(opts,`canvas.present`,params),!opts.json){let{ok}=getNodesTheme();defaultRuntime.log(ok(`canvas present ok`))}})})),nodesCallOpts(canvas.command(`hide`).description(`Hide the canvas`).requiredOption(`--node <idOrNameOrIp>`,`Node id, name, or IP`).option(`--invoke-timeout <ms>`,`Node invoke timeout in ms`).action(async opts=>{await runNodesCommand(`canvas hide`,async()=>{if(await invokeCanvas(opts,`canvas.hide`,void 0),!opts.json){let{ok}=getNodesTheme();defaultRuntime.log(ok(`canvas hide ok`))}})})),nodesCallOpts(canvas.command(`navigate`).description(`Navigate the canvas to a URL`).argument(`<url>`,`Target URL/path`).requiredOption(`--node <idOrNameOrIp>`,`Node id, name, or IP`).option(`--invoke-timeout <ms>`,`Node invoke timeout in ms`).action(async(url,opts)=>{await runNodesCommand(`canvas navigate`,async()=>{if(await invokeCanvas(opts,`canvas.navigate`,{url}),!opts.json){let{ok}=getNodesTheme();defaultRuntime.log(ok(`canvas navigate ok`))}})})),nodesCallOpts(canvas.command(`eval`).description(`Evaluate JavaScript in the canvas`).argument(`[js]`,`JavaScript to evaluate`).option(`--js <code>`,`JavaScript to evaluate`).requiredOption(`--node <idOrNameOrIp>`,`Node id, name, or IP`).option(`--invoke-timeout <ms>`,`Node invoke timeout in ms`).action(async(jsArg,opts)=>{await runNodesCommand(`canvas eval`,async()=>{let js=opts.js??jsArg;if(!js)throw Error(`missing --js or <js>`);let raw=await invokeCanvas(opts,`canvas.eval`,{javaScript:js});if(opts.json){defaultRuntime.log(JSON.stringify(raw,null,2));return}let payload=typeof raw==`object`&&raw?raw.payload:void 0;if(payload?.result)defaultRuntime.log(payload.result);else{let{ok}=getNodesTheme();defaultRuntime.log(ok(`canvas eval ok`))}})}));let a2ui=canvas.command(`a2ui`).description(`Render A2UI content on the canvas`);nodesCallOpts(a2ui.command(`push`).description(`Push A2UI JSONL to the canvas`).option(`--jsonl <path>`,`Path to JSONL payload`).option(`--text <text>`,`Render a quick A2UI text payload`).requiredOption(`--node <idOrNameOrIp>`,`Node id, name, or IP`).option(`--invoke-timeout <ms>`,`Node invoke timeout in ms`).action(async opts=>{await runNodesCommand(`canvas a2ui push`,async()=>{let hasJsonl=!!opts.jsonl,hasText=typeof opts.text==`string`;if(hasJsonl===hasText)throw Error(`provide exactly one of --jsonl or --text`);let jsonl=hasText?buildA2UITextJsonl(String(opts.text??``)):await fs.readFile(String(opts.jsonl),`utf8`),{version,messageCount}=validateA2UIJsonl(jsonl);if(version===`v0.9`)throw Error(`Detected A2UI v0.9 JSONL (createSurface). BuilderForceAgents currently supports v0.8 only.`);if(await invokeCanvas(opts,`canvas.a2ui.pushJSONL`,{jsonl}),!opts.json){let{ok}=getNodesTheme();defaultRuntime.log(ok(`canvas a2ui push ok (v0.8, ${messageCount} message${messageCount===1?``:`s`})`))}})})),nodesCallOpts(a2ui.command(`reset`).description(`Reset A2UI renderer state`).requiredOption(`--node <idOrNameOrIp>`,`Node id, name, or IP`).option(`--invoke-timeout <ms>`,`Node invoke timeout in ms`).action(async opts=>{await runNodesCommand(`canvas a2ui reset`,async()=>{if(await invokeCanvas(opts,`canvas.a2ui.reset`,void 0),!opts.json){let{ok}=getNodesTheme();defaultRuntime.log(ok(`canvas a2ui reset ok`))}})}))}function normalizeExecSecurity(value){let normalized=value?.trim().toLowerCase();return normalized===`deny`||normalized===`allowlist`||normalized===`full`?normalized:null}function normalizeExecAsk(value){let normalized=value?.trim().toLowerCase();return normalized===`off`||normalized===`on-miss`||normalized===`always`?normalized:null}function resolveExecDefaults(cfg,agentId){let globalExec=cfg?.tools?.exec;if(!agentId)return globalExec?{security:globalExec.security,ask:globalExec.ask,node:globalExec.node,pathPrepend:globalExec.pathPrepend,safeBins:globalExec.safeBins}:void 0;let agentExec=resolveAgentConfig(cfg,agentId)?.tools?.exec;return{security:agentExec?.security??globalExec?.security,ask:agentExec?.ask??globalExec?.ask,node:agentExec?.node??globalExec?.node,pathPrepend:agentExec?.pathPrepend??globalExec?.pathPrepend,safeBins:agentExec?.safeBins??globalExec?.safeBins}}async function resolveNodePlatform(opts,nodeId){try{let match=parseNodeList(await callGatewayCli(`node.list`,opts,{})).find(node=>node.nodeId===nodeId);return typeof match?.platform==`string`?match.platform:null}catch{return null}}function registerNodesInvokeCommands(nodes){nodesCallOpts(nodes.command(`invoke`).description(`Invoke a command on a paired node`).requiredOption(`--node <idOrNameOrIp>`,`Node id, name, or IP`).requiredOption(`--command <command>`,`Command (e.g. canvas.eval)`).option(`--params <json>`,`JSON object string for params`,`{}`).option(`--invoke-timeout <ms>`,`Node invoke timeout in ms (default 15000)`,`15000`).option(`--idempotency-key <key>`,`Idempotency key (optional)`).action(async opts=>{await runNodesCommand(`invoke`,async()=>{let nodeId=await resolveNodeId(opts,String(opts.node??``)),command=String(opts.command??``).trim();if(!nodeId||!command){let{error}=getNodesTheme();defaultRuntime.error(error(`--node and --command required`)),defaultRuntime.exit(1);return}let params=JSON.parse(String(opts.params??`{}`)),timeoutMs=opts.invokeTimeout?Number.parseInt(String(opts.invokeTimeout),10):void 0,invokeParams={nodeId,command,params,idempotencyKey:String(opts.idempotencyKey??randomIdempotencyKey())};typeof timeoutMs==`number`&&Number.isFinite(timeoutMs)&&(invokeParams.timeoutMs=timeoutMs);let result=await callGatewayCli(`node.invoke`,opts,invokeParams);defaultRuntime.log(JSON.stringify(result,null,2))})}),{timeoutMs:3e4}),nodesCallOpts(nodes.command(`run`).description(`Run a shell command on a node (mac only)`).option(`--node <idOrNameOrIp>`,`Node id, name, or IP`).option(`--cwd <path>`,`Working directory`).option(`--env <key=val>`,`Environment override (repeatable)`,(value,prev=[])=>[...prev,value]).option(`--raw <command>`,`Run a raw shell command string (sh -lc / cmd.exe /c)`).option(`--agent <id>`,`Agent id (default: configured default agent)`).option(`--ask <mode>`,`Exec ask mode (off|on-miss|always)`).option(`--security <mode>`,`Exec security mode (deny|allowlist|full)`).option(`--command-timeout <ms>`,`Command timeout (ms)`).option(`--needs-screen-recording`,`Require screen recording permission`).option(`--invoke-timeout <ms>`,`Node invoke timeout in ms (default 30000)`,`30000`).argument(`[command...]`,`Command and args`).action(async(command,opts)=>{await runNodesCommand(`run`,async()=>{let cfg=loadConfig(),agentId=opts.agent?.trim()||resolveDefaultAgentId(cfg),execDefaults=resolveExecDefaults(cfg,agentId),raw=typeof opts.raw==`string`?opts.raw.trim():``;if(raw&&Array.isArray(command)&&command.length>0)throw Error(`use --raw or argv, not both`);if(!raw&&(!Array.isArray(command)||command.length===0))throw Error(`command required`);let nodeQuery=String(opts.node??``).trim()||execDefaults?.node?.trim()||``;if(!nodeQuery)throw Error(`node required (set --node or tools.exec.node)`);let nodeId=await resolveNodeId(opts,nodeQuery),env=parseEnvPairs(opts.env),timeoutMs=parseTimeoutMs(opts.commandTimeout),invokeTimeout=parseTimeoutMs(opts.invokeTimeout),argv=Array.isArray(command)?command:[],rawCommand;if(raw){rawCommand=raw;let platform=await resolveNodePlatform(opts,nodeId);argv=buildNodeShellCommand(rawCommand,platform??void 0)}let nodeEnv=env?{...env}:void 0;nodeEnv&&applyPathPrepend(nodeEnv,execDefaults?.pathPrepend,{requireExisting:!0});let approvedByAsk=!1,approvalDecision=null,configuredSecurity=normalizeExecSecurity(execDefaults?.security)??`allowlist`,requestedSecurity=normalizeExecSecurity(opts.security);if(opts.security&&!requestedSecurity)throw Error(`invalid --security (use deny|allowlist|full)`);let configuredAsk=normalizeExecAsk(execDefaults?.ask)??`on-miss`,requestedAsk=normalizeExecAsk(opts.ask);if(opts.ask&&!requestedAsk)throw Error(`invalid --ask (use off|on-miss|always)`);let security=minSecurity(configuredSecurity,requestedSecurity??configuredSecurity),ask=maxAsk(configuredAsk,requestedAsk??configuredAsk),approvalsSnapshot=await callGatewayCli(`exec.approvals.node.get`,opts,{nodeId}),approvalsFile=approvalsSnapshot&&typeof approvalsSnapshot==`object`?approvalsSnapshot.file:void 0;if(!approvalsFile||typeof approvalsFile!=`object`)throw Error(`exec approvals unavailable`);let approvals=resolveExecApprovalsFromFile({file:approvalsFile,agentId,overrides:{security,ask}}),hostSecurity=minSecurity(security,approvals.agent.security),hostAsk=maxAsk(ask,approvals.agent.ask),askFallback=approvals.agent.askFallback;if(hostSecurity===`deny`)throw Error(`exec denied: host=node security=deny`);let requiresAsk=hostAsk===`always`||hostAsk===`on-miss`,approvalId=null;if(requiresAsk){approvalId=crypto.randomUUID();let approvalTimeoutMs=DEFAULT_EXEC_APPROVAL_TIMEOUT_MS,transportTimeoutMs=Math.max(parseTimeoutMs(opts.timeout)??0,approvalTimeoutMs+1e4),decisionResult=await callGatewayCli(`exec.approval.request`,opts,{id:approvalId,command:rawCommand??argv.join(` `),cwd:opts.cwd,host:`node`,security:hostSecurity,ask:hostAsk,agentId,resolvedPath:void 0,sessionKey:void 0,timeoutMs:approvalTimeoutMs},{transportTimeoutMs}),decision=decisionResult&&typeof decisionResult==`object`?decisionResult.decision??null:null;if(decision===`deny`)throw Error(`exec denied: user denied`);if(!decision){if(askFallback===`full`)approvedByAsk=!0,approvalDecision=`allow-once`;else if(askFallback!==`allowlist`)throw Error(`exec denied: approval required (approval UI not available)`)}decision===`allow-once`&&(approvedByAsk=!0,approvalDecision=`allow-once`),decision===`allow-always`&&(approvedByAsk=!0,approvalDecision=`allow-always`)}let invokeParams={nodeId,command:`system.run`,params:{command:argv,cwd:opts.cwd,env:nodeEnv,timeoutMs,needsScreenRecording:opts.needsScreenRecording===!0},idempotencyKey:String(opts.idempotencyKey??randomIdempotencyKey())};agentId&&(invokeParams.params.agentId=agentId),rawCommand&&(invokeParams.params.rawCommand=rawCommand),invokeParams.params.approved=approvedByAsk,approvalDecision&&(invokeParams.params.approvalDecision=approvalDecision),approvedByAsk&&approvalId&&(invokeParams.params.runId=approvalId),invokeTimeout!==void 0&&(invokeParams.timeoutMs=invokeTimeout);let result=await callGatewayCli(`node.invoke`,opts,invokeParams);if(opts.json){defaultRuntime.log(JSON.stringify(result,null,2));return}let payload=typeof result==`object`&&result?result.payload:void 0,stdout=typeof payload?.stdout==`string`?payload.stdout:``,stderr=typeof payload?.stderr==`string`?payload.stderr:``,exitCode=typeof payload?.exitCode==`number`?payload.exitCode:null,timedOut=payload?.timedOut===!0,success=payload?.success===!0;if(stdout&&process.stdout.write(stdout),stderr&&process.stderr.write(stderr),timedOut){let{error}=getNodesTheme();defaultRuntime.error(error(`run timed out`)),defaultRuntime.exit(1);return}if(exitCode!==null&&exitCode!==0){let hint=unauthorizedHintForMessage(`${stderr}\n${stdout}`);if(hint){let{warn}=getNodesTheme();defaultRuntime.error(warn(hint))}}if(exitCode!==null&&exitCode!==0&&!success){let{error}=getNodesTheme();defaultRuntime.error(error(`run exit ${exitCode}`)),defaultRuntime.exit(1);return}})}),{timeoutMs:35e3})}function registerNodesLocationCommands(nodes){nodesCallOpts(nodes.command(`location`).description(`Fetch location from a paired node`).command(`get`).description(`Fetch the current location from a node`).requiredOption(`--node <idOrNameOrIp>`,`Node id, name, or IP`).option(`--max-age <ms>`,`Use cached location newer than this (ms)`).option(`--accuracy <coarse|balanced|precise>`,`Desired accuracy (default: balanced/precise depending on node setting)`).option(`--location-timeout <ms>`,`Location fix timeout (ms)`,`10000`).option(`--invoke-timeout <ms>`,`Node invoke timeout in ms (default 20000)`,`20000`).action(async opts=>{await runNodesCommand(`location get`,async()=>{let nodeId=await resolveNodeId(opts,String(opts.node??``)),maxAgeMs=opts.maxAge?Number.parseInt(String(opts.maxAge),10):void 0,desiredAccuracyRaw=typeof opts.accuracy==`string`?opts.accuracy.trim().toLowerCase():void 0,desiredAccuracy=desiredAccuracyRaw===`coarse`||desiredAccuracyRaw===`balanced`||desiredAccuracyRaw===`precise`?desiredAccuracyRaw:void 0,timeoutMs=opts.locationTimeout?Number.parseInt(String(opts.locationTimeout),10):void 0,invokeTimeoutMs=opts.invokeTimeout?Number.parseInt(String(opts.invokeTimeout),10):void 0,invokeParams={nodeId,command:`location.get`,params:{maxAgeMs:Number.isFinite(maxAgeMs)?maxAgeMs:void 0,desiredAccuracy,timeoutMs:Number.isFinite(timeoutMs)?timeoutMs:void 0},idempotencyKey:randomIdempotencyKey()};typeof invokeTimeoutMs==`number`&&Number.isFinite(invokeTimeoutMs)&&(invokeParams.timeoutMs=invokeTimeoutMs);let raw=await callGatewayCli(`node.invoke`,opts,invokeParams),res=typeof raw==`object`&&raw?raw:{},payload=res.payload&&typeof res.payload==`object`?res.payload:{};if(opts.json){defaultRuntime.log(JSON.stringify(payload,null,2));return}let lat=payload.lat,lon=payload.lon,acc=payload.accuracyMeters;if(typeof lat==`number`&&typeof lon==`number`){let accText=typeof acc==`number`?` ±${acc.toFixed(1)}m`:``;defaultRuntime.log(`${lat},${lon}${accText}`);return}defaultRuntime.log(JSON.stringify(payload))})}),{timeoutMs:3e4})}function registerNodesNotifyCommand(nodes){nodesCallOpts(nodes.command(`notify`).description(`Send a local notification on a node (mac only)`).requiredOption(`--node <idOrNameOrIp>`,`Node id, name, or IP`).option(`--title <text>`,`Notification title`).option(`--body <text>`,`Notification body`).option(`--sound <name>`,`Notification sound`).option(`--priority <passive|active|timeSensitive>`,`Notification priority`).option(`--delivery <system|overlay|auto>`,`Delivery mode`,`system`).option(`--invoke-timeout <ms>`,`Node invoke timeout in ms (default 15000)`,`15000`).action(async opts=>{await runNodesCommand(`notify`,async()=>{let nodeId=await resolveNodeId(opts,String(opts.node??``)),title=String(opts.title??``).trim(),body=String(opts.body??``).trim();if(!title&&!body)throw Error(`missing --title or --body`);let invokeTimeout=opts.invokeTimeout?Number.parseInt(String(opts.invokeTimeout),10):void 0,invokeParams={nodeId,command:`system.notify`,params:{title,body,sound:opts.sound,priority:opts.priority,delivery:opts.delivery},idempotencyKey:String(opts.idempotencyKey??randomIdempotencyKey())};typeof invokeTimeout==`number`&&Number.isFinite(invokeTimeout)&&(invokeParams.timeoutMs=invokeTimeout);let result=await callGatewayCli(`node.invoke`,opts,invokeParams);if(opts.json){defaultRuntime.log(JSON.stringify(result,null,2));return}let{ok}=getNodesTheme();defaultRuntime.log(ok(`notify ok`))})}))}function renderPendingPairingRequestsTable(params){let{pending,now,tableWidth,theme}=params,rows=pending.map(r=>({Request:r.requestId,Node:r.displayName?.trim()?r.displayName.trim():r.nodeId,IP:r.remoteIp??``,Requested:typeof r.ts==`number`?formatTimeAgo(Math.max(0,now-r.ts)):theme.muted(`unknown`),Repair:r.isRepair?theme.warn(`yes`):``}));return{heading:theme.heading(`Pending`),table:renderTable({width:tableWidth,columns:[{key:`Request`,header:`Request`,minWidth:8},{key:`Node`,header:`Node`,minWidth:14,flex:!0},{key:`IP`,header:`IP`,minWidth:10},{key:`Requested`,header:`Requested`,minWidth:12},{key:`Repair`,header:`Repair`,minWidth:6}],rows}).trimEnd()}}function registerNodesPairingCommands(nodes){nodesCallOpts(nodes.command(`pending`).description(`List pending pairing requests`).action(async opts=>{await runNodesCommand(`pending`,async()=>{let{pending}=parsePairingList(await callGatewayCli(`node.pair.list`,opts,{}));if(opts.json){defaultRuntime.log(JSON.stringify(pending,null,2));return}if(pending.length===0){let{muted}=getNodesTheme();defaultRuntime.log(muted(`No pending pairing requests.`));return}let{heading,warn,muted}=getNodesTheme(),tableWidth=Math.max(60,(process.stdout.columns??120)-1),rendered=renderPendingPairingRequestsTable({pending,now:Date.now(),tableWidth,theme:{heading,warn,muted}});defaultRuntime.log(rendered.heading),defaultRuntime.log(rendered.table)})})),nodesCallOpts(nodes.command(`approve`).description(`Approve a pending pairing request`).argument(`<requestId>`,`Pending request id`).action(async(requestId,opts)=>{await runNodesCommand(`approve`,async()=>{let result=await callGatewayCli(`node.pair.approve`,opts,{requestId});defaultRuntime.log(JSON.stringify(result,null,2))})})),nodesCallOpts(nodes.command(`reject`).description(`Reject a pending pairing request`).argument(`<requestId>`,`Pending request id`).action(async(requestId,opts)=>{await runNodesCommand(`reject`,async()=>{let result=await callGatewayCli(`node.pair.reject`,opts,{requestId});defaultRuntime.log(JSON.stringify(result,null,2))})})),nodesCallOpts(nodes.command(`rename`).description(`Rename a paired node (display name override)`).requiredOption(`--node <idOrNameOrIp>`,`Node id, name, or IP`).requiredOption(`--name <displayName>`,`New display name`).action(async opts=>{await runNodesCommand(`rename`,async()=>{let nodeId=await resolveNodeId(opts,String(opts.node??``)),name=String(opts.name??``).trim();if(!nodeId||!name){defaultRuntime.error(`--node and --name required`),defaultRuntime.exit(1);return}let result=await callGatewayCli(`node.rename`,opts,{nodeId,displayName:name});if(opts.json){defaultRuntime.log(JSON.stringify(result,null,2));return}let{ok}=getNodesTheme();defaultRuntime.log(ok(`node rename ok: ${nodeId} -> ${name}`))})}))}function normalizeEnvironment(value){if(typeof value!=`string`)return null;let normalized=value.trim().toLowerCase();return normalized===`sandbox`||normalized===`production`?normalized:null}function registerNodesPushCommand(nodes){nodesCallOpts(nodes.command(`push`).description(`Send an APNs test push to an iOS node`).requiredOption(`--node <idOrNameOrIp>`,`Node id, name, or IP`).option(`--title <text>`,`Push title`,`BuilderForceAgents`).option(`--body <text>`,`Push body`).option(`--environment <sandbox|production>`,`Override APNs environment`).action(async opts=>{await runNodesCommand(`push`,async()=>{let nodeId=await resolveNodeId(opts,String(opts.node??``)),title=String(opts.title??``).trim()||`BuilderForceAgents`,body=String(opts.body??``).trim()||`Push test for node ${nodeId}`,environment=normalizeEnvironment(opts.environment);if(opts.environment&&!environment)throw Error(`invalid --environment (use sandbox|production)`);let params={nodeId,title,body};environment&&(params.environment=environment);let result=await callGatewayCli(`push.test`,opts,params);if(opts.json){defaultRuntime.log(JSON.stringify(result,null,2));return}let parsed=typeof result==`object`&&result?result:{},ok=parsed.ok===!0,status=typeof parsed.status==`number`?parsed.status:0,reason=typeof parsed.reason==`string`&&parsed.reason.trim().length>0?parsed.reason.trim():void 0,env=typeof parsed.environment==`string`&&parsed.environment.trim().length>0?parsed.environment.trim():`unknown`,{ok:okLabel,error:errorLabel}=getNodesTheme(),label=ok?okLabel:errorLabel;defaultRuntime.log(label(`push.test status=${status} ok=${ok} env=${env}`)),reason&&defaultRuntime.log(`reason: ${reason}`)})}),{timeoutMs:25e3})}function registerNodesScreenCommands(nodes){nodesCallOpts(nodes.command(`screen`).description(`Capture screen recordings from a paired node`).command(`record`).description(`Capture a short screen recording from a node (prints MEDIA:<path>)`).requiredOption(`--node <idOrNameOrIp>`,`Node id, name, or IP`).option(`--screen <index>`,`Screen index (0 = primary)`,`0`).option(`--duration <ms|10s>`,`Clip duration (ms or 10s)`,`10000`).option(`--fps <fps>`,`Frames per second`,`10`).option(`--no-audio`,`Disable microphone audio capture`).option(`--out <path>`,`Output path`).option(`--invoke-timeout <ms>`,`Node invoke timeout in ms (default 120000)`,`120000`).action(async opts=>{await runNodesCommand(`screen record`,async()=>{let nodeId=await resolveNodeId(opts,String(opts.node??``)),durationMs=parseDurationMs(opts.duration??``),screenIndex=Number.parseInt(String(opts.screen??`0`),10),fps=Number.parseFloat(String(opts.fps??`10`)),timeoutMs=opts.invokeTimeout?Number.parseInt(String(opts.invokeTimeout),10):void 0,raw=await callGatewayCli(`node.invoke`,opts,buildNodeInvokeParams({nodeId,command:`screen.record`,params:{durationMs:Number.isFinite(durationMs)?durationMs:void 0,screenIndex:Number.isFinite(screenIndex)?screenIndex:void 0,fps:Number.isFinite(fps)?fps:void 0,format:`mp4`,includeAudio:opts.audio!==!1},timeoutMs})),parsed=parseScreenRecordPayload((typeof raw==`object`&&raw?raw:{}).payload),written=await writeScreenRecordToFile(opts.out??screenRecordTempPath({ext:parsed.format||`mp4`}),parsed.base64);if(opts.json){defaultRuntime.log(JSON.stringify({file:{path:written.path,durationMs:parsed.durationMs,fps:parsed.fps,screenIndex:parsed.screenIndex,hasAudio:parsed.hasAudio}},null,2));return}defaultRuntime.log(`MEDIA:${shortenHomePath(written.path)}`)})}),{timeoutMs:18e4})}function formatVersionLabel(raw){let trimmed=raw.trim();return trimmed?trimmed.toLowerCase().startsWith(`v`)?trimmed:/^\d/.test(trimmed)?`v${trimmed}`:trimmed:raw}function resolveNodeVersions(node){let core=node.coreVersion?.trim()||void 0,ui=node.uiVersion?.trim()||void 0;if(core||ui)return{core,ui};let legacy=node.version?.trim();if(!legacy)return{core:void 0,ui:void 0};let platform=node.platform?.trim().toLowerCase()??``;return platform===`darwin`||platform===`linux`||platform===`win32`||platform===`windows`?{core:legacy,ui:void 0}:{core:void 0,ui:legacy}}function formatNodeVersions(node){let{core,ui}=resolveNodeVersions(node),parts=[];return core&&parts.push(`core ${formatVersionLabel(core)}`),ui&&parts.push(`ui ${formatVersionLabel(ui)}`),parts.length>0?parts.join(` · `):null}function formatPathEnv(raw){if(typeof raw!=`string`)return null;let trimmed=raw.trim();if(!trimmed)return null;let parts=trimmed.split(`:`).filter(Boolean);return shortenHomeInString(parts.length<=3?trimmed:`${parts.slice(0,2).join(`:`)}:…:${parts.slice(-1)[0]}`)}function parseSinceMs(raw,label){if(raw==null)return;let value=typeof raw==`string`?raw.trim():typeof raw==`number`?String(raw).trim():null;if(value===null){defaultRuntime.error(`${label}: invalid duration value`),defaultRuntime.exit(1);return}if(value)try{return parseDurationMs(value)}catch(err){let message=err instanceof Error?err.message:String(err);defaultRuntime.error(`${label}: ${message}`),defaultRuntime.exit(1);return}}function registerNodesStatusCommands(nodes){nodesCallOpts(nodes.command(`status`).description(`List known nodes with connection status and capabilities`).option(`--connected`,`Only show connected nodes`).option(`--last-connected <duration>`,`Only show nodes connected within duration (e.g. 24h)`).action(async opts=>{await runNodesCommand(`status`,async()=>{let connectedOnly=!!opts.connected,sinceMs=parseSinceMs(opts.lastConnected,`Invalid --last-connected`),result=await callGatewayCli(`node.list`,opts,{}),obj=typeof result==`object`&&result?result:{},{ok,warn,muted}=getNodesTheme(),tableWidth=Math.max(60,(process.stdout.columns??120)-1),now=Date.now(),nodes=parseNodeList(result),lastConnectedById=sinceMs===void 0?null:new Map(parsePairingList(await callGatewayCli(`node.pair.list`,opts,{})).paired.map(entry=>[entry.nodeId,entry])),filtered=nodes.filter(n=>{if(connectedOnly&&!n.connected)return!1;if(sinceMs!==void 0){let paired=lastConnectedById?.get(n.nodeId),lastConnectedAtMs=typeof paired?.lastConnectedAtMs==`number`?paired.lastConnectedAtMs:typeof n.connectedAtMs==`number`?n.connectedAtMs:void 0;if(typeof lastConnectedAtMs!=`number`||now-lastConnectedAtMs>sinceMs)return!1}return!0});if(opts.json){let ts=typeof obj.ts==`number`?obj.ts:Date.now();defaultRuntime.log(JSON.stringify({...obj,ts,nodes:filtered},null,2));return}let pairedCount=filtered.filter(n=>!!n.paired).length,connectedCount=filtered.filter(n=>!!n.connected).length,filteredLabel=filtered.length===nodes.length?``:` (of ${nodes.length})`;if(defaultRuntime.log(`Known: ${filtered.length}${filteredLabel} · Paired: ${pairedCount} · Connected: ${connectedCount}`),filtered.length===0)return;let rows=filtered.map(n=>{let name=n.displayName?.trim()?n.displayName.trim():n.nodeId,perms=formatPermissions(n.permissions),versions=formatNodeVersions(n),pathEnv=formatPathEnv(n.pathEnv),detailParts=[n.deviceFamily?`device: ${n.deviceFamily}`:null,n.modelIdentifier?`hw: ${n.modelIdentifier}`:null,perms?`perms: ${perms}`:null,versions,pathEnv?`path: ${pathEnv}`:null].filter(Boolean),caps=Array.isArray(n.caps)?n.caps.map(String).filter(Boolean).toSorted().join(`, `):`?`,paired=n.paired?ok(`paired`):warn(`unpaired`),connected=n.connected?ok(`connected`):muted(`disconnected`),since=typeof n.connectedAtMs==`number`?` (${formatTimeAgo(Math.max(0,now-n.connectedAtMs))})`:``;return{Node:name,ID:n.nodeId,IP:n.remoteIp??``,Detail:detailParts.join(` · `),Status:`${paired} · ${connected}${since}`,Caps:caps}});defaultRuntime.log(renderTable({width:tableWidth,columns:[{key:`Node`,header:`Node`,minWidth:14,flex:!0},{key:`ID`,header:`ID`,minWidth:10},{key:`IP`,header:`IP`,minWidth:10},{key:`Detail`,header:`Detail`,minWidth:18,flex:!0},{key:`Status`,header:`Status`,minWidth:18},{key:`Caps`,header:`Caps`,minWidth:12,flex:!0}],rows}).trimEnd())})})),nodesCallOpts(nodes.command(`describe`).description(`Describe a node (capabilities + supported invoke commands)`).requiredOption(`--node <idOrNameOrIp>`,`Node id, name, or IP`).action(async opts=>{await runNodesCommand(`describe`,async()=>{let nodeId=await resolveNodeId(opts,String(opts.node??``)),result=await callGatewayCli(`node.describe`,opts,{nodeId});if(opts.json){defaultRuntime.log(JSON.stringify(result,null,2));return}let obj=typeof result==`object`&&result?result:{},displayName=typeof obj.displayName==`string`?obj.displayName:nodeId,connected=!!obj.connected,paired=!!obj.paired,caps=Array.isArray(obj.caps)?obj.caps.map(String).filter(Boolean).toSorted():null,commands=Array.isArray(obj.commands)?obj.commands.map(String).filter(Boolean).toSorted():[],perms=formatPermissions(obj.permissions),family=typeof obj.deviceFamily==`string`?obj.deviceFamily:null,model=typeof obj.modelIdentifier==`string`?obj.modelIdentifier:null,ip=typeof obj.remoteIp==`string`?obj.remoteIp:null,pathEnv=typeof obj.pathEnv==`string`?obj.pathEnv:null,versions=formatNodeVersions(obj),{heading,ok,warn,muted}=getNodesTheme(),status=`${paired?ok(`paired`):warn(`unpaired`)} · ${connected?ok(`connected`):muted(`disconnected`)}`,tableWidth=Math.max(60,(process.stdout.columns??120)-1),rows=[{Field:`ID`,Value:nodeId},displayName?{Field:`Name`,Value:displayName}:null,ip?{Field:`IP`,Value:ip}:null,family?{Field:`Device`,Value:family}:null,model?{Field:`Model`,Value:model}:null,perms?{Field:`Perms`,Value:perms}:null,versions?{Field:`Version`,Value:versions}:null,pathEnv?{Field:`PATH`,Value:pathEnv}:null,{Field:`Status`,Value:status},{Field:`Caps`,Value:caps?caps.join(`, `):`?`}].filter(Boolean);if(defaultRuntime.log(heading(`Node`)),defaultRuntime.log(renderTable({width:tableWidth,columns:[{key:`Field`,header:`Field`,minWidth:8},{key:`Value`,header:`Value`,minWidth:24,flex:!0}],rows}).trimEnd()),defaultRuntime.log(``),defaultRuntime.log(heading(`Commands`)),commands.length===0){defaultRuntime.log(muted(`- (none reported)`));return}for(let c of commands)defaultRuntime.log(`- ${c}`)})})),nodesCallOpts(nodes.command(`list`).description(`List pending and paired nodes`).option(`--connected`,`Only show connected nodes`).option(`--last-connected <duration>`,`Only show nodes connected within duration (e.g. 24h)`).action(async opts=>{await runNodesCommand(`list`,async()=>{let connectedOnly=!!opts.connected,sinceMs=parseSinceMs(opts.lastConnected,`Invalid --last-connected`),{pending,paired}=parsePairingList(await callGatewayCli(`node.pair.list`,opts,{})),{heading,muted,warn}=getNodesTheme(),tableWidth=Math.max(60,(process.stdout.columns??120)-1),now=Date.now(),hasFilters=connectedOnly||sinceMs!==void 0,pendingRows=hasFilters?[]:pending,connectedById=hasFilters?new Map(parseNodeList(await callGatewayCli(`node.list`,opts,{})).map(node=>[node.nodeId,node])):null,filteredPaired=paired.filter(node=>{if(connectedOnly&&!connectedById?.get(node.nodeId)?.connected)return!1;if(sinceMs!==void 0){let live=connectedById?.get(node.nodeId),lastConnectedAtMs=typeof node.lastConnectedAtMs==`number`?node.lastConnectedAtMs:typeof live?.connectedAtMs==`number`?live.connectedAtMs:void 0;if(typeof lastConnectedAtMs!=`number`||now-lastConnectedAtMs>sinceMs)return!1}return!0}),filteredLabel=hasFilters&&filteredPaired.length!==paired.length?` (of ${paired.length})`:``;if(defaultRuntime.log(`Pending: ${pendingRows.length} · Paired: ${filteredPaired.length}${filteredLabel}`),opts.json){defaultRuntime.log(JSON.stringify({pending:pendingRows,paired:filteredPaired},null,2));return}if(pendingRows.length>0){let rendered=renderPendingPairingRequestsTable({pending:pendingRows,now,tableWidth,theme:{heading,warn,muted}});defaultRuntime.log(``),defaultRuntime.log(rendered.heading),defaultRuntime.log(rendered.table)}if(filteredPaired.length>0){let pairedRows=filteredPaired.map(n=>{let live=connectedById?.get(n.nodeId),lastConnectedAtMs=typeof n.lastConnectedAtMs==`number`?n.lastConnectedAtMs:typeof live?.connectedAtMs==`number`?live.connectedAtMs:void 0;return{Node:n.displayName?.trim()?n.displayName.trim():n.nodeId,Id:n.nodeId,IP:n.remoteIp??``,LastConnect:typeof lastConnectedAtMs==`number`?formatTimeAgo(Math.max(0,now-lastConnectedAtMs)):muted(`unknown`)}});defaultRuntime.log(``),defaultRuntime.log(heading(`Paired`)),defaultRuntime.log(renderTable({width:tableWidth,columns:[{key:`Node`,header:`Node`,minWidth:14,flex:!0},{key:`Id`,header:`ID`,minWidth:10},{key:`IP`,header:`IP`,minWidth:10},{key:`LastConnect`,header:`Last Connect`,minWidth:14}],rows:pairedRows}).trimEnd())}})}))}function registerNodesCli(program){let nodes=program.command(`nodes`).description(`Manage gateway-owned nodes (pairing, status, invoke, and media)`).addHelpText(`after`,()=>`\n${theme.heading(`Examples:`)}\n${formatHelpExamples([[`builderforce nodes status`,`List known nodes with live status.`],[`builderforce nodes pairing pending`,`Show pending node pairing requests.`],[`builderforce nodes run --node <id> --raw "uname -a"`,`Run a shell command on a node.`],[`builderforce nodes camera snap --node <id>`,`Capture a photo from a node camera.`]])}\n\n${theme.muted(`Docs:`)} ${formatDocsLink(`/cli/nodes`,`docs.builderforce.ai/cli/nodes`)}\n`);registerNodesStatusCommands(nodes),registerNodesPairingCommands(nodes),registerNodesInvokeCommands(nodes),registerNodesNotifyCommand(nodes),registerNodesPushCommand(nodes),registerNodesCanvasCommands(nodes),registerNodesCameraCommands(nodes),registerNodesScreenCommands(nodes),registerNodesLocationCommands(nodes)}export{registerNodesCli};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{u as resolveGatewayPort}from"./paths-BHg-VHB4.js";import{S as shortenHomePath,y as resolveUserPath}from"./utils-BP60e80M.js";import{p as defaultRuntime}from"./subsystem-C4b1Von0.js";import{Qt as normalizeSecretInput,R as normalizeProviderId,Yt as resolveEnvApiKey,Zt as normalizeOptionalSecretInput,b as ensureAuthProfileStore,s as resolveApiKeyForProfile,t as resolveAuthProfileOrder,v as upsertAuthProfile}from"./auth-profiles-
|
|
1
|
+
import{u as resolveGatewayPort}from"./paths-BHg-VHB4.js";import{S as shortenHomePath,y as resolveUserPath}from"./utils-BP60e80M.js";import{p as defaultRuntime}from"./subsystem-C4b1Von0.js";import{Qt as normalizeSecretInput,R as normalizeProviderId,Yt as resolveEnvApiKey,Zt as normalizeOptionalSecretInput,b as ensureAuthProfileStore,s as resolveApiKeyForProfile,t as resolveAuthProfileOrder,v as upsertAuthProfile}from"./auth-profiles-pt7Tr4HA.js";import{t as formatCliCommand}from"./command-format-DTMaGKs7.js";import{a as upsertSharedEnvVar}from"./env-file-DeS6x2OL.js";import{a as readConfigFileSnapshot,c as writeConfigFile,y as parseDurationMs}from"./io-D9hC2aG0.js";import{a as ensureWorkspaceAndSessions,b as waitForGatewayReachable,c as handleReset,g as resolveControlUiLinks,m as randomToken,n as applyWizardMetadata,t as DEFAULT_WORKSPACE}from"./onboard-helpers-Ce_c4Raj.js";import{a as gatewayInstallErrorHint,i as buildGatewayInstallPlan,r as isGatewayDaemonRuntime,t as DEFAULT_GATEWAY_DAEMON_RUNTIME}from"./daemon-runtime-Dx800VUt.js";import{t as assertSupportedRuntime}from"./runtime-guard-Bi8k55v9.js";import{r as isSystemdUserServiceAvailable}from"./systemd-DdVd5Yet.js";import{t as resolveGatewayService}from"./service-EKJG69M3.js";import{r as healthCommand}from"./health-zrsgFZmR.js";import{C as setXaiApiKey,S as setVercelAiGatewayApiKey,T as setZaiApiKey,_ as setOpenrouterApiKey,b as setTogetherApiKey,c as setAnthropicApiKey,d as setHuggingfaceApiKey,f as setKimiCodingApiKey,g as setOpencodeZenApiKey,h as setMoonshotApiKey,l as setCloudflareAiGatewayConfig,m as setMinimaxApiKey,p as setLitellmApiKey,u as setGeminiApiKey,v as setQianfanApiKey,w as setXiaomiApiKey,x as setVeniceApiKey,y as setSyntheticApiKey}from"./onboard-auth.credentials-DneFSdYg.js";import{A as applyXaiConfig,B as applyVercelAiGatewayConfig,E as applyTogetherConfig,H as applyAgentDefaultModelPrimary,I as applyLitellmConfig,M as applyXiaomiConfig,O as applyVeniceConfig,P as applyZaiConfig,R as applyCloudflareAiGatewayConfig,S as applyQianfanConfig,_ as applyMoonshotConfigCn,a as applyMinimaxApiConfig,b as applyOpenrouterConfig,d as applyAuthProfileConfig,f as applyHuggingfaceConfig,g as applyMoonshotConfig,l as applyMinimaxConfig,m as applyKimiCodeConfig,n as validateAnthropicSetupToken,o as applyMinimaxApiConfigCn,r as applyOpencodeZenConfig,t as buildTokenProfileId,w as applySyntheticConfig}from"./auth-token-BPHeoBAW.js";import{n as logConfigUpdated}from"./logging-ayt7F7vy.js";import{n as isDeprecatedAuthChoice,r as normalizeLegacyOnboardAuthChoice}from"./auth-choice-legacy-CgUsZOdE.js";import{i as detectZaiEndpoint,n as applyOpenAIConfig,o as applyGoogleGeminiModelDefault}from"./openai-model-default-pfoEzWYJ.js";import{n as ensureSystemdUserLingerNonInteractive}from"./systemd-linger-CPKngdUf.js";import{a as resolveCustomProviderId,n as applyCustomApiConfig,r as parseNonInteractiveCustomApiFlags,t as CustomApiError}from"./onboard-custom-BYIza2e7.js";import{t as runInteractiveOnboarding}from"./onboard-interactive-Cl2K3EYn.js";import{t as applyOnboardingLocalWorkspaceConfig}from"./onboard-config-BUzUtfP0.js";const ONBOARD_PROVIDER_AUTH_FLAGS=[{optionKey:`anthropicApiKey`,authChoice:`apiKey`,cliFlag:`--anthropic-api-key`,cliOption:`--anthropic-api-key <key>`,description:`Anthropic API key`},{optionKey:`openaiApiKey`,authChoice:`openai-api-key`,cliFlag:`--openai-api-key`,cliOption:`--openai-api-key <key>`,description:`OpenAI API key`},{optionKey:`openrouterApiKey`,authChoice:`openrouter-api-key`,cliFlag:`--openrouter-api-key`,cliOption:`--openrouter-api-key <key>`,description:`OpenRouter API key`},{optionKey:`aiGatewayApiKey`,authChoice:`ai-gateway-api-key`,cliFlag:`--ai-gateway-api-key`,cliOption:`--ai-gateway-api-key <key>`,description:`Vercel AI Gateway API key`},{optionKey:`cloudflareAiGatewayApiKey`,authChoice:`cloudflare-ai-gateway-api-key`,cliFlag:`--cloudflare-ai-gateway-api-key`,cliOption:`--cloudflare-ai-gateway-api-key <key>`,description:`Cloudflare AI Gateway API key`},{optionKey:`moonshotApiKey`,authChoice:`moonshot-api-key`,cliFlag:`--moonshot-api-key`,cliOption:`--moonshot-api-key <key>`,description:`Moonshot API key`},{optionKey:`kimiCodeApiKey`,authChoice:`kimi-code-api-key`,cliFlag:`--kimi-code-api-key`,cliOption:`--kimi-code-api-key <key>`,description:`Kimi Coding API key`},{optionKey:`geminiApiKey`,authChoice:`gemini-api-key`,cliFlag:`--gemini-api-key`,cliOption:`--gemini-api-key <key>`,description:`Gemini API key`},{optionKey:`zaiApiKey`,authChoice:`zai-api-key`,cliFlag:`--zai-api-key`,cliOption:`--zai-api-key <key>`,description:`Z.AI API key`},{optionKey:`xiaomiApiKey`,authChoice:`xiaomi-api-key`,cliFlag:`--xiaomi-api-key`,cliOption:`--xiaomi-api-key <key>`,description:`Xiaomi API key`},{optionKey:`minimaxApiKey`,authChoice:`minimax-api`,cliFlag:`--minimax-api-key`,cliOption:`--minimax-api-key <key>`,description:`MiniMax API key`},{optionKey:`syntheticApiKey`,authChoice:`synthetic-api-key`,cliFlag:`--synthetic-api-key`,cliOption:`--synthetic-api-key <key>`,description:`Synthetic API key`},{optionKey:`veniceApiKey`,authChoice:`venice-api-key`,cliFlag:`--venice-api-key`,cliOption:`--venice-api-key <key>`,description:`Venice API key`},{optionKey:`togetherApiKey`,authChoice:`together-api-key`,cliFlag:`--together-api-key`,cliOption:`--together-api-key <key>`,description:`Together AI API key`},{optionKey:`huggingfaceApiKey`,authChoice:`huggingface-api-key`,cliFlag:`--huggingface-api-key`,cliOption:`--huggingface-api-key <key>`,description:`Hugging Face API key (HF token)`},{optionKey:`opencodeZenApiKey`,authChoice:`opencode-zen`,cliFlag:`--opencode-zen-api-key`,cliOption:`--opencode-zen-api-key <key>`,description:`OpenCode Zen API key`},{optionKey:`xaiApiKey`,authChoice:`xai-api-key`,cliFlag:`--xai-api-key`,cliOption:`--xai-api-key <key>`,description:`xAI API key`},{optionKey:`litellmApiKey`,authChoice:`litellm-api-key`,cliFlag:`--litellm-api-key`,cliOption:`--litellm-api-key <key>`,description:`LiteLLM API key`},{optionKey:`qianfanApiKey`,authChoice:`qianfan-api-key`,cliFlag:`--qianfan-api-key`,cliOption:`--qianfan-api-key <key>`,description:`QIANFAN API key`}];function hasStringValue(value){return typeof value==`string`?value.trim().length>0:!!value}function inferAuthChoiceFromFlags(opts){let matches=ONBOARD_PROVIDER_AUTH_FLAGS.filter(({optionKey})=>hasStringValue(opts[optionKey])).map(flag=>({optionKey:flag.optionKey,authChoice:flag.authChoice,label:flag.cliFlag}));return(hasStringValue(opts.customBaseUrl)||hasStringValue(opts.customModelId)||hasStringValue(opts.customApiKey))&&matches.push({optionKey:`customBaseUrl`,authChoice:`custom-api-key`,label:`--custom-base-url/--custom-model-id/--custom-api-key`}),{choice:matches[0]?.authChoice,matches}}async function resolveApiKeyFromProfiles(params){let store=await ensureAuthProfileStore(params.agentDir),order=resolveAuthProfileOrder({cfg:params.cfg,store,provider:params.provider});for(let profileId of order){if(store.profiles[profileId]?.type!==`api_key`)continue;let resolved=await resolveApiKeyForProfile({cfg:params.cfg,store,profileId,agentDir:params.agentDir});if(resolved?.apiKey)return resolved.apiKey}return null}async function resolveNonInteractiveApiKey(params){let flagKey=normalizeOptionalSecretInput(params.flagValue);if(flagKey)return{key:flagKey,source:`flag`};let envResolved=resolveEnvApiKey(params.provider);if(envResolved?.apiKey)return{key:envResolved.apiKey,source:`env`};let explicitEnvVar=params.envVarName?.trim();if(explicitEnvVar){let explicitEnvKey=normalizeOptionalSecretInput(process.env[explicitEnvVar]);if(explicitEnvKey)return{key:explicitEnvKey,source:`env`}}if(params.allowProfile??!0){let profileKey=await resolveApiKeyFromProfiles({provider:params.provider,cfg:params.cfg,agentDir:params.agentDir});if(profileKey)return{key:profileKey,source:`profile`}}if(params.required===!1)return null;let profileHint=params.allowProfile===!1?``:`, or existing ${params.provider} API-key profile`;return params.runtime.error(`Missing ${params.flagName} (or ${params.envVar} in env${profileHint}).`),params.runtime.exit(1),null}async function applyNonInteractiveAuthChoice(params){let{authChoice,opts,runtime,baseConfig}=params,nextConfig=params.nextConfig;if(authChoice===`claude-cli`||authChoice===`codex-cli`)return runtime.error([`Auth choice "${authChoice}" is deprecated.`,`Use "--auth-choice builderforcellm" (recommended default), "--auth-choice token" (Anthropic setup-token), or "--auth-choice openai-codex".`].join(`
|
|
2
2
|
`)),runtime.exit(1),null;if(authChoice===`setup-token`)return runtime.error([`Auth choice "setup-token" requires interactive mode.`,`Use "--auth-choice token" with --token and --token-provider anthropic.`].join(`
|
|
3
3
|
`)),runtime.exit(1),null;if(authChoice===`local`)return runtime.error([`Auth choice "local" requires interactive mode.`,`Use interactive onboard/configure for guided local Ollama or llama.cpp/vLLM setup.`].join(`
|
|
4
4
|
`)),runtime.exit(1),null;if(authChoice===`vllm`)return runtime.error([`Auth choice "vllm" requires interactive mode.`,`Use interactive onboard/configure to enter base URL, API key, and model ID.`].join(`
|