@seanhogg/builderforce-agents 2026.10.12 → 2026.10.13
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/{agent-DvDtjczG.js → agent-CeWx2EpQ.js} +1 -1
- package/dist/{agent-DiLX8OzY.js → agent-DrcnpqOF.js} +1 -1
- package/dist/{agents-BawpdEjP.js → agents-CRJM6qhK.js} +1 -1
- package/dist/{agents-COWLUJqm.js → agents-hATFRfwk.js} +1 -1
- package/dist/{audio-preflight-CYQiI74L.js → audio-preflight-B9CfGDD2.js} +1 -1
- package/dist/{audio-preflight-BN1u9Tpc.js → audio-preflight-DHHeocUj.js} +1 -1
- package/dist/{auth-choice-D9VN-WjA.js → auth-choice-CWbPLRN0.js} +1 -1
- package/dist/{auth-choice-3cdcHeim.js → auth-choice-CzhKgWJy.js} +1 -1
- package/dist/{auth-choice.apply-Cd0RR0Z-.js → auth-choice.apply-C0RTYtRN.js} +1 -1
- package/dist/{auth-choice.apply-CMDgoDNN.js → auth-choice.apply-ChrTTHkK.js} +1 -1
- package/dist/{auth-choice.apply-BAeGyEKW.js → auth-choice.apply-D4LYzI8l.js} +1 -1
- package/dist/{auth-choice.apply-CSXvPCea.js → auth-choice.apply-Dy4rVG6K.js} +1 -1
- package/dist/{auth-choice.apply.transformers-DkX2-OZa.js → auth-choice.apply.transformers-9v6HFzNs.js} +1 -1
- package/dist/{auth-choice.apply.transformers-CEVxl3ul.js → auth-choice.apply.transformers-Be8599JD.js} +1 -1
- package/dist/{auth-choice.apply.transformers-B2Nr9M7m.js → auth-choice.apply.transformers-CgfGlqy1.js} +1 -1
- package/dist/{auth-choice.apply.transformers-Dpy9gODo.js → auth-choice.apply.transformers-D9a8-sLS.js} +1 -1
- package/dist/{banner-C93QSUTe.js → banner-8F7-gU1V.js} +1 -1
- package/dist/build-info.json +3 -3
- package/dist/{builderforce-Dl4bZ63C.js → builderforce-CCfM1c79.js} +1 -1
- package/dist/{builderforce-C_tuO46t.js → builderforce-CImLd8Zo.js} +1 -1
- package/dist/bundled/boot-md/handler.js +1 -1
- package/dist/bundled/session-memory/handler.js +1 -1
- package/dist/{channel-options-CiYpNR-1.js → channel-options-CRng-5hZ.js} +1 -1
- package/dist/{channel-options-Cziy0WDc.js → channel-options-D5kOIN7b.js} +1 -1
- package/dist/{channel-web-Ae15MleJ.js → channel-web-B5HSpL4k.js} +1 -1
- package/dist/{channels-cli-CZM033Me.js → channels-cli-COl9TDHT.js} +1 -1
- package/dist/{channels-cli-yi1vxpvO.js → channels-cli-bR8QwOv3.js} +1 -1
- package/dist/chrome-ChzFLAeJ.js +4 -0
- package/dist/chrome-CrqJ4Ijz.js +4 -0
- package/dist/{cli-Bwv_-VuS.js → cli-BqJMHFNK.js} +1 -1
- package/dist/{cli-D8fndSEi.js → cli-DBn0qbHS.js} +1 -1
- package/dist/{command-registry-Cjom5ab0.js → command-registry-BqhtXJa7.js} +1 -1
- package/dist/{command-registry-8uEx2JjY.js → command-registry-DVH79C3B.js} +1 -1
- package/dist/{completion-cli-PTFpWp8Q.js → completion-cli-BFR0u1Uh.js} +1 -1
- package/dist/{completion-cli-LUuqgvVQ.js → completion-cli-BuUAEqQw.js} +1 -1
- package/dist/{completion-cli-DRsz70D2.js → completion-cli-CwaIh4zw.js} +1 -1
- package/dist/{completion-cli-BsXDz7T2.js → completion-cli-Da3-oE7r.js} +1 -1
- package/dist/{config-cli-BIx0enD5.js → config-cli-Bhrj7H1i.js} +1 -1
- package/dist/{config-cli-BFhOXrua.js → config-cli-DOHKZ1lO.js} +1 -1
- package/dist/{configure-D96xLIb6.js → configure-B-Yta1X3.js} +1 -1
- package/dist/{configure-S7YE6hn1.js → configure-BHVk4Ax9.js} +1 -1
- package/dist/{configure-dDKfCq_g.js → configure-D9YZEK_D.js} +1 -1
- package/dist/{configure-C7xdw9Kq.js → configure-DPE2hDzY.js} +1 -1
- package/dist/{deps-CGiO_NDu.js → deps-CrAVOWsA.js} +1 -1
- package/dist/{doctor-completion-ChhIrLd3.js → doctor-completion-CkjrUmbI.js} +1 -1
- package/dist/{doctor-completion-BUZwWoWB.js → doctor-completion-Dh9ah5lH.js} +1 -1
- package/dist/{embedded-DJYMy81Q.js → embedded-BrqzM5oT.js} +12 -12
- package/dist/{embedded-DjDnQMNx.js → embedded-wYxo-ADm.js} +12 -12
- package/dist/entry.js +1 -1
- package/dist/extensionAPI.js +1 -1
- package/dist/{gateway-cli-CN114d5j.js → gateway-cli-C2nh9UyY.js} +2 -2
- package/dist/{gateway-cli-Dzl70YBF.js → gateway-cli-CGkTLhet.js} +2 -2
- package/dist/{health-Cf1YoTRN.js → health-CEz2-7et.js} +1 -1
- package/dist/{health-AlkF1nUa.js → health-CFVx21sO.js} +1 -1
- package/dist/{health-ySVOGGNu.js → health-aKuq4xwa.js} +1 -1
- package/dist/{hooks-cli-6jeFEGg3.js → hooks-cli-DPSrycwI.js} +1 -1
- package/dist/{hooks-cli-DVPMCXUq.js → hooks-cli-uPHs7qnC.js} +1 -1
- package/dist/index.js +2 -2
- package/dist/llm-slug-generator.js +1 -1
- package/dist/{models-CGUxphfN.js → models--TwKHn8b.js} +1 -1
- package/dist/{models-CIMM_Z3u.js → models-BXJebxTU.js} +1 -1
- package/dist/{models-cli-Cijh2uON.js → models-cli-O1zCgeoA.js} +1 -1
- package/dist/{models-cli-Oys3e_I3.js → models-cli-iKu1IVeH.js} +1 -1
- package/dist/{onboard-DAEXNhNd.js → onboard--0I8pdee.js} +1 -1
- package/dist/{onboard-b2fWbf0Q.js → onboard-C40OvMZO.js} +1 -1
- package/dist/{onboard-channels-elaccQRE.js → onboard-channels-BbpyejX4.js} +1 -1
- package/dist/{onboard-channels-Bsd11scA.js → onboard-channels-CoJnsCfd.js} +1 -1
- package/dist/{onboard-channels-C_Q7OUow.js → onboard-channels-ZI4QC9WU.js} +1 -1
- package/dist/{onboard-channels-Tl1X4Pl_.js → onboard-channels-uvIeLPXK.js} +1 -1
- package/dist/{onboard-interactive-DyGNiYRI.js → onboard-interactive-B3Z0XLT6.js} +1 -1
- package/dist/{onboard-interactive-C0qmgHsH.js → onboard-interactive-CJdxqQ1b.js} +1 -1
- package/dist/{onboard-interactive-86s992_v.js → onboard-interactive-COnCCTTW.js} +1 -1
- package/dist/{onboard-interactive-CvMSTjPK.js → onboard-interactive-jss8R9r9.js} +1 -1
- package/dist/{onboarding-DzvbhsaR.js → onboarding-B1BmYWrs.js} +2 -2
- package/dist/{onboarding-B0tbaqZ7.js → onboarding-CdRbvLgp.js} +2 -2
- package/dist/{onboarding.finalize-D-Pi9Blv.js → onboarding.finalize-B0AjF6qZ.js} +1 -1
- package/dist/{onboarding.finalize-CERLBlRF.js → onboarding.finalize-WsL-ijTc.js} +1 -1
- package/dist/{outbound-send-deps-CzhBrVa7.js → outbound-send-deps-DuML6h7r.js} +1 -1
- package/dist/{plugin-registry-DtrHn5NR.js → plugin-registry-BjWNyeVY.js} +1 -1
- package/dist/{plugin-registry-Avx51RIY.js → plugin-registry-Cf_sv-ny.js} +1 -1
- package/dist/{plugin-registry-CFkQDTOt.js → plugin-registry-DdFb5usc.js} +1 -1
- package/dist/{plugin-registry-BEmyRfmb.js → plugin-registry-DrEpL5ac.js} +1 -1
- package/dist/plugin-sdk/{accounts-BwreSNAR.js → accounts-Cy3WCbWg.js} +1 -1
- package/dist/plugin-sdk/{active-listener-DpQ7aGYd.js → active-listener-DVWVNlT9.js} +1 -1
- package/dist/plugin-sdk/agent-runtime/src/agents/tool-retry.d.ts +40 -32
- package/dist/plugin-sdk/agent-runtime/src/builderforce/model/agent-types.d.ts +6 -0
- package/dist/plugin-sdk/{agent-scope-BQByW0cD.js → agent-scope-DgKN27hJ.js} +1 -1
- package/dist/plugin-sdk/{api-key-rotation-yqTCeKjV.js → api-key-rotation-D37jV9ZW.js} +1 -1
- package/dist/plugin-sdk/{audio-preflight-B6uTvVfA.js → audio-preflight-D4xyO8Zq.js} +1 -1
- package/dist/plugin-sdk/{auth-json-Dw6ij9Pa.js → auth-json-nASe57Uw.js} +1 -1
- package/dist/plugin-sdk/{bindings-CDEzl4kl.js → bindings-CH-YLOLC.js} +1 -1
- package/dist/plugin-sdk/{channel-web-DKbpA9xC.js → channel-web-huZSNTX3.js} +1 -1
- package/dist/plugin-sdk/{chrome-DriEqJRH.js → chrome-CRUzg3kA.js} +1 -1
- package/dist/plugin-sdk/{chunk-cW0POl22.js → chunk-C94IAOuf.js} +1 -1
- package/dist/plugin-sdk/{command-format-CAX9XFjI.js → command-format-B3XMq_73.js} +1 -1
- package/dist/plugin-sdk/{common-BxEWhN2X.js → common-n0l_XN-S.js} +1 -1
- package/dist/plugin-sdk/{config-3vPn_hmp.js → config--Ci8Y91R.js} +2 -2
- package/dist/plugin-sdk/{fetch-DH0Y8iyO.js → fetch-B-GxSYRO.js} +1 -1
- package/dist/plugin-sdk/index.js +1 -1
- package/dist/plugin-sdk/{login-Dhdx0bVL.js → login-DZliYZg8.js} +1 -1
- package/dist/plugin-sdk/{login-qr-DAjOuijP.js → login-qr-DKcGvAjv.js} +1 -1
- package/dist/plugin-sdk/{manager-i8psl2Er.js → manager-DioOqJm_.js} +1 -1
- package/dist/plugin-sdk/{markdown-tables-Epim9b-0.js → markdown-tables-BUfhHgfs.js} +1 -1
- package/dist/plugin-sdk/{message-channel-sBPQc_-T.js → message-channel-CuZ2xOAM.js} +1 -1
- package/dist/plugin-sdk/{model-catalog-COVRezOQ.js → model-catalog-DIQ5a-o4.js} +1 -1
- package/dist/plugin-sdk/{model-selection-Crz-xYNU.js → model-selection-_H_U9jWH.js} +1 -1
- package/dist/plugin-sdk/{outbound-CPutSvae.js → outbound-Djibdmi7.js} +1 -1
- package/dist/plugin-sdk/{plugins-CaUOZBVb.js → plugins-BdkC9v5E.js} +1 -1
- package/dist/plugin-sdk/{pw-ai-jI9AWvKe.js → pw-ai-Bbi8Us-p.js} +1 -1
- package/dist/plugin-sdk/{qmd-manager-BRe5fGZw.js → qmd-manager-Dxn0jCpE.js} +1 -1
- package/dist/plugin-sdk/{registry-DJq2Cvo9.js → registry-CZHRcH-q.js} +1 -1
- package/dist/plugin-sdk/{render-BUCRXPIk.js → render-CuA_WRX5.js} +1 -1
- package/dist/plugin-sdk/{replies-CYjI7bye.js → replies-Cf69aZLA.js} +1 -1
- package/dist/plugin-sdk/{reply-B5o-SSYy.js → reply-BOVC-7UD.js} +13 -13
- package/dist/plugin-sdk/{reply-prefix-CCymsmsP.js → reply-prefix-w7kAvH11.js} +1 -1
- package/dist/plugin-sdk/{resolve-route-DN1J7Wyc.js → resolve-route-0sbvl4ZN.js} +1 -1
- package/dist/plugin-sdk/{runner-C2pDJlRw.js → runner-DKoKK09-.js} +4 -4
- package/dist/plugin-sdk/{session-BnleckVX.js → session-DGLuyt10.js} +1 -1
- package/dist/plugin-sdk/{sqlite-BlMLqMl8.js → sqlite-JjFgDV-H.js} +1 -1
- package/dist/plugin-sdk/{subsystem-COTa5Ly_.js → subsystem-D0Ril4rt.js} +1 -1
- package/dist/plugin-sdk/{tool-images-DSpchb4x.js → tool-images-WRTP95FT.js} +1 -1
- package/dist/plugin-sdk/{tool-loop-detection-16p7mJ8N.js → tool-loop-detection-g8gPTCgJ.js} +1 -1
- package/dist/plugin-sdk/web-Cdu8TkUy.js +1 -0
- package/dist/plugin-sdk/{whatsapp-actions-C2B3iw8n.js → whatsapp-actions-CsSzy7G0.js} +1 -1
- package/dist/{plugins-DAlgx58e.js → plugins-Dr1wmnAf.js} +1 -1
- package/dist/{plugins-De7aK3yK.js → plugins-JhEblShx.js} +1 -1
- package/dist/{plugins-cli-CwdUVWjG.js → plugins-cli-DW4hoeeV.js} +1 -1
- package/dist/{plugins-cli-CfVCrrhx.js → plugins-cli-GewV3E8e.js} +1 -1
- package/dist/{program-CFL6mW3l.js → program-bggmBKuL.js} +2 -2
- package/dist/{program-context-DP4Xq9zC.js → program-context-BCTE8zEF.js} +1 -1
- package/dist/{prompt-select-styled-NxrGT7OR.js → prompt-select-styled-BtjhlTEH.js} +1 -1
- package/dist/{prompt-select-styled-Csz9HlSx.js → prompt-select-styled-CaNl41mG.js} +1 -1
- package/dist/{provider-auth-helpers-BMBw21Tn.js → provider-auth-helpers-CWUfg9zf.js} +1 -1
- package/dist/{provider-auth-helpers-VWPvSXPH.js → provider-auth-helpers-y1X8xKVE.js} +1 -1
- package/dist/{provider-dispatcher-CSOHd9zJ.js → provider-dispatcher-CRsPmKhJ.js} +1 -1
- package/dist/{provider-dispatcher-Bg9orQPy.js → provider-dispatcher-D9GbE_Ce.js} +1 -1
- package/dist/{push-apns-rMu8MKXi.js → push-apns-Cb1sQEEa.js} +1 -1
- package/dist/{push-apns-ep5WkyGz.js → push-apns-Cr-6aD3y.js} +1 -1
- package/dist/{pw-ai-UXo3gDGy.js → pw-ai-CG-kY5NP.js} +1 -1
- package/dist/{pw-ai-CIN6tj0G.js → pw-ai-DcZPg2vm.js} +1 -1
- package/dist/{register.agent-BynXVz7v.js → register.agent-B33EZBoL.js} +1 -1
- package/dist/{register.agent-RNVNKBP3.js → register.agent-DfYqZls1.js} +1 -1
- package/dist/{register.configure-BdqREs1-.js → register.configure-CREcJhKA.js} +1 -1
- package/dist/{register.configure-DDrvpBnA.js → register.configure-D8an7wc5.js} +1 -1
- package/dist/{register.maintenance-DT6t7mD_.js → register.maintenance-D84M5XLR.js} +1 -1
- package/dist/{register.maintenance-BSKHOCTV.js → register.maintenance-Dnp_Ii2x.js} +1 -1
- package/dist/{register.message-7KIfSUxS.js → register.message-B6E0uAEu.js} +1 -1
- package/dist/{register.message-DDhEvcaX.js → register.message-WOWC4tyf.js} +1 -1
- package/dist/{register.onboard-CKhooa7L.js → register.onboard-AgVEhehS.js} +1 -1
- package/dist/{register.onboard-CswvuzLx.js → register.onboard-Cwozk0Tx.js} +1 -1
- package/dist/{register.setup-1BmR-qlh.js → register.setup-BKyCvo9_.js} +1 -1
- package/dist/{register.setup-CivwfXf_.js → register.setup-C9IeGiAd.js} +1 -1
- package/dist/{register.status-health-sessions-CLdHZiJm.js → register.status-health-sessions-CYZctjpx.js} +1 -1
- package/dist/{register.status-health-sessions-BXpljfv3.js → register.status-health-sessions-CcL6srRC.js} +1 -1
- package/dist/{register.subclis-D_fHb-Aj.js → register.subclis-AFsfDByV.js} +1 -1
- package/dist/{register.subclis-CTTxdHaJ.js → register.subclis-C0DxtuRO.js} +1 -1
- package/dist/{reply-D9wUWhMx.js → reply-BuUSdq2L.js} +9 -9
- package/dist/{run-main-DNyQhVQT.js → run-main-CgJMiKPV.js} +1 -1
- package/dist/{runner-BNnckkaT.js → runner-C8oNv-9y.js} +3 -3
- package/dist/{runner-EHybuAt7.js → runner-nDoIXX7n.js} +3 -3
- package/dist/{server-node-events-BGrnw4ZT.js → server-node-events-BMsKmU5S.js} +1 -1
- package/dist/{server-node-events-D4WVcVHy.js → server-node-events-fS8TluXq.js} +1 -1
- package/dist/{session-dirs-eNN7E3kA.js → session-dirs-Bkfs-7vN.js} +1 -1
- package/dist/{session-dirs-C-pVBwSV.js → session-dirs-rYDCA_mQ.js} +1 -1
- package/dist/{status-Demw1HZ7.js → status-Ad1eFPKR.js} +1 -1
- package/dist/{status-CBieo24v.js → status-BMzVz5KY.js} +1 -1
- package/dist/{status-rkFgCaBM.js → status-CXRyaGws.js} +1 -1
- package/dist/{status-wTMmjZ7M.js → status-DpEUFAMk.js} +1 -1
- package/dist/{status-BhJw9Htq.js → status-oaiZkYBt.js} +1 -1
- package/dist/{subagent-registry-Bje3RAgk.js → subagent-registry-gVTWLPpL.js} +1 -1
- package/dist/{subagent-registry-B0kpBIxD.js → subagent-registry-hM0OCDzv.js} +1 -1
- package/dist/{subagent-registry-Cj5yC7B4.js → subagent-registry-m_x-JRkR.js} +9 -9
- package/dist/{tui-BCtecmPL.js → tui-HTtOgZ_X.js} +2 -2
- package/dist/{tui-BqHLI73U.js → tui-LemSel3H.js} +2 -2
- package/dist/{tui-cli-2R0xjpqW.js → tui-cli-BpzicV5H.js} +1 -1
- package/dist/{tui-cli-Dvd8BwzD.js → tui-cli-CruoIP1K.js} +1 -1
- package/dist/{update-cli-DUObGvw1.js → update-cli-Wa-nZ_Lq.js} +1 -1
- package/dist/{update-cli-Bt7Vfi7c.js → update-cli-zv67YxK1.js} +1 -1
- package/dist/{web--KblE8ax.js → web-BrsbhB1i.js} +1 -1
- package/dist/{web-C-yTnRvS.js → web-BzkO4Pbe.js} +1 -1
- package/dist/{web-0VRcRcFj.js → web-D_QYY7Gt.js} +1 -1
- package/dist/{web-BcUIWAAJ.js → web-jPbmSTQm.js} +1 -1
- package/package.json +1 -1
- package/dist/chrome-CmCESKt9.js +0 -4
- package/dist/chrome-D6qk0wxW.js +0 -4
- package/dist/plugin-sdk/web-CzJYJZZs.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{c as normalizeAccountId,t as DEFAULT_ACCOUNT_ID}from"./session-key-5J69DULS.js";import{B as info,E as jidToE164,K as success,Z as getChildLogger,j as resolveUserPath}from"./registry-
|
|
1
|
+
import{c as normalizeAccountId,t as DEFAULT_ACCOUNT_ID}from"./session-key-5J69DULS.js";import{B as info,E as jidToE164,K as success,Z as getChildLogger,j as resolveUserPath}from"./registry-CZHRcH-q.js";import{a as resolveOAuthDir}from"./paths-Cb8zTlyG.js";import{i as defaultRuntime}from"./subsystem-D0Ril4rt.js";import{t as formatCliCommand}from"./command-format-B3XMq_73.js";import path from"node:path";import fs from"node:fs";import fs$1 from"node:fs/promises";function createAccountListHelpers(channelKey){function listConfiguredAccountIds(cfg){let accounts=cfg.channels?.[channelKey]?.accounts;return!accounts||typeof accounts!=`object`?[]:Object.keys(accounts).filter(Boolean)}function listAccountIds(cfg){let ids=listConfiguredAccountIds(cfg);return ids.length===0?[DEFAULT_ACCOUNT_ID]:ids.toSorted((a,b)=>a.localeCompare(b))}function resolveDefaultAccountId(cfg){let ids=listAccountIds(cfg);return ids.includes(DEFAULT_ACCOUNT_ID)?DEFAULT_ACCOUNT_ID:ids[0]??DEFAULT_ACCOUNT_ID}return{listConfiguredAccountIds,listAccountIds,resolveDefaultAccountId}}function resolveDefaultWebAuthDir(){return path.join(resolveOAuthDir(),`whatsapp`,DEFAULT_ACCOUNT_ID)}const WA_WEB_AUTH_DIR=resolveDefaultWebAuthDir();function resolveWebCredsPath(authDir){return path.join(authDir,`creds.json`)}function resolveWebCredsBackupPath(authDir){return path.join(authDir,`creds.json.bak`)}function readCredsJsonRaw(filePath){try{if(!fs.existsSync(filePath))return null;let stats=fs.statSync(filePath);return!stats.isFile()||stats.size<=1?null:fs.readFileSync(filePath,`utf-8`)}catch{return null}}function maybeRestoreCredsFromBackup(authDir){let logger=getChildLogger({module:`web-session`});try{let credsPath=resolveWebCredsPath(authDir),backupPath=resolveWebCredsBackupPath(authDir),raw=readCredsJsonRaw(credsPath);if(raw){JSON.parse(raw);return}let backupRaw=readCredsJsonRaw(backupPath);if(!backupRaw)return;JSON.parse(backupRaw),fs.copyFileSync(backupPath,credsPath);try{fs.chmodSync(credsPath,384)}catch{}logger.warn({credsPath},`restored corrupted WhatsApp creds.json from backup`)}catch{}}async function webAuthExists(authDir=resolveDefaultWebAuthDir()){let resolvedAuthDir=resolveUserPath(authDir);maybeRestoreCredsFromBackup(resolvedAuthDir);let credsPath=resolveWebCredsPath(resolvedAuthDir);try{await fs$1.access(resolvedAuthDir)}catch{return!1}try{let stats=await fs$1.stat(credsPath);if(!stats.isFile()||stats.size<=1)return!1;let raw=await fs$1.readFile(credsPath,`utf-8`);return JSON.parse(raw),!0}catch{return!1}}async function clearLegacyBaileysAuthState(authDir){let entries=await fs$1.readdir(authDir,{withFileTypes:!0}),shouldDelete=name=>name===`oauth.json`?!1:name===`creds.json`||name===`creds.json.bak`?!0:name.endsWith(`.json`)?/^(app-state-sync|session|sender-key|pre-key)-/.test(name):!1;await Promise.all(entries.map(async entry=>{entry.isFile()&&shouldDelete(entry.name)&&await fs$1.rm(path.join(authDir,entry.name),{force:!0})}))}async function logoutWeb(params){let runtime=params.runtime??defaultRuntime,resolvedAuthDir=resolveUserPath(params.authDir??resolveDefaultWebAuthDir());return await webAuthExists(resolvedAuthDir)?(params.isLegacyAuthDir?await clearLegacyBaileysAuthState(resolvedAuthDir):await fs$1.rm(resolvedAuthDir,{recursive:!0,force:!0}),runtime.log(success(`Cleared WhatsApp Web credentials.`)),!0):(runtime.log(info(`No WhatsApp Web session found; nothing to delete.`)),!1)}function readWebSelfId(authDir=resolveDefaultWebAuthDir()){try{let credsPath=resolveWebCredsPath(resolveUserPath(authDir));if(!fs.existsSync(credsPath))return{e164:null,jid:null};let raw=fs.readFileSync(credsPath,`utf-8`),jid=JSON.parse(raw)?.me?.id??null;return{e164:jid?jidToE164(jid,{authDir}):null,jid}}catch{return{e164:null,jid:null}}}function getWebAuthAgeMs(authDir=resolveDefaultWebAuthDir()){try{let stats=fs.statSync(resolveWebCredsPath(resolveUserPath(authDir)));return Date.now()-stats.mtimeMs}catch{return null}}function logWebSelfId(authDir=resolveDefaultWebAuthDir(),runtime=defaultRuntime,includeChannelPrefix=!1){let{e164,jid}=readWebSelfId(authDir),details=e164||jid?`${e164??`unknown`}${jid?` (jid ${jid})`:``}`:`unknown`,prefix=includeChannelPrefix?`Web Channel: `:``;runtime.log(info(`${prefix}${details}`))}async function pickWebChannel(pref,authDir=resolveDefaultWebAuthDir()){let choice=pref===`auto`?`web`:pref;if(!await webAuthExists(authDir))throw Error(`No WhatsApp Web session found. Run \`${formatCliCommand(`builderforce channels login --channel whatsapp --verbose`)}\` to link.`);return choice}const{listConfiguredAccountIds,listAccountIds,resolveDefaultAccountId}=createAccountListHelpers(`whatsapp`),listWhatsAppAccountIds=listAccountIds,resolveDefaultWhatsAppAccountId=resolveDefaultAccountId;function resolveAccountConfig(cfg,accountId){let accounts=cfg.channels?.whatsapp?.accounts;if(!(!accounts||typeof accounts!=`object`))return accounts[accountId]}function resolveDefaultAuthDir(accountId){return path.join(resolveOAuthDir(),`whatsapp`,normalizeAccountId(accountId))}function resolveLegacyAuthDir(){return resolveOAuthDir()}function legacyAuthExists(authDir){try{return fs.existsSync(path.join(authDir,`creds.json`))}catch{return!1}}function resolveWhatsAppAuthDir(params){let accountId=params.accountId.trim()||DEFAULT_ACCOUNT_ID,configured=resolveAccountConfig(params.cfg,accountId)?.authDir?.trim();if(configured)return{authDir:resolveUserPath(configured),isLegacy:!1};let defaultDir=resolveDefaultAuthDir(accountId);if(accountId===DEFAULT_ACCOUNT_ID){let legacyDir=resolveLegacyAuthDir();if(legacyAuthExists(legacyDir)&&!legacyAuthExists(defaultDir))return{authDir:legacyDir,isLegacy:!0}}return{authDir:defaultDir,isLegacy:!1}}function resolveWhatsAppAccount(params){let rootCfg=params.cfg.channels?.whatsapp,accountId=params.accountId?.trim()||resolveDefaultWhatsAppAccountId(params.cfg),accountCfg=resolveAccountConfig(params.cfg,accountId),enabled=accountCfg?.enabled!==!1,{authDir,isLegacy}=resolveWhatsAppAuthDir({cfg:params.cfg,accountId});return{accountId,name:accountCfg?.name?.trim()||void 0,enabled,sendReadReceipts:accountCfg?.sendReadReceipts??rootCfg?.sendReadReceipts??!0,messagePrefix:accountCfg?.messagePrefix??rootCfg?.messagePrefix??params.cfg.messages?.messagePrefix,authDir,isLegacyAuthDir:isLegacy,selfChatMode:accountCfg?.selfChatMode??rootCfg?.selfChatMode,dmPolicy:accountCfg?.dmPolicy??rootCfg?.dmPolicy,allowFrom:accountCfg?.allowFrom??rootCfg?.allowFrom,groupAllowFrom:accountCfg?.groupAllowFrom??rootCfg?.groupAllowFrom,groupPolicy:accountCfg?.groupPolicy??rootCfg?.groupPolicy,textChunkLimit:accountCfg?.textChunkLimit??rootCfg?.textChunkLimit,chunkMode:accountCfg?.chunkMode??rootCfg?.chunkMode,mediaMaxMb:accountCfg?.mediaMaxMb??rootCfg?.mediaMaxMb,blockStreaming:accountCfg?.blockStreaming??rootCfg?.blockStreaming,ackReaction:accountCfg?.ackReaction??rootCfg?.ackReaction,groups:accountCfg?.groups??rootCfg?.groups,debounceMs:accountCfg?.debounceMs??rootCfg?.debounceMs}}export{createAccountListHelpers as _,WA_WEB_AUTH_DIR as a,logoutWeb as c,readCredsJsonRaw as d,readWebSelfId as f,webAuthExists as g,resolveWebCredsPath as h,resolveWhatsAppAuthDir as i,maybeRestoreCredsFromBackup as l,resolveWebCredsBackupPath as m,resolveDefaultWhatsAppAccountId as n,getWebAuthAgeMs as o,resolveDefaultWebAuthDir as p,resolveWhatsAppAccount as r,logWebSelfId as s,listWhatsAppAccountIds as t,pickWebChannel as u};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as DEFAULT_ACCOUNT_ID}from"./session-key-5J69DULS.js";import{t as formatCliCommand}from"./command-format-
|
|
1
|
+
import{t as DEFAULT_ACCOUNT_ID}from"./session-key-5J69DULS.js";import{t as formatCliCommand}from"./command-format-B3XMq_73.js";import{i as markdownToIRWithMeta,t as renderMarkdownWithMarkers}from"./render-CuA_WRX5.js";function normalizePollInput(input,options={}){let question=input.question.trim();if(!question)throw Error(`Poll question is required`);let cleaned=(input.options??[]).map(option=>option.trim()).filter(Boolean);if(cleaned.length<2)throw Error(`Poll requires at least 2 options`);if(options.maxOptions!==void 0&&cleaned.length>options.maxOptions)throw Error(`Poll supports at most ${options.maxOptions} options`);let maxSelectionsRaw=input.maxSelections,maxSelections=typeof maxSelectionsRaw==`number`&&Number.isFinite(maxSelectionsRaw)?Math.floor(maxSelectionsRaw):1;if(maxSelections<1)throw Error(`maxSelections must be at least 1`);if(maxSelections>cleaned.length)throw Error(`maxSelections cannot exceed option count`);let durationSecondsRaw=input.durationSeconds,durationSeconds=typeof durationSecondsRaw==`number`&&Number.isFinite(durationSecondsRaw)?Math.floor(durationSecondsRaw):void 0;if(durationSeconds!==void 0&&durationSeconds<1)throw Error(`durationSeconds must be at least 1`);let durationRaw=input.durationHours,durationHours=typeof durationRaw==`number`&&Number.isFinite(durationRaw)?Math.floor(durationRaw):void 0;if(durationHours!==void 0&&durationHours<1)throw Error(`durationHours must be at least 1`);if(durationSeconds!==void 0&&durationHours!==void 0)throw Error(`durationSeconds and durationHours are mutually exclusive`);return{question,options:cleaned,maxSelections,durationSeconds,durationHours}}function normalizePollDurationHours(value,options){let base=typeof value==`number`&&Number.isFinite(value)?Math.floor(value):options.defaultHours;return Math.min(Math.max(base,1),options.maxHours)}const MARKDOWN_STYLE_MARKERS={bold:{open:`**`,close:`**`},italic:{open:`_`,close:`_`},strikethrough:{open:`~~`,close:`~~`},code:{open:"`",close:"`"},code_block:{open:"```\n",close:"```"}};function convertMarkdownTables(markdown,mode){if(!markdown||mode===`off`)return markdown;let{ir,hasTables}=markdownToIRWithMeta(markdown,{linkify:!1,autolink:!1,headingStyle:`none`,blockquotePrefix:``,tableMode:mode});return hasTables?renderMarkdownWithMarkers(ir,{styleMarkers:MARKDOWN_STYLE_MARKERS,escapeText:text=>text,buildLink:(link,text)=>{let href=link.href.trim();return!href||!text.slice(link.start,link.end)?null:{start:link.start,end:link.end,open:`[`,close:`](${href})`}}}):markdown}const listeners=new Map;function resolveWebAccountId(accountId){return(accountId??``).trim()||DEFAULT_ACCOUNT_ID}function requireActiveWebListener(accountId){let id=resolveWebAccountId(accountId),listener=listeners.get(id)??null;if(!listener)throw Error(`No active WhatsApp Web listener (account: ${id}). Start the gateway, then link WhatsApp with: ${formatCliCommand(`builderforce channels login --channel whatsapp --account ${id}`)}.`);return{accountId:id,listener}}function setActiveWebListener(accountIdOrListener,maybeListener){let{accountId,listener}=typeof accountIdOrListener==`string`?{accountId:accountIdOrListener,listener:maybeListener??null}:{accountId:DEFAULT_ACCOUNT_ID,listener:accountIdOrListener??null},id=resolveWebAccountId(accountId);listener?listeners.set(id,listener):listeners.delete(id)}function getActiveWebListener(accountId){let id=resolveWebAccountId(accountId);return listeners.get(id)??null}export{normalizePollDurationHours as a,convertMarkdownTables as i,requireActiveWebListener as n,normalizePollInput as o,setActiveWebListener as r,getActiveWebListener as t};
|
|
@@ -1,41 +1,49 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Transient tool-failure backoff.
|
|
2
|
+
* Transient tool-failure backoff — for IDEMPOTENT tools only.
|
|
3
3
|
*
|
|
4
|
-
* A tool call that fails because the API was RATE-LIMITED
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* exhausted and emits an empty answer — losing the whole turn, not just the one call.
|
|
4
|
+
* A read-only tool call that fails because the API was RATE-LIMITED must not reach the
|
|
5
|
+
* model as a terminal tool failure: the model re-issues immediately, gets 429'd again, and
|
|
6
|
+
* after N consecutive failed dispatches the turn-ender declares the run exhausted.
|
|
8
7
|
*
|
|
9
|
-
* The retry
|
|
10
|
-
* `tool-definition-adapter.ts`), so the before-tool-call
|
|
11
|
-
*
|
|
12
|
-
* outcome. The guard is untouched; it simply stops firing on transient blips.
|
|
8
|
+
* The retry lives INSIDE a single `tool.execute` invocation (see
|
|
9
|
+
* `tool-definition-adapter.ts`), so the before/after-tool-call hooks and the
|
|
10
|
+
* consecutive-failure guard upstream each observe exactly ONE call with ONE final outcome.
|
|
13
11
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
12
|
+
* Replay safety is the whole contract:
|
|
13
|
+
* - Only a tool that DECLARES itself idempotent (`AgentTool.idempotent === true`, default
|
|
14
|
+
* false) is ever retried. `exec` / `write` / `edit` / `apply_patch` / `process` are never
|
|
15
|
+
* retried even if mis-flagged — a `git push` or a deploy must never run twice.
|
|
16
|
+
* - Only a STRUCTURED rate-limit signal is retried: `status === 429` (or `statusCode` /
|
|
17
|
+
* `response.status`) or an explicit `retryAfterMs` / `retryAfter` / `retry_after` field
|
|
18
|
+
* on the thrown error. The error MESSAGE is never classified: a failed command whose
|
|
19
|
+
* output mentions "429", "timeout" or "rate limit" is that command's result, not a
|
|
20
|
+
* transport blip, and timeouts are not retried at all.
|
|
21
|
+
* - Total WALL time (tool runtime + backoff) is bounded, not just the backoff sleeps.
|
|
18
22
|
*
|
|
19
23
|
* `Retry-After` is read in the shape the gateway already writes
|
|
20
|
-
* (`src/gateway/http-common.ts
|
|
21
|
-
*
|
|
22
|
-
* with the JSON-body `retry_after` variant (`DiscordApiError.retryAfter`) alongside it.
|
|
24
|
+
* (`src/gateway/http-common.ts`, `src/gateway/server-http.ts`: integer SECONDS) and that
|
|
25
|
+
* `src/discord/api.ts` already consumes, with the JSON-body `retry_after` variant alongside.
|
|
23
26
|
*/
|
|
24
27
|
import { type RetryInfo } from "../infra/retry.js";
|
|
25
28
|
/**
|
|
26
|
-
* Bounded budget. One initial call plus two retries,
|
|
27
|
-
*
|
|
28
|
-
* trading one cascade for a hang.
|
|
29
|
+
* Bounded budget. One initial call plus two retries, never more than ~10s of total backoff
|
|
30
|
+
* and never more than ~30s of wall time (runtime included) inside a single tool call.
|
|
29
31
|
*/
|
|
30
32
|
export declare const TRANSIENT_TOOL_RETRY_DEFAULTS: {
|
|
31
33
|
readonly attempts: 3;
|
|
32
34
|
readonly minDelayMs: 500;
|
|
33
35
|
readonly maxDelayMs: 8000;
|
|
34
36
|
readonly maxTotalBackoffMs: 10000;
|
|
37
|
+
readonly maxTotalWallMs: 30000;
|
|
35
38
|
};
|
|
39
|
+
/** True when this tool may be replayed after a rate-limit rejection. */
|
|
40
|
+
export declare function isRetryableTool(tool: {
|
|
41
|
+
name?: string;
|
|
42
|
+
idempotent?: boolean;
|
|
43
|
+
}): boolean;
|
|
36
44
|
/**
|
|
37
|
-
* True
|
|
38
|
-
*
|
|
45
|
+
* True ONLY for a structured rate-limit rejection (status 429 or an explicit retry-after
|
|
46
|
+
* field). Message text is deliberately ignored — see the module doc.
|
|
39
47
|
*/
|
|
40
48
|
export declare function isTransientToolFailure(err: unknown): boolean;
|
|
41
49
|
/**
|
|
@@ -55,19 +63,19 @@ export type TransientToolRetryOptions = {
|
|
|
55
63
|
maxDelayMs?: number;
|
|
56
64
|
/** Hard cap on the SUM of all backoff delays inside one turn. */
|
|
57
65
|
maxTotalBackoffMs?: number;
|
|
66
|
+
/** Hard cap on elapsed wall time (runtime + backoff) before another attempt may start. */
|
|
67
|
+
maxTotalWallMs?: number;
|
|
68
|
+
/**
|
|
69
|
+
* The tool declared itself safe to replay (see {@link isRetryableTool}). When false or
|
|
70
|
+
* omitted, `fn` runs exactly once — no retry of any kind.
|
|
71
|
+
*/
|
|
72
|
+
idempotent?: boolean;
|
|
58
73
|
onRetry?: (info: RetryInfo) => void;
|
|
59
74
|
};
|
|
60
75
|
/**
|
|
61
|
-
* Run `fn
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
* Replay safety: a 429 is rejected before the work runs, so replaying it is safe. A
|
|
67
|
-
* `timeout`/`ECONNRESET` may in principle have been thrown AFTER a mutating tool did its
|
|
68
|
-
* side effect, so a tool whose replay is not idempotent should throw with an explicit
|
|
69
|
-
* status (or a non-transient reason) rather than a bare transport error. This is the
|
|
70
|
-
* deliberate trade: the alternative — surfacing the blip immediately — costs the whole
|
|
71
|
-
* turn, which is strictly worse than the rare duplicate write.
|
|
76
|
+
* Run `fn`; when `options.idempotent` is true, retry STRUCTURED rate-limit rejections with
|
|
77
|
+
* backoff (honouring `Retry-After`) until the attempt / backoff / wall budget is spent.
|
|
78
|
+
* Everything else propagates on the first attempt, unchanged, so the caller's existing
|
|
79
|
+
* error-result handling is untouched.
|
|
72
80
|
*/
|
|
73
81
|
export declare function executeWithTransientToolRetry<T>(fn: () => Promise<T>, options?: TransientToolRetryOptions): Promise<T>;
|
|
@@ -73,6 +73,12 @@ export interface AgentToolResult<T> {
|
|
|
73
73
|
export type AgentToolUpdateCallback<T = any> = (partialResult: AgentToolResult<T>) => void;
|
|
74
74
|
export interface AgentTool<TParameters extends TSchema = TSchema, TDetails = any> extends Tool<TParameters> {
|
|
75
75
|
label: string;
|
|
76
|
+
/**
|
|
77
|
+
* The call is safe to REPLAY (read-only: read / search / list / fetch-GET). Only such
|
|
78
|
+
* tools are retried after a structured rate-limit rejection (`agents/tool-retry.ts`).
|
|
79
|
+
* Default false — a side-effecting tool (exec, write, edit, ...) is never replayed.
|
|
80
|
+
*/
|
|
81
|
+
idempotent?: boolean;
|
|
76
82
|
execute: (toolCallId: string, params: Static<TParameters>, signal?: AbortSignal, onUpdate?: AgentToolUpdateCallback<TDetails>) => Promise<AgentToolResult<TDetails>>;
|
|
77
83
|
}
|
|
78
84
|
export interface AgentContext {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{_ as isSubagentSessionKey,g as isCronSessionKey,l as normalizeAgentId,n as DEFAULT_AGENT_ID,v as parseAgentSessionKey}from"./session-key-5J69DULS.js";import{B as info,G as shouldLogVerbose,O as pathExists,Q as getLogger,U as logVerboseConsole,et as onLoggerReset,j as resolveUserPath,q as warn,z as danger}from"./registry-DJq2Cvo9.js";import{s as resolveStateDir,u as resolveRequiredHomeDir}from"./paths-Cb8zTlyG.js";import{i as defaultRuntime,t as createSubsystemLogger}from"./subsystem-COTa5Ly_.js";import path from"node:path";import fs from"node:fs";import os from"node:os";import{fileURLToPath}from"node:url";import fs$1 from"node:fs/promises";import{promisify}from"node:util";import{execFile,spawn}from"node:child_process";const subsystemColonRe=/^([a-z][a-z0-9-]{1,30}):\s+(.*)$/i,subsystemBracketRe=/^\[([a-z][a-z0-9_.:/-]{0,40})\]\s*(.*)$/i;function parseSubsystem(message){let colonMatch=message.match(subsystemColonRe);if(colonMatch)return{subsystem:colonMatch[1],rest:colonMatch[2]};let bracketMatch=message.match(subsystemBracketRe);return bracketMatch?{subsystem:bracketMatch[1],rest:bracketMatch[2]}:null}const loggerCache=new Map;function getSubsystem(name){let logger=loggerCache.get(name);return logger||(logger=createSubsystemLogger(name),loggerCache.set(name,logger)),logger}function resetLoggerCache(){loggerCache.clear()}onLoggerReset(resetLoggerCache);function logInfo(message,runtime=defaultRuntime){if(runtime!==defaultRuntime){runtime.log(info(message)),getLogger().info(message);return}let parsed=parseSubsystem(message);parsed?getSubsystem(parsed.subsystem).info(parsed.rest):getSubsystem(`general`).info(message)}function logWarn(message,runtime=defaultRuntime){if(runtime!==defaultRuntime){runtime.log(warn(message)),getLogger().warn(message);return}let parsed=parseSubsystem(message);parsed?getSubsystem(parsed.subsystem).warn(parsed.rest):getSubsystem(`general`).warn(message)}function logError(message,runtime=defaultRuntime){if(runtime!==defaultRuntime){runtime.error(danger(message)),getLogger().error(message);return}let parsed=parseSubsystem(message);parsed?getSubsystem(parsed.subsystem).error(parsed.rest):getSubsystem(`general`).error(message)}function logDebug(message){getLogger().debug(message),logVerboseConsole(message)}const DEFAULT_RETRY_CODES=[`EBADF`];function resolveCommandStdio(params){return[params.hasInput?`pipe`:params.preferInherit?`inherit`:`pipe`,`pipe`,`pipe`]}function shouldRetry(err,codes){let code=err&&typeof err==`object`&&`code`in err?String(err.code):``;return code.length>0&&codes.includes(code)}async function spawnAndWaitForSpawn(spawnImpl,argv,options){let child=spawnImpl(argv[0],argv.slice(1),options);return await new Promise((resolve,reject)=>{let settled=!1,cleanup=()=>{child.removeListener(`error`,onError),child.removeListener(`spawn`,onSpawn)},finishResolve=()=>{settled||(settled=!0,cleanup(),resolve(child))},onError=err=>{settled||(settled=!0,cleanup(),reject(err))},onSpawn=()=>{finishResolve()};child.once(`error`,onError),child.once(`spawn`,onSpawn),process.nextTick(()=>{typeof child.pid==`number`&&finishResolve()})})}async function spawnWithFallback(params){let spawnImpl=params.spawnImpl??spawn,retryCodes=params.retryCodes??DEFAULT_RETRY_CODES,baseOptions={...params.options},fallbacks=params.fallbacks??[],attempts=[{options:baseOptions},...fallbacks.map(fallback=>({label:fallback.label,options:{...baseOptions,...fallback.options}}))],lastError;for(let index=0;index<attempts.length;index+=1){let attempt=attempts[index];try{return{child:await spawnAndWaitForSpawn(spawnImpl,params.argv,attempt.options),usedFallback:index>0,fallbackLabel:attempt.label}}catch(err){lastError=err;let nextFallback=fallbacks[index];if(!nextFallback||!shouldRetry(err,retryCodes))throw err;params.onFallback?.(err,nextFallback)}}throw lastError}const execFileAsync=promisify(execFile);function resolveCommand(command){if(process.platform!==`win32`)return command;let basename=path.basename(command).toLowerCase();return path.extname(basename)?command:[`npm`,`pnpm`,`yarn`,`npx`].includes(basename)?`${command}.cmd`:command}function shouldSpawnWithShell(params){return!1}async function runExec(command,args,opts=1e4){let options=typeof opts==`number`?{timeout:opts,encoding:`utf8`}:{timeout:opts.timeoutMs,maxBuffer:opts.maxBuffer,encoding:`utf8`};try{let{stdout,stderr}=await execFileAsync(resolveCommand(command),args,options);return shouldLogVerbose()&&(stdout.trim()&&logDebug(stdout.trim()),stderr.trim()&&logError(stderr.trim())),{stdout,stderr}}catch(err){throw shouldLogVerbose()&&logError(danger(`Command failed: ${command} ${args.join(` `)}`)),err}}async function runCommandWithTimeout(argv,optionsOrTimeout){let options=typeof optionsOrTimeout==`number`?{timeoutMs:optionsOrTimeout}:optionsOrTimeout,{timeoutMs,cwd,input,env,noOutputTimeoutMs}=options,{windowsVerbatimArguments}=options,hasInput=input!==void 0,shouldSuppressNpmFund=(()=>{let cmd=path.basename(argv[0]??``);return cmd===`npm`||cmd===`npm.cmd`||cmd===`npm.exe`?!0:cmd===`node`||cmd===`node.exe`?(argv[1]??``).includes(`npm-cli.js`):!1})(),mergedEnv=env?{...process.env,...env}:{...process.env},resolvedEnv=Object.fromEntries(Object.entries(mergedEnv).filter(([,value])=>value!==void 0).map(([key,value])=>[key,String(value)]));shouldSuppressNpmFund&&(resolvedEnv.NPM_CONFIG_FUND??=`false`,resolvedEnv.npm_config_fund??=`false`);let stdio=resolveCommandStdio({hasInput,preferInherit:!0}),resolvedCommand=resolveCommand(argv[0]??``),child=spawn(resolvedCommand,argv.slice(1),{stdio,cwd,env:resolvedEnv,windowsVerbatimArguments,...shouldSpawnWithShell({resolvedCommand,platform:process.platform})?{shell:!0}:{}});return await new Promise((resolve,reject)=>{let stdout=``,stderr=``,settled=!1,timedOut=!1,noOutputTimedOut=!1,noOutputTimer=null,shouldTrackOutputTimeout=typeof noOutputTimeoutMs==`number`&&Number.isFinite(noOutputTimeoutMs)&&noOutputTimeoutMs>0,clearNoOutputTimer=()=>{noOutputTimer&&=(clearTimeout(noOutputTimer),null)},armNoOutputTimer=()=>{!shouldTrackOutputTimeout||settled||(clearNoOutputTimer(),noOutputTimer=setTimeout(()=>{settled||(noOutputTimedOut=!0,typeof child.kill==`function`&&child.kill(`SIGKILL`))},Math.floor(noOutputTimeoutMs)))},timer=setTimeout(()=>{timedOut=!0,typeof child.kill==`function`&&child.kill(`SIGKILL`)},timeoutMs);armNoOutputTimer(),hasInput&&child.stdin&&(child.stdin.write(input??``),child.stdin.end()),child.stdout?.on(`data`,d=>{stdout+=d.toString(),armNoOutputTimer()}),child.stderr?.on(`data`,d=>{stderr+=d.toString(),armNoOutputTimer()}),child.on(`error`,err=>{settled||(settled=!0,clearTimeout(timer),clearNoOutputTimer(),reject(err))}),child.on(`close`,(code,signal)=>{if(settled)return;settled=!0,clearTimeout(timer),clearNoOutputTimer();let termination=noOutputTimedOut?`no-output-timeout`:timedOut?`timeout`:signal==null?`exit`:`signal`;resolve({pid:child.pid??void 0,stdout,stderr,code,signal,killed:child.killed,termination,noOutputTimedOut})})})}function normalizeSkillFilter(skillFilter){if(skillFilter!==void 0)return skillFilter.map(entry=>String(entry).trim()).filter(Boolean)}const CORE_PACKAGE_NAMES=[`@seanhogg/builderforce-agents`,...[`builderforce`]],CORE_PACKAGE_NAME_SET=new Set(CORE_PACKAGE_NAMES);function isCorePackageName(name){return!!(name&&CORE_PACKAGE_NAME_SET.has(name))}async function readPackageName(dir){try{let raw=await fs$1.readFile(path.join(dir,`package.json`),`utf-8`),parsed=JSON.parse(raw);return typeof parsed.name==`string`?parsed.name:null}catch{return null}}function readPackageNameSync(dir){try{let raw=fs.readFileSync(path.join(dir,`package.json`),`utf-8`),parsed=JSON.parse(raw);return typeof parsed.name==`string`?parsed.name:null}catch{return null}}async function findPackageRoot(startDir,maxDepth=12){let current=path.resolve(startDir);for(let i=0;i<maxDepth;i+=1){if(isCorePackageName(await readPackageName(current)))return current;let parent=path.dirname(current);if(parent===current)break;current=parent}return null}function findPackageRootSync(startDir,maxDepth=12){let current=path.resolve(startDir);for(let i=0;i<maxDepth;i+=1){if(isCorePackageName(readPackageNameSync(current)))return current;let parent=path.dirname(current);if(parent===current)break;current=parent}return null}function candidateDirsFromArgv1(argv1){let normalized=path.resolve(argv1),candidates=[path.dirname(normalized)];try{let resolved=fs.realpathSync(normalized);resolved!==normalized&&candidates.push(path.dirname(resolved))}catch{}let parts=normalized.split(path.sep),binIndex=parts.lastIndexOf(`.bin`);if(binIndex>0&&parts[binIndex-1]===`node_modules`){let binName=path.basename(normalized),nodeModulesDir=parts.slice(0,binIndex).join(path.sep);candidates.push(path.join(nodeModulesDir,binName))}return candidates}async function resolveBuilderForceAgentsPackageRoot(opts){for(let candidate of buildCandidates(opts)){let found=await findPackageRoot(candidate);if(found)return found}return null}function resolveBuilderForceAgentsPackageRootSync(opts){for(let candidate of buildCandidates(opts)){let found=findPackageRootSync(candidate);if(found)return found}return null}function buildCandidates(opts){let candidates=[];return opts.moduleUrl&&candidates.push(path.dirname(fileURLToPath(opts.moduleUrl))),opts.argv1&&candidates.push(...candidateDirsFromArgv1(opts.argv1)),opts.cwd&&candidates.push(opts.cwd),candidates}const FALLBACK_TEMPLATE_DIR=path.resolve(path.dirname(fileURLToPath(import.meta.url)),`../../foundation`);let cachedTemplateDir,resolvingTemplateDir;async function resolveWorkspaceTemplateDir(opts){if(cachedTemplateDir)return cachedTemplateDir;if(resolvingTemplateDir)return resolvingTemplateDir;resolvingTemplateDir=(async()=>{let moduleUrl=opts?.moduleUrl??import.meta.url,argv1=opts?.argv1??process.argv[1],cwd=opts?.cwd??process.cwd(),packageRoot=await resolveBuilderForceAgentsPackageRoot({moduleUrl,argv1,cwd}),candidates=[packageRoot?path.join(packageRoot,`foundation`):null,cwd?path.resolve(cwd,`foundation`):null,FALLBACK_TEMPLATE_DIR].filter(Boolean);for(let candidate of candidates)if(await pathExists(candidate))return cachedTemplateDir=candidate,candidate;return cachedTemplateDir=candidates[0]??FALLBACK_TEMPLATE_DIR,cachedTemplateDir})();try{return await resolvingTemplateDir}finally{resolvingTemplateDir=void 0}}function resolveDefaultAgentWorkspaceDir(env=process.env,homedir=os.homedir){let home=resolveRequiredHomeDir(env,homedir),profile=env.BUILDERFORCE_AGENTS_PROFILE?.trim();return profile&&profile.toLowerCase()!==`default`?path.join(home,`.builderforce`,`workspace-${profile}`):path.join(home,`.builderforce`,`workspace`)}const DEFAULT_AGENT_WORKSPACE_DIR=resolveDefaultAgentWorkspaceDir(),DEFAULT_AGENTS_FILENAME=`AGENTS.md`,DEFAULT_SOUL_FILENAME=`SOUL.md`,DEFAULT_TOOLS_FILENAME=`TOOLS.md`,DEFAULT_IDENTITY_FILENAME=`IDENTITY.md`,DEFAULT_USER_FILENAME=`USER.md`,DEFAULT_HEARTBEAT_FILENAME=`HEARTBEAT.md`,DEFAULT_BOOTSTRAP_FILENAME=`BOOTSTRAP.md`,EMBEDDED_WORKSPACE_TEMPLATES={[DEFAULT_AGENTS_FILENAME]:`# AGENTS
|
|
1
|
+
import{_ as isSubagentSessionKey,g as isCronSessionKey,l as normalizeAgentId,n as DEFAULT_AGENT_ID,v as parseAgentSessionKey}from"./session-key-5J69DULS.js";import{B as info,G as shouldLogVerbose,O as pathExists,Q as getLogger,U as logVerboseConsole,et as onLoggerReset,j as resolveUserPath,q as warn,z as danger}from"./registry-CZHRcH-q.js";import{s as resolveStateDir,u as resolveRequiredHomeDir}from"./paths-Cb8zTlyG.js";import{i as defaultRuntime,t as createSubsystemLogger}from"./subsystem-D0Ril4rt.js";import path from"node:path";import fs from"node:fs";import os from"node:os";import{fileURLToPath}from"node:url";import fs$1 from"node:fs/promises";import{promisify}from"node:util";import{execFile,spawn}from"node:child_process";const subsystemColonRe=/^([a-z][a-z0-9-]{1,30}):\s+(.*)$/i,subsystemBracketRe=/^\[([a-z][a-z0-9_.:/-]{0,40})\]\s*(.*)$/i;function parseSubsystem(message){let colonMatch=message.match(subsystemColonRe);if(colonMatch)return{subsystem:colonMatch[1],rest:colonMatch[2]};let bracketMatch=message.match(subsystemBracketRe);return bracketMatch?{subsystem:bracketMatch[1],rest:bracketMatch[2]}:null}const loggerCache=new Map;function getSubsystem(name){let logger=loggerCache.get(name);return logger||(logger=createSubsystemLogger(name),loggerCache.set(name,logger)),logger}function resetLoggerCache(){loggerCache.clear()}onLoggerReset(resetLoggerCache);function logInfo(message,runtime=defaultRuntime){if(runtime!==defaultRuntime){runtime.log(info(message)),getLogger().info(message);return}let parsed=parseSubsystem(message);parsed?getSubsystem(parsed.subsystem).info(parsed.rest):getSubsystem(`general`).info(message)}function logWarn(message,runtime=defaultRuntime){if(runtime!==defaultRuntime){runtime.log(warn(message)),getLogger().warn(message);return}let parsed=parseSubsystem(message);parsed?getSubsystem(parsed.subsystem).warn(parsed.rest):getSubsystem(`general`).warn(message)}function logError(message,runtime=defaultRuntime){if(runtime!==defaultRuntime){runtime.error(danger(message)),getLogger().error(message);return}let parsed=parseSubsystem(message);parsed?getSubsystem(parsed.subsystem).error(parsed.rest):getSubsystem(`general`).error(message)}function logDebug(message){getLogger().debug(message),logVerboseConsole(message)}const DEFAULT_RETRY_CODES=[`EBADF`];function resolveCommandStdio(params){return[params.hasInput?`pipe`:params.preferInherit?`inherit`:`pipe`,`pipe`,`pipe`]}function shouldRetry(err,codes){let code=err&&typeof err==`object`&&`code`in err?String(err.code):``;return code.length>0&&codes.includes(code)}async function spawnAndWaitForSpawn(spawnImpl,argv,options){let child=spawnImpl(argv[0],argv.slice(1),options);return await new Promise((resolve,reject)=>{let settled=!1,cleanup=()=>{child.removeListener(`error`,onError),child.removeListener(`spawn`,onSpawn)},finishResolve=()=>{settled||(settled=!0,cleanup(),resolve(child))},onError=err=>{settled||(settled=!0,cleanup(),reject(err))},onSpawn=()=>{finishResolve()};child.once(`error`,onError),child.once(`spawn`,onSpawn),process.nextTick(()=>{typeof child.pid==`number`&&finishResolve()})})}async function spawnWithFallback(params){let spawnImpl=params.spawnImpl??spawn,retryCodes=params.retryCodes??DEFAULT_RETRY_CODES,baseOptions={...params.options},fallbacks=params.fallbacks??[],attempts=[{options:baseOptions},...fallbacks.map(fallback=>({label:fallback.label,options:{...baseOptions,...fallback.options}}))],lastError;for(let index=0;index<attempts.length;index+=1){let attempt=attempts[index];try{return{child:await spawnAndWaitForSpawn(spawnImpl,params.argv,attempt.options),usedFallback:index>0,fallbackLabel:attempt.label}}catch(err){lastError=err;let nextFallback=fallbacks[index];if(!nextFallback||!shouldRetry(err,retryCodes))throw err;params.onFallback?.(err,nextFallback)}}throw lastError}const execFileAsync=promisify(execFile);function resolveCommand(command){if(process.platform!==`win32`)return command;let basename=path.basename(command).toLowerCase();return path.extname(basename)?command:[`npm`,`pnpm`,`yarn`,`npx`].includes(basename)?`${command}.cmd`:command}function shouldSpawnWithShell(params){return!1}async function runExec(command,args,opts=1e4){let options=typeof opts==`number`?{timeout:opts,encoding:`utf8`}:{timeout:opts.timeoutMs,maxBuffer:opts.maxBuffer,encoding:`utf8`};try{let{stdout,stderr}=await execFileAsync(resolveCommand(command),args,options);return shouldLogVerbose()&&(stdout.trim()&&logDebug(stdout.trim()),stderr.trim()&&logError(stderr.trim())),{stdout,stderr}}catch(err){throw shouldLogVerbose()&&logError(danger(`Command failed: ${command} ${args.join(` `)}`)),err}}async function runCommandWithTimeout(argv,optionsOrTimeout){let options=typeof optionsOrTimeout==`number`?{timeoutMs:optionsOrTimeout}:optionsOrTimeout,{timeoutMs,cwd,input,env,noOutputTimeoutMs}=options,{windowsVerbatimArguments}=options,hasInput=input!==void 0,shouldSuppressNpmFund=(()=>{let cmd=path.basename(argv[0]??``);return cmd===`npm`||cmd===`npm.cmd`||cmd===`npm.exe`?!0:cmd===`node`||cmd===`node.exe`?(argv[1]??``).includes(`npm-cli.js`):!1})(),mergedEnv=env?{...process.env,...env}:{...process.env},resolvedEnv=Object.fromEntries(Object.entries(mergedEnv).filter(([,value])=>value!==void 0).map(([key,value])=>[key,String(value)]));shouldSuppressNpmFund&&(resolvedEnv.NPM_CONFIG_FUND??=`false`,resolvedEnv.npm_config_fund??=`false`);let stdio=resolveCommandStdio({hasInput,preferInherit:!0}),resolvedCommand=resolveCommand(argv[0]??``),child=spawn(resolvedCommand,argv.slice(1),{stdio,cwd,env:resolvedEnv,windowsVerbatimArguments,...shouldSpawnWithShell({resolvedCommand,platform:process.platform})?{shell:!0}:{}});return await new Promise((resolve,reject)=>{let stdout=``,stderr=``,settled=!1,timedOut=!1,noOutputTimedOut=!1,noOutputTimer=null,shouldTrackOutputTimeout=typeof noOutputTimeoutMs==`number`&&Number.isFinite(noOutputTimeoutMs)&&noOutputTimeoutMs>0,clearNoOutputTimer=()=>{noOutputTimer&&=(clearTimeout(noOutputTimer),null)},armNoOutputTimer=()=>{!shouldTrackOutputTimeout||settled||(clearNoOutputTimer(),noOutputTimer=setTimeout(()=>{settled||(noOutputTimedOut=!0,typeof child.kill==`function`&&child.kill(`SIGKILL`))},Math.floor(noOutputTimeoutMs)))},timer=setTimeout(()=>{timedOut=!0,typeof child.kill==`function`&&child.kill(`SIGKILL`)},timeoutMs);armNoOutputTimer(),hasInput&&child.stdin&&(child.stdin.write(input??``),child.stdin.end()),child.stdout?.on(`data`,d=>{stdout+=d.toString(),armNoOutputTimer()}),child.stderr?.on(`data`,d=>{stderr+=d.toString(),armNoOutputTimer()}),child.on(`error`,err=>{settled||(settled=!0,clearTimeout(timer),clearNoOutputTimer(),reject(err))}),child.on(`close`,(code,signal)=>{if(settled)return;settled=!0,clearTimeout(timer),clearNoOutputTimer();let termination=noOutputTimedOut?`no-output-timeout`:timedOut?`timeout`:signal==null?`exit`:`signal`;resolve({pid:child.pid??void 0,stdout,stderr,code,signal,killed:child.killed,termination,noOutputTimedOut})})})}function normalizeSkillFilter(skillFilter){if(skillFilter!==void 0)return skillFilter.map(entry=>String(entry).trim()).filter(Boolean)}const CORE_PACKAGE_NAMES=[`@seanhogg/builderforce-agents`,...[`builderforce`]],CORE_PACKAGE_NAME_SET=new Set(CORE_PACKAGE_NAMES);function isCorePackageName(name){return!!(name&&CORE_PACKAGE_NAME_SET.has(name))}async function readPackageName(dir){try{let raw=await fs$1.readFile(path.join(dir,`package.json`),`utf-8`),parsed=JSON.parse(raw);return typeof parsed.name==`string`?parsed.name:null}catch{return null}}function readPackageNameSync(dir){try{let raw=fs.readFileSync(path.join(dir,`package.json`),`utf-8`),parsed=JSON.parse(raw);return typeof parsed.name==`string`?parsed.name:null}catch{return null}}async function findPackageRoot(startDir,maxDepth=12){let current=path.resolve(startDir);for(let i=0;i<maxDepth;i+=1){if(isCorePackageName(await readPackageName(current)))return current;let parent=path.dirname(current);if(parent===current)break;current=parent}return null}function findPackageRootSync(startDir,maxDepth=12){let current=path.resolve(startDir);for(let i=0;i<maxDepth;i+=1){if(isCorePackageName(readPackageNameSync(current)))return current;let parent=path.dirname(current);if(parent===current)break;current=parent}return null}function candidateDirsFromArgv1(argv1){let normalized=path.resolve(argv1),candidates=[path.dirname(normalized)];try{let resolved=fs.realpathSync(normalized);resolved!==normalized&&candidates.push(path.dirname(resolved))}catch{}let parts=normalized.split(path.sep),binIndex=parts.lastIndexOf(`.bin`);if(binIndex>0&&parts[binIndex-1]===`node_modules`){let binName=path.basename(normalized),nodeModulesDir=parts.slice(0,binIndex).join(path.sep);candidates.push(path.join(nodeModulesDir,binName))}return candidates}async function resolveBuilderForceAgentsPackageRoot(opts){for(let candidate of buildCandidates(opts)){let found=await findPackageRoot(candidate);if(found)return found}return null}function resolveBuilderForceAgentsPackageRootSync(opts){for(let candidate of buildCandidates(opts)){let found=findPackageRootSync(candidate);if(found)return found}return null}function buildCandidates(opts){let candidates=[];return opts.moduleUrl&&candidates.push(path.dirname(fileURLToPath(opts.moduleUrl))),opts.argv1&&candidates.push(...candidateDirsFromArgv1(opts.argv1)),opts.cwd&&candidates.push(opts.cwd),candidates}const FALLBACK_TEMPLATE_DIR=path.resolve(path.dirname(fileURLToPath(import.meta.url)),`../../foundation`);let cachedTemplateDir,resolvingTemplateDir;async function resolveWorkspaceTemplateDir(opts){if(cachedTemplateDir)return cachedTemplateDir;if(resolvingTemplateDir)return resolvingTemplateDir;resolvingTemplateDir=(async()=>{let moduleUrl=opts?.moduleUrl??import.meta.url,argv1=opts?.argv1??process.argv[1],cwd=opts?.cwd??process.cwd(),packageRoot=await resolveBuilderForceAgentsPackageRoot({moduleUrl,argv1,cwd}),candidates=[packageRoot?path.join(packageRoot,`foundation`):null,cwd?path.resolve(cwd,`foundation`):null,FALLBACK_TEMPLATE_DIR].filter(Boolean);for(let candidate of candidates)if(await pathExists(candidate))return cachedTemplateDir=candidate,candidate;return cachedTemplateDir=candidates[0]??FALLBACK_TEMPLATE_DIR,cachedTemplateDir})();try{return await resolvingTemplateDir}finally{resolvingTemplateDir=void 0}}function resolveDefaultAgentWorkspaceDir(env=process.env,homedir=os.homedir){let home=resolveRequiredHomeDir(env,homedir),profile=env.BUILDERFORCE_AGENTS_PROFILE?.trim();return profile&&profile.toLowerCase()!==`default`?path.join(home,`.builderforce`,`workspace-${profile}`):path.join(home,`.builderforce`,`workspace`)}const DEFAULT_AGENT_WORKSPACE_DIR=resolveDefaultAgentWorkspaceDir(),DEFAULT_AGENTS_FILENAME=`AGENTS.md`,DEFAULT_SOUL_FILENAME=`SOUL.md`,DEFAULT_TOOLS_FILENAME=`TOOLS.md`,DEFAULT_IDENTITY_FILENAME=`IDENTITY.md`,DEFAULT_USER_FILENAME=`USER.md`,DEFAULT_HEARTBEAT_FILENAME=`HEARTBEAT.md`,DEFAULT_BOOTSTRAP_FILENAME=`BOOTSTRAP.md`,EMBEDDED_WORKSPACE_TEMPLATES={[DEFAULT_AGENTS_FILENAME]:`# AGENTS
|
|
2
2
|
|
|
3
3
|
Project rules and collaboration guidelines for this workspace.
|
|
4
4
|
`,[DEFAULT_SOUL_FILENAME]:`# SOUL
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{l as normalizeProviderId}from"./model-selection-
|
|
1
|
+
import{l as normalizeProviderId}from"./model-selection-_H_U9jWH.js";import{n as formatErrorMessage}from"./errors-L3rugjUL.js";const SESSION_TRANSCRIPT_LISTENERS=new Set;function onSessionTranscriptUpdate(listener){return SESSION_TRANSCRIPT_LISTENERS.add(listener),()=>{SESSION_TRANSCRIPT_LISTENERS.delete(listener)}}function emitSessionTranscriptUpdate(sessionFile){let trimmed=sessionFile.trim();if(!trimmed)return;let update={sessionFile:trimmed};for(let listener of SESSION_TRANSCRIPT_LISTENERS)listener(update)}function parseGeminiAuth(apiKey){if(apiKey.startsWith(`{`))try{let parsed=JSON.parse(apiKey);if(typeof parsed.token==`string`&&parsed.token)return{headers:{Authorization:`Bearer ${parsed.token}`,"Content-Type":`application/json`}}}catch{}return{headers:{"x-goog-api-key":apiKey,"Content-Type":`application/json`}}}const KEY_SPLIT_RE=/[\s,;]+/g,GOOGLE_LIVE_SINGLE_KEY=`BUILDERFORCE_AGENTS_LIVE_GEMINI_KEY`,PROVIDER_PREFIX_OVERRIDES={google:`GEMINI`,"google-vertex":`GEMINI`},PROVIDER_API_KEY_CONFIG={anthropic:{liveSingle:`BUILDERFORCE_AGENTS_LIVE_ANTHROPIC_KEY`,listVar:`BUILDERFORCE_AGENTS_LIVE_ANTHROPIC_KEYS`,primaryVar:`ANTHROPIC_API_KEY`,prefixedVar:`ANTHROPIC_API_KEY_`},google:{liveSingle:GOOGLE_LIVE_SINGLE_KEY,listVar:`GEMINI_API_KEYS`,primaryVar:`GEMINI_API_KEY`,prefixedVar:`GEMINI_API_KEY_`},"google-vertex":{liveSingle:GOOGLE_LIVE_SINGLE_KEY,listVar:`GEMINI_API_KEYS`,primaryVar:`GEMINI_API_KEY`,prefixedVar:`GEMINI_API_KEY_`},openai:{liveSingle:`BUILDERFORCE_AGENTS_LIVE_OPENAI_KEY`,listVar:`OPENAI_API_KEYS`,primaryVar:`OPENAI_API_KEY`,prefixedVar:`OPENAI_API_KEY_`}};function parseKeyList(raw){return raw?raw.split(KEY_SPLIT_RE).map(value=>value.trim()).filter(Boolean):[]}function collectEnvPrefixedKeys(prefix){let keys=[];for(let[name,value]of Object.entries(process.env)){if(!name.startsWith(prefix))continue;let trimmed=value?.trim();trimmed&&keys.push(trimmed)}return keys}function resolveProviderApiKeyConfig(provider){let normalized=normalizeProviderId(provider),custom=PROVIDER_API_KEY_CONFIG[normalized],base=PROVIDER_PREFIX_OVERRIDES[normalized]??normalized.toUpperCase().replace(/-/g,`_`),liveSingle=custom?.liveSingle??`BUILDERFORCE_AGENTS_LIVE_${base}_KEY`,listVar=custom?.listVar??`${base}_API_KEYS`,primaryVar=custom?.primaryVar??`${base}_API_KEY`,prefixedVar=custom?.prefixedVar??`${base}_API_KEY_`;return normalized===`google`||normalized===`google-vertex`?{liveSingle,listVar,primaryVar,prefixedVar,fallbackVars:[`GOOGLE_API_KEY`]}:{liveSingle,listVar,primaryVar,prefixedVar,fallbackVars:[]}}function collectProviderApiKeys(provider){let config=resolveProviderApiKeyConfig(provider),forcedSingle=config.liveSingle?process.env[config.liveSingle]?.trim():void 0;if(forcedSingle)return[forcedSingle];let fromList=parseKeyList(config.listVar?process.env[config.listVar]:void 0),primary=config.primaryVar?process.env[config.primaryVar]?.trim():void 0,fromPrefixed=config.prefixedVar?collectEnvPrefixedKeys(config.prefixedVar):[],fallback=config.fallbackVars.map(envVar=>process.env[envVar]?.trim()).filter(Boolean),seen=new Set,add=value=>{value&&(seen.has(value)||seen.add(value))};for(let value of fromList)add(value);add(primary);for(let value of fromPrefixed)add(value);for(let value of fallback)add(value);return Array.from(seen)}function isApiKeyRateLimitError(message){let lower=message.toLowerCase();return!!(lower.includes(`rate_limit`)||lower.includes(`rate limit`)||lower.includes(`429`)||lower.includes(`quota exceeded`)||lower.includes(`quota_exceeded`)||lower.includes(`resource exhausted`)||lower.includes(`resource_exhausted`)||lower.includes(`too many requests`))}function dedupeApiKeys(raw){let seen=new Set,keys=[];for(let value of raw){let apiKey=value.trim();!apiKey||seen.has(apiKey)||(seen.add(apiKey),keys.push(apiKey))}return keys}function collectProviderApiKeysForExecution(params){let{primaryApiKey,provider}=params;return dedupeApiKeys([primaryApiKey?.trim()??``,...collectProviderApiKeys(provider)])}async function executeWithApiKeyRotation(params){let keys=dedupeApiKeys(params.apiKeys);if(keys.length===0)throw Error(`No API keys configured for provider "${params.provider}".`);let lastError;for(let attempt=0;attempt<keys.length;attempt+=1){let apiKey=keys[attempt];try{return await params.execute(apiKey)}catch(error){lastError=error;let message=formatErrorMessage(error);if(!(params.shouldRetry?params.shouldRetry({apiKey,error,attempt,message}):isApiKeyRateLimitError(message))||attempt+1>=keys.length)break;params.onRetry?.({apiKey,error,attempt,message})}}throw lastError===void 0?Error(`Failed to run API request for ${params.provider}.`):lastError}export{onSessionTranscriptUpdate as a,emitSessionTranscriptUpdate as i,executeWithApiKeyRotation as n,parseGeminiAuth as r,collectProviderApiKeysForExecution as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./session-key-5J69DULS.js";import"./accounts-
|
|
1
|
+
import"./session-key-5J69DULS.js";import"./accounts-Cy3WCbWg.js";import{G as shouldLogVerbose,H as logVerbose}from"./registry-CZHRcH-q.js";import"./paths-Cb8zTlyG.js";import"./model-selection-_H_U9jWH.js";import"./config--Ci8Y91R.js";import"./fetch-B-GxSYRO.js";import"./subsystem-D0Ril4rt.js";import"./agent-scope-DgKN27hJ.js";import"./tool-images-WRTP95FT.js";import{a as runCapability,n as createMediaAttachmentCache,o as isAudioAttachment,r as normalizeMediaAttachments,t as buildProviderRegistry}from"./runner-DKoKK09-.js";import"./redact-Bv8wnIZm.js";import"./errors-L3rugjUL.js";import"./chrome-CRUzg3kA.js";import"./command-format-B3XMq_73.js";import"./plugins-BdkC9v5E.js";import"./bindings-CH-YLOLC.js";import"./message-channel-CuZ2xOAM.js";import"./src-5XE2oMwl.js";import"./paths-DtbnCdO7.js";import"./api-key-rotation-D37jV9ZW.js";import"./model-catalog-DIQ5a-o4.js";async function transcribeFirstAudio(params){let{ctx,cfg}=params,audioConfig=cfg.tools?.media?.audio;if(!audioConfig||audioConfig.enabled===!1)return;let attachments=normalizeMediaAttachments(ctx);if(!attachments||attachments.length===0)return;let firstAudio=attachments.find(att=>att&&isAudioAttachment(att)&&!att.alreadyTranscribed);if(!firstAudio)return;shouldLogVerbose()&&logVerbose(`audio-preflight: transcribing attachment ${firstAudio.index} for mention check`);let providerRegistry=buildProviderRegistry(params.providers),cache=createMediaAttachmentCache(attachments);try{let result=await runCapability({capability:`audio`,cfg,ctx,attachments:cache,media:attachments,agentDir:params.agentDir,providerRegistry,config:audioConfig,activeModel:params.activeModel});if(!result||result.outputs.length===0)return;let audioOutput=result.outputs.find(output=>output.kind===`audio.transcription`);return!audioOutput||!audioOutput.text?void 0:(firstAudio.alreadyTranscribed=!0,shouldLogVerbose()&&logVerbose(`audio-preflight: transcribed ${audioOutput.text.length} chars from attachment ${firstAudio.index}`),audioOutput.text)}catch(err){shouldLogVerbose()&&logVerbose(`audio-preflight: transcription failed: ${String(err)}`);return}finally{await cache.cleanup()}}export{transcribeFirstAudio};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./session-key-5J69DULS.js";import"./registry-
|
|
1
|
+
import"./session-key-5J69DULS.js";import"./registry-CZHRcH-q.js";import"./paths-Cb8zTlyG.js";import{l as normalizeProviderId,lt as ensureAuthProfileStore}from"./model-selection-_H_U9jWH.js";import"./subsystem-D0Ril4rt.js";import"./agent-scope-DgKN27hJ.js";import"./command-format-B3XMq_73.js";import"./src-5XE2oMwl.js";import path from"node:path";import fs from"node:fs/promises";async function readAuthJson(filePath){try{let raw=await fs.readFile(filePath,`utf8`),parsed=JSON.parse(raw);return!parsed||typeof parsed!=`object`?{}:parsed}catch{return{}}}function convertCredential(cred){if(cred.type===`api_key`){let key=typeof cred.key==`string`?cred.key.trim():``;return key?{type:`api_key`,key}:null}if(cred.type===`token`){let token=typeof cred.token==`string`?cred.token.trim():``;if(!token)return null;let expires=typeof cred.expires==`number`?cred.expires:NaN;return Number.isFinite(expires)&&expires>0&&Date.now()>=expires?null:{type:`api_key`,key:token}}if(cred.type===`oauth`){let accessRaw=cred.access,refreshRaw=cred.refresh,expiresRaw=cred.expires,access=typeof accessRaw==`string`?accessRaw.trim():``,refresh=typeof refreshRaw==`string`?refreshRaw.trim():``,expires=typeof expiresRaw==`number`?expiresRaw:NaN;return!access||!refresh||!Number.isFinite(expires)||expires<=0?null:{type:`oauth`,access,refresh,expires}}return null}function credentialsEqual(a,b){return!a||typeof a!=`object`||a.type!==b.type?!1:a.type===`api_key`&&b.type===`api_key`?a.key===b.key:a.type===`oauth`&&b.type===`oauth`?a.access===b.access&&a.refresh===b.refresh&&a.expires===b.expires:!1}async function ensureAuthJsonFromAuthProfiles(agentDir){let store=await ensureAuthProfileStore(agentDir,{allowKeychainPrompt:!1}),authPath=path.join(agentDir,`auth.json`),providerCredentials=new Map;for(let[,cred]of Object.entries(store.profiles)){let provider=normalizeProviderId(String(cred.provider??``)).trim();if(!provider||providerCredentials.has(provider))continue;let converted=convertCredential(cred);converted&&providerCredentials.set(provider,converted)}if(providerCredentials.size===0)return{wrote:!1,authPath};let existing=await readAuthJson(authPath),changed=!1;for(let[provider,cred]of providerCredentials)credentialsEqual(existing[provider],cred)||(existing[provider]=cred,changed=!0);return changed?(await fs.mkdir(agentDir,{recursive:!0,mode:448}),await fs.writeFile(authPath,`${JSON.stringify(existing,null,2)}\n`,{mode:384}),{wrote:!0,authPath}):{wrote:!1,authPath}}export{ensureAuthJsonFromAuthProfiles};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{c as normalizeAccountId,l as normalizeAgentId}from"./session-key-5J69DULS.js";import{o as normalizeChatChannelId}from"./registry-
|
|
1
|
+
import{c as normalizeAccountId,l as normalizeAgentId}from"./session-key-5J69DULS.js";import{o as normalizeChatChannelId}from"./registry-CZHRcH-q.js";import{c as resolveDefaultAgentId}from"./agent-scope-DgKN27hJ.js";function normalizeBindingChannelId(raw){return normalizeChatChannelId(raw)||(raw??``).trim().toLowerCase()||null}function listBindings(cfg){return Array.isArray(cfg.bindings)?cfg.bindings:[]}function resolveNormalizedBindingMatch(binding){if(!binding||typeof binding!=`object`)return null;let match=binding.match;if(!match||typeof match!=`object`)return null;let channelId=normalizeBindingChannelId(match.channel);if(!channelId)return null;let accountId=typeof match.accountId==`string`?match.accountId.trim():``;return!accountId||accountId===`*`?null:{agentId:normalizeAgentId(binding.agentId),accountId:normalizeAccountId(accountId),channelId}}function listBoundAccountIds(cfg,channelId){let normalizedChannel=normalizeBindingChannelId(channelId);if(!normalizedChannel)return[];let ids=new Set;for(let binding of listBindings(cfg)){let resolved=resolveNormalizedBindingMatch(binding);!resolved||resolved.channelId!==normalizedChannel||ids.add(resolved.accountId)}return Array.from(ids).toSorted((a,b)=>a.localeCompare(b))}function resolveDefaultAgentBoundAccountId(cfg,channelId){let normalizedChannel=normalizeBindingChannelId(channelId);if(!normalizedChannel)return null;let defaultAgentId=normalizeAgentId(resolveDefaultAgentId(cfg));for(let binding of listBindings(cfg)){let resolved=resolveNormalizedBindingMatch(binding);if(!(!resolved||resolved.channelId!==normalizedChannel||resolved.agentId!==defaultAgentId))return resolved.accountId}return null}export{listBoundAccountIds as n,resolveDefaultAgentBoundAccountId as r,listBindings as t};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{i as buildAgentMainSessionKey,l as normalizeAgentId,o as buildGroupHistoryKey,r as DEFAULT_MAIN_KEY}from"./session-key-5J69DULS.js";import{f as readWebSelfId,o as getWebAuthAgeMs,r as resolveWhatsAppAccount}from"./accounts-BwreSNAR.js";import{$ as formatLocationText,B as recordChannelActivity,Bt as createDedupeCache,O as enqueueSystemEvent,_ as resolveInboundDebounceMs,b as hasControlCommand,bt as buildMentionRegexes,c as computeBackoff,ct as shouldAckReactionForWhatsApp,d as formatDurationPrecise,et as toLocationContext,f as readChannelAllowFromStore,g as createInboundDebouncer,l as sleepWithAbort,lt as resolveMentionGating,m as dispatchReplyWithBufferedBlockDispatcher,mt as buildHistoryContextFromEntries,n as normalizeGroupActivation,p as upsertChannelPairingRequest,pt as DEFAULT_GROUP_HISTORY_LIMIT,r as parseActivationCommand,t as getReplyFromConfig,u as buildPairingReply,v as formatInboundEnvelope,x as shouldComputeCommandAuthorized,xt as normalizeMentionText,y as resolveEnvelopeFormatOptions,yt as recordPendingHistoryEntryIfEnabled}from"./reply-B5o-SSYy.js";import{A as resolveJidToE164,D as normalizeE164,E as jidToE164,F as sleep,G as shouldLogVerbose,H as logVerbose,L as toWhatsappJid,T as isSelfChatMode,Z as getChildLogger,_ as clamp,o as normalizeChatChannelId}from"./registry-DJq2Cvo9.js";import{n as loadConfig}from"./config-3vPn_hmp.js";import{i as defaultRuntime,t as createSubsystemLogger}from"./subsystem-COTa5Ly_.js";import{c as resolveIdentityNamePrefix,l as resolveMessagePrefix,n as createReplyPrefixOptions}from"./reply-prefix-CCymsmsP.js";import{An as recordSessionMetaFromInbound,Br as resolveChannelGroupRequireMention,On as loadSessionStore,c as registerUnhandledRejectionHandler,cr as resolveGroupSessionKey,dn as saveMediaBuffer,jn as updateLastRoute,kn as readSessionUpdatedAt,zr as resolveChannelGroupPolicy}from"./runner-C2pDJlRw.js";import{t as formatCliCommand}from"./command-format-CAX9XFjI.js";import{s as resolveStorePath}from"./paths-DtbnCdO7.js";import{i as convertMarkdownTables,r as setActiveWebListener}from"./active-listener-DpQ7aGYd.js";import{c as getAgentScopedMediaLocalRoots,o as loadWebMedia}from"./render-BUCRXPIk.js";import{c as resolveChunkMode,i as chunkMarkdownTextWithMode,l as resolveTextChunkLimit}from"./chunk-cW0POl22.js";import{n as resolveMarkdownTableMode}from"./markdown-tables-Epim9b-0.js";import{t as finalizeInboundContext}from"./inbound-context-BuKpttHk.js";import{n as resolveAgentRoute,t as buildAgentSessionKey}from"./resolve-route-DN1J7Wyc.js";import{i as markdownToWhatsApp,r as sendReactionWhatsApp}from"./outbound-CPutSvae.js";import{i as waitForWaConnection,n as formatError,r as getStatusCode,t as createWaSocket}from"./session-BnleckVX.js";import{randomUUID}from"node:crypto";import{getMaxListeners,setMaxListeners}from"node:events";import{DisconnectReason,downloadMediaMessage,extractMessageContent,getContentType,isJidGroup,normalizeMessageContent}from"@whiskeysockets/baileys";function getSessionRecipients(cfg){if((cfg.session?.scope??`per-sender`)===`global`)return[];let store=loadSessionStore(resolveStorePath(cfg.session?.store)),isGroupKey=key=>key.includes(`:group:`)||key.includes(`:channel:`)||key.includes(`@g.us`),isCronKey=key=>key.startsWith(`cron:`),recipients=Object.entries(store).filter(([key])=>key!==`global`&&key!==`unknown`).filter(([key])=>!isGroupKey(key)&&!isCronKey(key)).map(([_,entry])=>({to:normalizeChatChannelId(entry?.lastChannel)===`whatsapp`&&entry?.lastTo?normalizeE164(entry.lastTo):``,updatedAt:entry?.updatedAt??0})).filter(({to})=>to.length>1).toSorted((a,b)=>b.updatedAt-a.updatedAt),seen=new Set;return recipients.filter(r=>seen.has(r.to)?!1:(seen.add(r.to),!0))}function resolveWhatsAppHeartbeatRecipients(cfg,opts={}){if(opts.to)return{recipients:[normalizeE164(opts.to)],source:`flag`};let sessionRecipients=getSessionRecipients(cfg),allowFrom=Array.isArray(cfg.channels?.whatsapp?.allowFrom)&&cfg.channels.whatsapp.allowFrom.length>0?cfg.channels.whatsapp.allowFrom.filter(v=>v!==`*`).map(normalizeE164):[];return opts.all?{recipients:(list=>[...new Set(list.filter(Boolean))])([...sessionRecipients.map(s=>s.to),...allowFrom]),source:`all`}:sessionRecipients.length===1?{recipients:[sessionRecipients[0].to],source:`session-single`}:sessionRecipients.length>1?{recipients:sessionRecipients.map(s=>s.to),source:`session-ambiguous`}:{recipients:allowFrom,source:`allowFrom`}}const DEFAULT_RECONNECT_POLICY={initialMs:2e3,maxMs:3e4,factor:1.8,jitter:.25,maxAttempts:12};function resolveHeartbeatSeconds(cfg,overrideSeconds){let candidate=overrideSeconds??cfg.web?.heartbeatSeconds;return typeof candidate==`number`&&candidate>0?candidate:60}function resolveReconnectPolicy(cfg,overrides){let reconnectOverrides=cfg.web?.reconnect??{},overrideConfig=overrides??{},merged={...DEFAULT_RECONNECT_POLICY,...reconnectOverrides,...overrideConfig};return merged.initialMs=Math.max(250,merged.initialMs),merged.maxMs=Math.max(merged.initialMs,merged.maxMs),merged.factor=clamp(merged.factor,1.1,10),merged.jitter=clamp(merged.jitter,0,1),merged.maxAttempts=Math.max(0,Math.floor(merged.maxAttempts)),merged}function newConnectionId(){return randomUUID()}const whatsappLog=createSubsystemLogger(`gateway/channels/whatsapp`),whatsappInboundLog=whatsappLog.child(`inbound`),whatsappOutboundLog=whatsappLog.child(`outbound`),whatsappHeartbeatLog=whatsappLog.child(`heartbeat`);function elide(text,limit=400){return!text||text.length<=limit?text:`${text.slice(0,limit)}… (truncated ${text.length-limit} chars)`}function isLikelyWhatsAppCryptoError(reason){let haystack=(reason instanceof Error?`${reason.message}\n${reason.stack??``}`:(value=>{if(value==null)return``;if(typeof value==`string`)return value;if(value instanceof Error)return`${value.message}\n${value.stack??``}`;if(typeof value==`object`)try{return JSON.stringify(value)}catch{return Object.prototype.toString.call(value)}return typeof value==`number`||typeof value==`boolean`||typeof value==`bigint`?String(value):typeof value==`symbol`?value.description??value.toString():typeof value==`function`?value.name?`[function ${value.name}]`:`[function]`:Object.prototype.toString.call(value)})(reason)).toLowerCase();return haystack.includes(`unsupported state or unable to authenticate data`)||haystack.includes(`bad mac`)?haystack.includes(`@whiskeysockets/baileys`)||haystack.includes(`baileys`)||haystack.includes(`noise-handler`)||haystack.includes(`aesdecryptgcm`):!1}function waitForever(){return setInterval(()=>{},1e6).unref(),new Promise(()=>{})}const recentInboundMessages=createDedupeCache({ttlMs:20*6e4,maxSize:5e3});function isRecentInboundMessage(key){return recentInboundMessages.check(key)}const ALLOWED_VCARD_KEYS=new Set([`FN`,`N`,`TEL`]);function parseVcard(vcard){if(!vcard)return{phones:[]};let lines=vcard.split(/\r?\n/),nameFromN,nameFromFn,phones=[];for(let rawLine of lines){let line=rawLine.trim();if(!line)continue;let colonIndex=line.indexOf(`:`);if(colonIndex===-1)continue;let key=line.slice(0,colonIndex).toUpperCase(),rawValue=line.slice(colonIndex+1).trim();if(!rawValue)continue;let baseKey=normalizeVcardKey(key);if(!baseKey||!ALLOWED_VCARD_KEYS.has(baseKey))continue;let value=cleanVcardValue(rawValue);if(value){if(baseKey===`FN`&&!nameFromFn){nameFromFn=normalizeVcardName(value);continue}if(baseKey===`N`&&!nameFromN){nameFromN=normalizeVcardName(value);continue}if(baseKey===`TEL`){let phone=normalizeVcardPhone(value);phone&&phones.push(phone)}}}return{name:nameFromFn??nameFromN,phones}}function normalizeVcardKey(key){let[primary]=key.split(`;`);if(!primary)return;let segments=primary.split(`.`);return segments[segments.length-1]||void 0}function cleanVcardValue(value){return value.replace(/\\n/gi,` `).replace(/\\,/g,`,`).replace(/\\;/g,`;`).trim()}function normalizeVcardName(value){return value.replace(/;/g,` `).replace(/\s+/g,` `).trim()}function normalizeVcardPhone(value){let trimmed=value.trim();return trimmed?trimmed.toLowerCase().startsWith(`tel:`)?trimmed.slice(4).trim():trimmed:``}function unwrapMessage$1(message){return normalizeMessageContent(message)}function extractContextInfo(message){if(!message)return;let contentType=getContentType(message),candidate=contentType?message[contentType]:void 0,contextInfo=candidate&&typeof candidate==`object`&&`contextInfo`in candidate?candidate.contextInfo:void 0;if(contextInfo)return contextInfo;let fallback=message.extendedTextMessage?.contextInfo??message.imageMessage?.contextInfo??message.videoMessage?.contextInfo??message.documentMessage?.contextInfo??message.audioMessage?.contextInfo??message.stickerMessage?.contextInfo??message.buttonsResponseMessage?.contextInfo??message.listResponseMessage?.contextInfo??message.templateButtonReplyMessage?.contextInfo??message.interactiveResponseMessage?.contextInfo??message.buttonsMessage?.contextInfo??message.listMessage?.contextInfo;if(fallback)return fallback;for(let value of Object.values(message)){if(!value||typeof value!=`object`||!(`contextInfo`in value))continue;let candidateContext=value.contextInfo;if(candidateContext)return candidateContext}}function extractMentionedJids(rawMessage){let message=unwrapMessage$1(rawMessage);if(!message)return;let flattened=[message.extendedTextMessage?.contextInfo?.mentionedJid,message.extendedTextMessage?.contextInfo?.quotedMessage?.extendedTextMessage?.contextInfo?.mentionedJid,message.imageMessage?.contextInfo?.mentionedJid,message.videoMessage?.contextInfo?.mentionedJid,message.documentMessage?.contextInfo?.mentionedJid,message.audioMessage?.contextInfo?.mentionedJid,message.stickerMessage?.contextInfo?.mentionedJid,message.buttonsResponseMessage?.contextInfo?.mentionedJid,message.listResponseMessage?.contextInfo?.mentionedJid].flatMap(arr=>arr??[]).filter(Boolean);if(flattened.length!==0)return Array.from(new Set(flattened))}function extractText(rawMessage){let message=unwrapMessage$1(rawMessage);if(!message)return;let extracted=extractMessageContent(message),candidates=[message,extracted&&extracted!==message?extracted:void 0];for(let candidate of candidates){if(!candidate)continue;if(typeof candidate.conversation==`string`&&candidate.conversation.trim())return candidate.conversation.trim();let extended=candidate.extendedTextMessage?.text;if(extended?.trim())return extended.trim();let caption=candidate.imageMessage?.caption??candidate.videoMessage?.caption??candidate.documentMessage?.caption;if(caption?.trim())return caption.trim()}let contactPlaceholder=extractContactPlaceholder(message)??(extracted&&extracted!==message?extractContactPlaceholder(extracted):void 0);if(contactPlaceholder)return contactPlaceholder}function extractMediaPlaceholder(rawMessage){let message=unwrapMessage$1(rawMessage);if(message){if(message.imageMessage)return`<media:image>`;if(message.videoMessage)return`<media:video>`;if(message.audioMessage)return`<media:audio>`;if(message.documentMessage)return`<media:document>`;if(message.stickerMessage)return`<media:sticker>`}}function extractContactPlaceholder(rawMessage){let message=unwrapMessage$1(rawMessage);if(!message)return;let contact=message.contactMessage??void 0;if(contact){let{name,phones}=describeContact({displayName:contact.displayName,vcard:contact.vcard});return formatContactPlaceholder(name,phones)}let contactsArray=message.contactsArrayMessage?.contacts??void 0;if(!(!contactsArray||contactsArray.length===0))return formatContactsPlaceholder(contactsArray.map(entry=>describeContact({displayName:entry.displayName,vcard:entry.vcard})).map(entry=>formatContactLabel(entry.name,entry.phones)).filter(value=>!!value),contactsArray.length)}function describeContact(input){let displayName=(input.displayName??``).trim(),parsed=parseVcard(input.vcard??void 0);return{name:displayName||parsed.name,phones:parsed.phones}}function formatContactPlaceholder(name,phones){let label=formatContactLabel(name,phones);return label?`<contact: ${label}>`:`<contact>`}function formatContactsPlaceholder(labels,total){let cleaned=labels.map(label=>label.trim()).filter(Boolean);if(cleaned.length===0)return`<contacts: ${total} ${total===1?`contact`:`contacts`}>`;let remaining=Math.max(total-cleaned.length,0),suffix=remaining>0?` +${remaining} more`:``;return`<contacts: ${cleaned.join(`, `)}${suffix}>`}function formatContactLabel(name,phones){let parts=[name,formatPhoneList(phones)].filter(value=>!!value);if(parts.length!==0)return parts.join(`, `)}function formatPhoneList(phones){let cleaned=phones?.map(phone=>phone.trim()).filter(Boolean)??[];if(cleaned.length===0)return;let{shown,remaining}=summarizeList(cleaned,cleaned.length,1),[primary]=shown;if(primary)return remaining===0?primary:`${primary} (+${remaining} more)`}function summarizeList(values,total,maxShown){let shown=values.slice(0,maxShown);return{shown,remaining:Math.max(total-shown.length,0)}}function extractLocationData(rawMessage){let message=unwrapMessage$1(rawMessage);if(!message)return null;let live=message.liveLocationMessage??void 0;if(live){let latitudeRaw=live.degreesLatitude,longitudeRaw=live.degreesLongitude;if(latitudeRaw!=null&&longitudeRaw!=null){let latitude=Number(latitudeRaw),longitude=Number(longitudeRaw);if(Number.isFinite(latitude)&&Number.isFinite(longitude))return{latitude,longitude,accuracy:live.accuracyInMeters??void 0,caption:live.caption??void 0,source:`live`,isLive:!0}}}let location=message.locationMessage??void 0;if(location){let latitudeRaw=location.degreesLatitude,longitudeRaw=location.degreesLongitude;if(latitudeRaw!=null&&longitudeRaw!=null){let latitude=Number(latitudeRaw),longitude=Number(longitudeRaw);if(Number.isFinite(latitude)&&Number.isFinite(longitude)){let isLive=!!location.isLive;return{latitude,longitude,accuracy:location.accuracyInMeters??void 0,name:location.name??void 0,address:location.address??void 0,caption:location.comment??void 0,source:isLive?`live`:location.name||location.address?`place`:`pin`,isLive}}}}return null}function describeReplyContext(rawMessage){let message=unwrapMessage$1(rawMessage);if(!message)return null;let contextInfo=extractContextInfo(message),quoted=normalizeMessageContent(contextInfo?.quotedMessage);if(!quoted)return null;let location=extractLocationData(quoted),locationText=location?formatLocationText(location):void 0,body=[extractText(quoted),locationText].filter(Boolean).join(`
|
|
1
|
+
import{i as buildAgentMainSessionKey,l as normalizeAgentId,o as buildGroupHistoryKey,r as DEFAULT_MAIN_KEY}from"./session-key-5J69DULS.js";import{f as readWebSelfId,o as getWebAuthAgeMs,r as resolveWhatsAppAccount}from"./accounts-Cy3WCbWg.js";import{$ as formatLocationText,B as recordChannelActivity,Bt as createDedupeCache,O as enqueueSystemEvent,_ as resolveInboundDebounceMs,b as hasControlCommand,bt as buildMentionRegexes,c as computeBackoff,ct as shouldAckReactionForWhatsApp,d as formatDurationPrecise,et as toLocationContext,f as readChannelAllowFromStore,g as createInboundDebouncer,l as sleepWithAbort,lt as resolveMentionGating,m as dispatchReplyWithBufferedBlockDispatcher,mt as buildHistoryContextFromEntries,n as normalizeGroupActivation,p as upsertChannelPairingRequest,pt as DEFAULT_GROUP_HISTORY_LIMIT,r as parseActivationCommand,t as getReplyFromConfig,u as buildPairingReply,v as formatInboundEnvelope,x as shouldComputeCommandAuthorized,xt as normalizeMentionText,y as resolveEnvelopeFormatOptions,yt as recordPendingHistoryEntryIfEnabled}from"./reply-BOVC-7UD.js";import{A as resolveJidToE164,D as normalizeE164,E as jidToE164,F as sleep,G as shouldLogVerbose,H as logVerbose,L as toWhatsappJid,T as isSelfChatMode,Z as getChildLogger,_ as clamp,o as normalizeChatChannelId}from"./registry-CZHRcH-q.js";import{n as loadConfig}from"./config--Ci8Y91R.js";import{i as defaultRuntime,t as createSubsystemLogger}from"./subsystem-D0Ril4rt.js";import{c as resolveIdentityNamePrefix,l as resolveMessagePrefix,n as createReplyPrefixOptions}from"./reply-prefix-w7kAvH11.js";import{An as recordSessionMetaFromInbound,Br as resolveChannelGroupRequireMention,On as loadSessionStore,c as registerUnhandledRejectionHandler,cr as resolveGroupSessionKey,dn as saveMediaBuffer,jn as updateLastRoute,kn as readSessionUpdatedAt,zr as resolveChannelGroupPolicy}from"./runner-DKoKK09-.js";import{t as formatCliCommand}from"./command-format-B3XMq_73.js";import{s as resolveStorePath}from"./paths-DtbnCdO7.js";import{i as convertMarkdownTables,r as setActiveWebListener}from"./active-listener-DVWVNlT9.js";import{c as getAgentScopedMediaLocalRoots,o as loadWebMedia}from"./render-CuA_WRX5.js";import{c as resolveChunkMode,i as chunkMarkdownTextWithMode,l as resolveTextChunkLimit}from"./chunk-C94IAOuf.js";import{n as resolveMarkdownTableMode}from"./markdown-tables-BUfhHgfs.js";import{t as finalizeInboundContext}from"./inbound-context-BuKpttHk.js";import{n as resolveAgentRoute,t as buildAgentSessionKey}from"./resolve-route-0sbvl4ZN.js";import{i as markdownToWhatsApp,r as sendReactionWhatsApp}from"./outbound-Djibdmi7.js";import{i as waitForWaConnection,n as formatError,r as getStatusCode,t as createWaSocket}from"./session-DGLuyt10.js";import{randomUUID}from"node:crypto";import{getMaxListeners,setMaxListeners}from"node:events";import{DisconnectReason,downloadMediaMessage,extractMessageContent,getContentType,isJidGroup,normalizeMessageContent}from"@whiskeysockets/baileys";function getSessionRecipients(cfg){if((cfg.session?.scope??`per-sender`)===`global`)return[];let store=loadSessionStore(resolveStorePath(cfg.session?.store)),isGroupKey=key=>key.includes(`:group:`)||key.includes(`:channel:`)||key.includes(`@g.us`),isCronKey=key=>key.startsWith(`cron:`),recipients=Object.entries(store).filter(([key])=>key!==`global`&&key!==`unknown`).filter(([key])=>!isGroupKey(key)&&!isCronKey(key)).map(([_,entry])=>({to:normalizeChatChannelId(entry?.lastChannel)===`whatsapp`&&entry?.lastTo?normalizeE164(entry.lastTo):``,updatedAt:entry?.updatedAt??0})).filter(({to})=>to.length>1).toSorted((a,b)=>b.updatedAt-a.updatedAt),seen=new Set;return recipients.filter(r=>seen.has(r.to)?!1:(seen.add(r.to),!0))}function resolveWhatsAppHeartbeatRecipients(cfg,opts={}){if(opts.to)return{recipients:[normalizeE164(opts.to)],source:`flag`};let sessionRecipients=getSessionRecipients(cfg),allowFrom=Array.isArray(cfg.channels?.whatsapp?.allowFrom)&&cfg.channels.whatsapp.allowFrom.length>0?cfg.channels.whatsapp.allowFrom.filter(v=>v!==`*`).map(normalizeE164):[];return opts.all?{recipients:(list=>[...new Set(list.filter(Boolean))])([...sessionRecipients.map(s=>s.to),...allowFrom]),source:`all`}:sessionRecipients.length===1?{recipients:[sessionRecipients[0].to],source:`session-single`}:sessionRecipients.length>1?{recipients:sessionRecipients.map(s=>s.to),source:`session-ambiguous`}:{recipients:allowFrom,source:`allowFrom`}}const DEFAULT_RECONNECT_POLICY={initialMs:2e3,maxMs:3e4,factor:1.8,jitter:.25,maxAttempts:12};function resolveHeartbeatSeconds(cfg,overrideSeconds){let candidate=overrideSeconds??cfg.web?.heartbeatSeconds;return typeof candidate==`number`&&candidate>0?candidate:60}function resolveReconnectPolicy(cfg,overrides){let reconnectOverrides=cfg.web?.reconnect??{},overrideConfig=overrides??{},merged={...DEFAULT_RECONNECT_POLICY,...reconnectOverrides,...overrideConfig};return merged.initialMs=Math.max(250,merged.initialMs),merged.maxMs=Math.max(merged.initialMs,merged.maxMs),merged.factor=clamp(merged.factor,1.1,10),merged.jitter=clamp(merged.jitter,0,1),merged.maxAttempts=Math.max(0,Math.floor(merged.maxAttempts)),merged}function newConnectionId(){return randomUUID()}const whatsappLog=createSubsystemLogger(`gateway/channels/whatsapp`),whatsappInboundLog=whatsappLog.child(`inbound`),whatsappOutboundLog=whatsappLog.child(`outbound`),whatsappHeartbeatLog=whatsappLog.child(`heartbeat`);function elide(text,limit=400){return!text||text.length<=limit?text:`${text.slice(0,limit)}… (truncated ${text.length-limit} chars)`}function isLikelyWhatsAppCryptoError(reason){let haystack=(reason instanceof Error?`${reason.message}\n${reason.stack??``}`:(value=>{if(value==null)return``;if(typeof value==`string`)return value;if(value instanceof Error)return`${value.message}\n${value.stack??``}`;if(typeof value==`object`)try{return JSON.stringify(value)}catch{return Object.prototype.toString.call(value)}return typeof value==`number`||typeof value==`boolean`||typeof value==`bigint`?String(value):typeof value==`symbol`?value.description??value.toString():typeof value==`function`?value.name?`[function ${value.name}]`:`[function]`:Object.prototype.toString.call(value)})(reason)).toLowerCase();return haystack.includes(`unsupported state or unable to authenticate data`)||haystack.includes(`bad mac`)?haystack.includes(`@whiskeysockets/baileys`)||haystack.includes(`baileys`)||haystack.includes(`noise-handler`)||haystack.includes(`aesdecryptgcm`):!1}function waitForever(){return setInterval(()=>{},1e6).unref(),new Promise(()=>{})}const recentInboundMessages=createDedupeCache({ttlMs:20*6e4,maxSize:5e3});function isRecentInboundMessage(key){return recentInboundMessages.check(key)}const ALLOWED_VCARD_KEYS=new Set([`FN`,`N`,`TEL`]);function parseVcard(vcard){if(!vcard)return{phones:[]};let lines=vcard.split(/\r?\n/),nameFromN,nameFromFn,phones=[];for(let rawLine of lines){let line=rawLine.trim();if(!line)continue;let colonIndex=line.indexOf(`:`);if(colonIndex===-1)continue;let key=line.slice(0,colonIndex).toUpperCase(),rawValue=line.slice(colonIndex+1).trim();if(!rawValue)continue;let baseKey=normalizeVcardKey(key);if(!baseKey||!ALLOWED_VCARD_KEYS.has(baseKey))continue;let value=cleanVcardValue(rawValue);if(value){if(baseKey===`FN`&&!nameFromFn){nameFromFn=normalizeVcardName(value);continue}if(baseKey===`N`&&!nameFromN){nameFromN=normalizeVcardName(value);continue}if(baseKey===`TEL`){let phone=normalizeVcardPhone(value);phone&&phones.push(phone)}}}return{name:nameFromFn??nameFromN,phones}}function normalizeVcardKey(key){let[primary]=key.split(`;`);if(!primary)return;let segments=primary.split(`.`);return segments[segments.length-1]||void 0}function cleanVcardValue(value){return value.replace(/\\n/gi,` `).replace(/\\,/g,`,`).replace(/\\;/g,`;`).trim()}function normalizeVcardName(value){return value.replace(/;/g,` `).replace(/\s+/g,` `).trim()}function normalizeVcardPhone(value){let trimmed=value.trim();return trimmed?trimmed.toLowerCase().startsWith(`tel:`)?trimmed.slice(4).trim():trimmed:``}function unwrapMessage$1(message){return normalizeMessageContent(message)}function extractContextInfo(message){if(!message)return;let contentType=getContentType(message),candidate=contentType?message[contentType]:void 0,contextInfo=candidate&&typeof candidate==`object`&&`contextInfo`in candidate?candidate.contextInfo:void 0;if(contextInfo)return contextInfo;let fallback=message.extendedTextMessage?.contextInfo??message.imageMessage?.contextInfo??message.videoMessage?.contextInfo??message.documentMessage?.contextInfo??message.audioMessage?.contextInfo??message.stickerMessage?.contextInfo??message.buttonsResponseMessage?.contextInfo??message.listResponseMessage?.contextInfo??message.templateButtonReplyMessage?.contextInfo??message.interactiveResponseMessage?.contextInfo??message.buttonsMessage?.contextInfo??message.listMessage?.contextInfo;if(fallback)return fallback;for(let value of Object.values(message)){if(!value||typeof value!=`object`||!(`contextInfo`in value))continue;let candidateContext=value.contextInfo;if(candidateContext)return candidateContext}}function extractMentionedJids(rawMessage){let message=unwrapMessage$1(rawMessage);if(!message)return;let flattened=[message.extendedTextMessage?.contextInfo?.mentionedJid,message.extendedTextMessage?.contextInfo?.quotedMessage?.extendedTextMessage?.contextInfo?.mentionedJid,message.imageMessage?.contextInfo?.mentionedJid,message.videoMessage?.contextInfo?.mentionedJid,message.documentMessage?.contextInfo?.mentionedJid,message.audioMessage?.contextInfo?.mentionedJid,message.stickerMessage?.contextInfo?.mentionedJid,message.buttonsResponseMessage?.contextInfo?.mentionedJid,message.listResponseMessage?.contextInfo?.mentionedJid].flatMap(arr=>arr??[]).filter(Boolean);if(flattened.length!==0)return Array.from(new Set(flattened))}function extractText(rawMessage){let message=unwrapMessage$1(rawMessage);if(!message)return;let extracted=extractMessageContent(message),candidates=[message,extracted&&extracted!==message?extracted:void 0];for(let candidate of candidates){if(!candidate)continue;if(typeof candidate.conversation==`string`&&candidate.conversation.trim())return candidate.conversation.trim();let extended=candidate.extendedTextMessage?.text;if(extended?.trim())return extended.trim();let caption=candidate.imageMessage?.caption??candidate.videoMessage?.caption??candidate.documentMessage?.caption;if(caption?.trim())return caption.trim()}let contactPlaceholder=extractContactPlaceholder(message)??(extracted&&extracted!==message?extractContactPlaceholder(extracted):void 0);if(contactPlaceholder)return contactPlaceholder}function extractMediaPlaceholder(rawMessage){let message=unwrapMessage$1(rawMessage);if(message){if(message.imageMessage)return`<media:image>`;if(message.videoMessage)return`<media:video>`;if(message.audioMessage)return`<media:audio>`;if(message.documentMessage)return`<media:document>`;if(message.stickerMessage)return`<media:sticker>`}}function extractContactPlaceholder(rawMessage){let message=unwrapMessage$1(rawMessage);if(!message)return;let contact=message.contactMessage??void 0;if(contact){let{name,phones}=describeContact({displayName:contact.displayName,vcard:contact.vcard});return formatContactPlaceholder(name,phones)}let contactsArray=message.contactsArrayMessage?.contacts??void 0;if(!(!contactsArray||contactsArray.length===0))return formatContactsPlaceholder(contactsArray.map(entry=>describeContact({displayName:entry.displayName,vcard:entry.vcard})).map(entry=>formatContactLabel(entry.name,entry.phones)).filter(value=>!!value),contactsArray.length)}function describeContact(input){let displayName=(input.displayName??``).trim(),parsed=parseVcard(input.vcard??void 0);return{name:displayName||parsed.name,phones:parsed.phones}}function formatContactPlaceholder(name,phones){let label=formatContactLabel(name,phones);return label?`<contact: ${label}>`:`<contact>`}function formatContactsPlaceholder(labels,total){let cleaned=labels.map(label=>label.trim()).filter(Boolean);if(cleaned.length===0)return`<contacts: ${total} ${total===1?`contact`:`contacts`}>`;let remaining=Math.max(total-cleaned.length,0),suffix=remaining>0?` +${remaining} more`:``;return`<contacts: ${cleaned.join(`, `)}${suffix}>`}function formatContactLabel(name,phones){let parts=[name,formatPhoneList(phones)].filter(value=>!!value);if(parts.length!==0)return parts.join(`, `)}function formatPhoneList(phones){let cleaned=phones?.map(phone=>phone.trim()).filter(Boolean)??[];if(cleaned.length===0)return;let{shown,remaining}=summarizeList(cleaned,cleaned.length,1),[primary]=shown;if(primary)return remaining===0?primary:`${primary} (+${remaining} more)`}function summarizeList(values,total,maxShown){let shown=values.slice(0,maxShown);return{shown,remaining:Math.max(total-shown.length,0)}}function extractLocationData(rawMessage){let message=unwrapMessage$1(rawMessage);if(!message)return null;let live=message.liveLocationMessage??void 0;if(live){let latitudeRaw=live.degreesLatitude,longitudeRaw=live.degreesLongitude;if(latitudeRaw!=null&&longitudeRaw!=null){let latitude=Number(latitudeRaw),longitude=Number(longitudeRaw);if(Number.isFinite(latitude)&&Number.isFinite(longitude))return{latitude,longitude,accuracy:live.accuracyInMeters??void 0,caption:live.caption??void 0,source:`live`,isLive:!0}}}let location=message.locationMessage??void 0;if(location){let latitudeRaw=location.degreesLatitude,longitudeRaw=location.degreesLongitude;if(latitudeRaw!=null&&longitudeRaw!=null){let latitude=Number(latitudeRaw),longitude=Number(longitudeRaw);if(Number.isFinite(latitude)&&Number.isFinite(longitude)){let isLive=!!location.isLive;return{latitude,longitude,accuracy:location.accuracyInMeters??void 0,name:location.name??void 0,address:location.address??void 0,caption:location.comment??void 0,source:isLive?`live`:location.name||location.address?`place`:`pin`,isLive}}}}return null}function describeReplyContext(rawMessage){let message=unwrapMessage$1(rawMessage);if(!message)return null;let contextInfo=extractContextInfo(message),quoted=normalizeMessageContent(contextInfo?.quotedMessage);if(!quoted)return null;let location=extractLocationData(quoted),locationText=location?formatLocationText(location):void 0,body=[extractText(quoted),locationText].filter(Boolean).join(`
|
|
2
2
|
`).trim();if(body||=extractMediaPlaceholder(quoted),!body){let quotedType=quoted?getContentType(quoted):void 0;return logVerbose(`Quoted message missing extractable body${quotedType?` (type ${quotedType})`:``}`),null}let senderJid=contextInfo?.participant??void 0,senderE164=senderJid?jidToE164(senderJid)??senderJid:void 0,sender=senderE164??`unknown sender`;return{id:contextInfo?.stanzaId?String(contextInfo.stanzaId):void 0,body,sender,senderJid,senderE164}}async function checkInboundAccessControl(params){let cfg=loadConfig(),account=resolveWhatsAppAccount({cfg,accountId:params.accountId}),dmPolicy=account.dmPolicy??`pairing`,configuredAllowFrom=account.allowFrom,storeAllowFrom=await readChannelAllowFromStore(`whatsapp`,process.env,account.accountId).catch(()=>[]),combinedAllowFrom=Array.from(new Set([...configuredAllowFrom??[],...storeAllowFrom])),defaultAllowFrom=combinedAllowFrom.length===0&¶ms.selfE164?[params.selfE164]:void 0,allowFrom=combinedAllowFrom.length>0?combinedAllowFrom:defaultAllowFrom,groupAllowFrom=account.groupAllowFrom??(configuredAllowFrom&&configuredAllowFrom.length>0?configuredAllowFrom:void 0),isSamePhone=params.from===params.selfE164,isSelfChat=isSelfChatMode(params.selfE164,configuredAllowFrom),pairingGraceMs=typeof params.pairingGraceMs==`number`&¶ms.pairingGraceMs>0?params.pairingGraceMs:3e4,suppressPairingReply=typeof params.connectedAtMs==`number`&&typeof params.messageTimestampMs==`number`&¶ms.messageTimestampMs<params.connectedAtMs-pairingGraceMs,dmHasWildcard=allowFrom?.includes(`*`)??!1,normalizedAllowFrom=allowFrom&&allowFrom.length>0?allowFrom.filter(entry=>entry!==`*`).map(normalizeE164):[],groupHasWildcard=groupAllowFrom?.includes(`*`)??!1,normalizedGroupAllowFrom=groupAllowFrom&&groupAllowFrom.length>0?groupAllowFrom.filter(entry=>entry!==`*`).map(normalizeE164):[],defaultGroupPolicy=cfg.channels?.defaults?.groupPolicy,groupPolicy=account.groupPolicy??defaultGroupPolicy??`open`;if(params.group&&groupPolicy===`disabled`)return logVerbose(`Blocked group message (groupPolicy: disabled)`),{allowed:!1,shouldMarkRead:!1,isSelfChat,resolvedAccountId:account.accountId};if(params.group&&groupPolicy===`allowlist`){if(!groupAllowFrom||groupAllowFrom.length===0)return logVerbose(`Blocked group message (groupPolicy: allowlist, no groupAllowFrom)`),{allowed:!1,shouldMarkRead:!1,isSelfChat,resolvedAccountId:account.accountId};if(!(groupHasWildcard||params.senderE164!=null&&normalizedGroupAllowFrom.includes(params.senderE164)))return logVerbose(`Blocked group message from ${params.senderE164??`unknown sender`} (groupPolicy: allowlist)`),{allowed:!1,shouldMarkRead:!1,isSelfChat,resolvedAccountId:account.accountId}}if(!params.group){if(params.isFromMe&&!isSamePhone)return logVerbose(`Skipping outbound DM (fromMe); no pairing reply needed.`),{allowed:!1,shouldMarkRead:!1,isSelfChat,resolvedAccountId:account.accountId};if(dmPolicy===`disabled`)return logVerbose(`Blocked dm (dmPolicy: disabled)`),{allowed:!1,shouldMarkRead:!1,isSelfChat,resolvedAccountId:account.accountId};if(dmPolicy!==`open`&&!isSamePhone){let candidate=params.from;if(!(dmHasWildcard||normalizedAllowFrom.length>0&&normalizedAllowFrom.includes(candidate))){if(dmPolicy===`pairing`)if(suppressPairingReply)logVerbose(`Skipping pairing reply for historical DM from ${candidate}.`);else{let{code,created}=await upsertChannelPairingRequest({channel:`whatsapp`,id:candidate,accountId:account.accountId,meta:{name:(params.pushName??``).trim()||void 0}});if(created){logVerbose(`whatsapp pairing request sender=${candidate} name=${params.pushName??`unknown`}`);try{await params.sock.sendMessage(params.remoteJid,{text:buildPairingReply({channel:`whatsapp`,idLine:`Your WhatsApp phone number: ${candidate}`,code})})}catch(err){logVerbose(`whatsapp pairing reply failed for ${candidate}: ${String(err)}`)}}}else logVerbose(`Blocked unauthorized sender ${candidate} (dmPolicy=${dmPolicy})`);return{allowed:!1,shouldMarkRead:!1,isSelfChat,resolvedAccountId:account.accountId}}}}return{allowed:!0,shouldMarkRead:!0,isSelfChat,resolvedAccountId:account.accountId}}function unwrapMessage(message){return normalizeMessageContent(message)}function resolveMediaMimetype(message){let explicit=message.imageMessage?.mimetype??message.videoMessage?.mimetype??message.documentMessage?.mimetype??message.audioMessage?.mimetype??message.stickerMessage?.mimetype??void 0;if(explicit)return explicit;if(message.audioMessage)return`audio/ogg; codecs=opus`;if(message.imageMessage)return`image/jpeg`;if(message.videoMessage)return`video/mp4`;if(message.stickerMessage)return`image/webp`}async function downloadInboundMedia(msg,sock){let message=unwrapMessage(msg.message);if(!message)return;let mimetype=resolveMediaMimetype(message),fileName=message.documentMessage?.fileName??void 0;if(!(!message.imageMessage&&!message.videoMessage&&!message.documentMessage&&!message.audioMessage&&!message.stickerMessage))try{return{buffer:await downloadMediaMessage(msg,`buffer`,{},{reuploadRequest:sock.updateMediaMessage,logger:sock.logger}),mimetype,fileName}}catch(err){logVerbose(`downloadMediaMessage failed: ${String(err)}`);return}}function recordWhatsAppOutbound(accountId){recordChannelActivity({channel:`whatsapp`,accountId,direction:`outbound`})}function resolveOutboundMessageId(result){return typeof result==`object`&&result&&`key`in result?String(result.key?.id??`unknown`):`unknown`}function createWebSendApi(params){return{sendMessage:async(to,text,mediaBuffer,mediaType,sendOptions)=>{let jid=toWhatsappJid(to),payload;if(mediaBuffer&&mediaType)if(mediaType.startsWith(`image/`))payload={image:mediaBuffer,caption:text||void 0,mimetype:mediaType};else if(mediaType.startsWith(`audio/`))payload={audio:mediaBuffer,ptt:!0,mimetype:mediaType};else if(mediaType.startsWith(`video/`)){let gifPlayback=sendOptions?.gifPlayback;payload={video:mediaBuffer,caption:text||void 0,mimetype:mediaType,...gifPlayback?{gifPlayback:!0}:{}}}else payload={document:mediaBuffer,fileName:sendOptions?.fileName?.trim()||`file`,caption:text||void 0,mimetype:mediaType};else payload={text};let result=await params.sock.sendMessage(jid,payload);return recordWhatsAppOutbound(sendOptions?.accountId??params.defaultAccountId),{messageId:resolveOutboundMessageId(result)}},sendPoll:async(to,poll)=>{let jid=toWhatsappJid(to),result=await params.sock.sendMessage(jid,{poll:{name:poll.question,values:poll.options,selectableCount:poll.maxSelections??1}});return recordWhatsAppOutbound(params.defaultAccountId),{messageId:resolveOutboundMessageId(result)}},sendReaction:async(chatJid,messageId,emoji,fromMe,participant)=>{let jid=toWhatsappJid(chatJid);await params.sock.sendMessage(jid,{react:{text:emoji,key:{remoteJid:jid,id:messageId,fromMe,participant:participant?toWhatsappJid(participant):void 0}}})},sendComposingTo:async to=>{let jid=toWhatsappJid(to);await params.sock.sendPresenceUpdate(`composing`,jid)}}}async function monitorWebInbox(options){let inboundLogger=getChildLogger({module:`web-inbound`}),inboundConsoleLog=createSubsystemLogger(`gateway/channels/whatsapp`).child(`inbound`),sock=await createWaSocket(!1,options.verbose,{authDir:options.authDir});await waitForWaConnection(sock);let connectedAtMs=Date.now(),onCloseResolve=null,onClose=new Promise(resolve=>{onCloseResolve=resolve}),resolveClose=reason=>{if(!onCloseResolve)return;let resolver=onCloseResolve;onCloseResolve=null,resolver(reason)};try{await sock.sendPresenceUpdate(`available`),shouldLogVerbose()&&logVerbose(`Sent global 'available' presence on connect`)}catch(err){logVerbose(`Failed to send 'available' presence on connect: ${String(err)}`)}let selfJid=sock.user?.id,selfE164=selfJid?jidToE164(selfJid):null,debouncer=createInboundDebouncer({debounceMs:options.debounceMs??0,buildKey:msg=>{let senderKey=msg.chatType===`group`?msg.senderJid??msg.senderE164??msg.senderName??msg.from:msg.from;if(!senderKey)return null;let conversationKey=msg.chatType===`group`?msg.chatId:msg.from;return`${msg.accountId}:${conversationKey}:${senderKey}`},shouldDebounce:options.shouldDebounce,onFlush:async entries=>{let last=entries.at(-1);if(!last)return;if(entries.length===1){await options.onMessage(last);return}let mentioned=new Set;for(let entry of entries)for(let jid of entry.mentionedJids??[])mentioned.add(jid);let combinedBody=entries.map(entry=>entry.body).filter(Boolean).join(`
|
|
3
3
|
`),combinedMessage={...last,body:combinedBody,mentionedJids:mentioned.size>0?Array.from(mentioned):void 0};await options.onMessage(combinedMessage)},onError:err=>{inboundLogger.error({error:String(err)},`failed handling inbound web message`),inboundConsoleLog.error(`Failed handling inbound web message: ${String(err)}`)}}),groupMetaCache=new Map,GROUP_META_TTL_MS=300*1e3,lidLookup=sock.signalRepository?.lidMapping,resolveInboundJid=async jid=>resolveJidToE164(jid,{authDir:options.authDir,lidLookup}),getGroupMeta=async jid=>{let cached=groupMetaCache.get(jid);if(cached&&cached.expires>Date.now())return cached;try{let meta=await sock.groupMetadata(jid),participants=(await Promise.all(meta.participants?.map(async p=>await resolveInboundJid(p.id)??p.id)??[])).filter(Boolean)??[],entry={subject:meta.subject,participants,expires:Date.now()+GROUP_META_TTL_MS};return groupMetaCache.set(jid,entry),entry}catch(err){return logVerbose(`Failed to fetch group metadata for ${jid}: ${String(err)}`),{expires:Date.now()+GROUP_META_TTL_MS}}},handleMessagesUpsert=async upsert=>{if(!(upsert.type!==`notify`&&upsert.type!==`append`))for(let msg of upsert.messages??[]){recordChannelActivity({channel:`whatsapp`,accountId:options.accountId,direction:`inbound`});let id=msg.key?.id??void 0,remoteJid=msg.key?.remoteJid;if(!remoteJid||remoteJid.endsWith(`@status`)||remoteJid.endsWith(`@broadcast`))continue;let group=isJidGroup(remoteJid)===!0;if(id&&isRecentInboundMessage(`${options.accountId}:${remoteJid}:${id}`))continue;let participantJid=msg.key?.participant??void 0,from=group?remoteJid:await resolveInboundJid(remoteJid);if(!from)continue;let senderE164=group?participantJid?await resolveInboundJid(participantJid):null:from,groupSubject,groupParticipants;if(group){let meta=await getGroupMeta(remoteJid);groupSubject=meta.subject,groupParticipants=meta.participants}let messageTimestampMs=msg.messageTimestamp?Number(msg.messageTimestamp)*1e3:void 0,access=await checkInboundAccessControl({accountId:options.accountId,from,selfE164,senderE164,group,pushName:msg.pushName??void 0,isFromMe:!!msg.key?.fromMe,messageTimestampMs,connectedAtMs,sock:{sendMessage:(jid,content)=>sock.sendMessage(jid,content)},remoteJid});if(!access.allowed)continue;if(id&&!access.isSelfChat&&options.sendReadReceipts!==!1){let participant=msg.key?.participant;try{await sock.readMessages([{remoteJid,id,participant,fromMe:!1}]),shouldLogVerbose()&&logVerbose(`Marked message ${id} as read for ${remoteJid}${participant?` (participant ${participant})`:``}`)}catch(err){logVerbose(`Failed to mark message ${id} read: ${String(err)}`)}}else id&&access.isSelfChat&&shouldLogVerbose()&&logVerbose(`Self-chat mode: skipping read receipt for ${id}`);if(upsert.type===`append`)continue;let location=extractLocationData(msg.message??void 0),locationText=location?formatLocationText(location):void 0,body=extractText(msg.message??void 0);if(locationText&&(body=[body,locationText].filter(Boolean).join(`
|
|
4
4
|
`).trim()),!body&&(body=extractMediaPlaceholder(msg.message??void 0),!body))continue;let replyContext=describeReplyContext(msg.message),mediaPath,mediaType,mediaFileName;try{let inboundMedia=await downloadInboundMedia(msg,sock);if(inboundMedia){let maxBytes=(typeof options.mediaMaxMb==`number`&&options.mediaMaxMb>0?options.mediaMaxMb:50)*1024*1024;mediaPath=(await saveMediaBuffer(inboundMedia.buffer,inboundMedia.mimetype,`inbound`,maxBytes,inboundMedia.fileName)).path,mediaType=inboundMedia.mimetype,mediaFileName=inboundMedia.fileName}}catch(err){logVerbose(`Inbound media download failed: ${String(err)}`)}let chatJid=remoteJid,sendComposing=async()=>{try{await sock.sendPresenceUpdate(`composing`,chatJid)}catch(err){logVerbose(`Presence update failed: ${String(err)}`)}},reply=async text=>{await sock.sendMessage(chatJid,{text})},sendMedia=async payload=>{await sock.sendMessage(chatJid,payload)},timestamp=messageTimestampMs,mentionedJids=extractMentionedJids(msg.message),senderName=msg.pushName??void 0;inboundLogger.info({from,to:selfE164??`me`,body,mediaPath,mediaType,mediaFileName,timestamp},`inbound message`);let inboundMessage={id,from,conversationId:from,to:selfE164??`me`,accountId:access.resolvedAccountId,body,pushName:senderName,timestamp,chatType:group?`group`:`direct`,chatId:remoteJid,senderJid:participantJid,senderE164:senderE164??void 0,senderName,replyToId:replyContext?.id,replyToBody:replyContext?.body,replyToSender:replyContext?.sender,replyToSenderJid:replyContext?.senderJid,replyToSenderE164:replyContext?.senderE164,groupSubject,groupParticipants,mentionedJids:mentionedJids??void 0,selfJid,selfE164,location:location??void 0,sendComposing,reply,sendMedia,mediaPath,mediaType,mediaFileName};try{Promise.resolve(debouncer.enqueue(inboundMessage)).catch(err=>{inboundLogger.error({error:String(err)},`failed handling inbound web message`),inboundConsoleLog.error(`Failed handling inbound web message: ${String(err)}`)})}catch(err){inboundLogger.error({error:String(err)},`failed handling inbound web message`),inboundConsoleLog.error(`Failed handling inbound web message: ${String(err)}`)}}};sock.ev.on(`messages.upsert`,handleMessagesUpsert);let handleConnectionUpdate=update=>{try{if(update.connection===`close`){let status=getStatusCode(update.lastDisconnect?.error);resolveClose({status,isLoggedOut:status===DisconnectReason.loggedOut,error:update.lastDisconnect?.error})}}catch(err){inboundLogger.error({error:String(err)},`connection.update handler error`),resolveClose({status:void 0,isLoggedOut:!1,error:err})}};return sock.ev.on(`connection.update`,handleConnectionUpdate),{close:async()=>{try{let ev=sock.ev,messagesUpsertHandler=handleMessagesUpsert,connectionUpdateHandler=handleConnectionUpdate;typeof ev.off==`function`?(ev.off(`messages.upsert`,messagesUpsertHandler),ev.off(`connection.update`,connectionUpdateHandler)):typeof ev.removeListener==`function`&&(ev.removeListener(`messages.upsert`,messagesUpsertHandler),ev.removeListener(`connection.update`,connectionUpdateHandler)),sock.ws?.close()}catch(err){logVerbose(`Socket close failed: ${String(err)}`)}},onClose,signalClose:reason=>{resolveClose(reason??{status:void 0,isLoggedOut:!1,error:`closed`})},...createWebSendApi({sock:{sendMessage:(jid,content)=>sock.sendMessage(jid,content),sendPresenceUpdate:(presence,jid)=>sock.sendPresenceUpdate(presence,jid)},defaultAccountId:options.accountId})}}function buildMentionConfig(cfg,agentId){return{mentionRegexes:buildMentionRegexes(cfg,agentId),allowFrom:cfg.channels?.whatsapp?.allowFrom}}function resolveMentionTargets(msg,authDir){let jidOptions=authDir?{authDir}:void 0;return{normalizedMentions:msg.mentionedJids?.length?msg.mentionedJids.map(jid=>jidToE164(jid,jidOptions)??jid).filter(Boolean):[],selfE164:msg.selfE164??(msg.selfJid?jidToE164(msg.selfJid,jidOptions):null),selfJid:msg.selfJid?msg.selfJid.replace(/:\\d+/,``):null}}function isBotMentionedFromTargets(msg,mentionCfg,targets){let clean=text=>normalizeMentionText(text),isSelfChat=isSelfChatMode(targets.selfE164,mentionCfg.allowFrom);if((msg.mentionedJids?.length??0)>0&&!isSelfChat)return!!(targets.selfE164&&targets.normalizedMentions.includes(targets.selfE164)||targets.selfJid&&targets.normalizedMentions.includes(targets.selfJid));let bodyClean=clean(msg.body);if(mentionCfg.mentionRegexes.some(re=>re.test(bodyClean)))return!0;if(targets.selfE164){let selfDigits=targets.selfE164.replace(/\D/g,``);if(selfDigits){if(bodyClean.replace(/[^\d]/g,``).includes(selfDigits))return!0;let bodyNoSpace=msg.body.replace(/[\s-]/g,``);if(RegExp(`\\+?${selfDigits}`,`i`).test(bodyNoSpace))return!0}}return!1}function debugMention(msg,mentionCfg,authDir){let mentionTargets=resolveMentionTargets(msg,authDir);return{wasMentioned:isBotMentionedFromTargets(msg,mentionCfg,mentionTargets),details:{from:msg.from,body:msg.body,bodyClean:normalizeMentionText(msg.body),mentionedJids:msg.mentionedJids??null,normalizedMentionedJids:mentionTargets.normalizedMentions.length?mentionTargets.normalizedMentions:null,selfJid:msg.selfJid??null,selfJidBare:mentionTargets.selfJid,selfE164:msg.selfE164??null,resolvedSelfE164:mentionTargets.selfE164}}}function resolveOwnerList(mentionCfg,selfE164){let allowFrom=mentionCfg.allowFrom;return(Array.isArray(allowFrom)&&allowFrom.length>0?allowFrom:selfE164?[selfE164]:[]).filter(entry=>!!(entry&&entry!==`*`)).map(entry=>normalizeE164(entry)).filter(entry=>!!entry)}function createEchoTracker(params){let recentlySent=new Set,maxItems=Math.max(1,params.maxItems??100),buildCombinedKey=p=>`combined:${p.sessionKey}:${p.combinedBody}`,trim=()=>{for(;recentlySent.size>maxItems;){let firstKey=recentlySent.values().next().value;if(!firstKey)break;recentlySent.delete(firstKey)}};return{rememberText:(text,opts)=>{text&&(recentlySent.add(text),opts.combinedBody&&opts.combinedBodySessionKey&&recentlySent.add(buildCombinedKey({sessionKey:opts.combinedBodySessionKey,combinedBody:opts.combinedBody})),opts.logVerboseMessage&¶ms.logVerbose?.(`Added to echo detection set (size now: ${recentlySent.size}): ${text.substring(0,50)}...`),trim())},has:key=>recentlySent.has(key),forget:key=>{recentlySent.delete(key)},buildCombinedKey}}async function maybeBroadcastMessage(params){let broadcastAgents=params.cfg.broadcast?.[params.peerId];if(!broadcastAgents||!Array.isArray(broadcastAgents)||broadcastAgents.length===0)return!1;let strategy=params.cfg.broadcast?.strategy||`parallel`;whatsappInboundLog.info(`Broadcasting message to ${broadcastAgents.length} agents (${strategy})`);let agentIds=params.cfg.agents?.list?.map(agent=>normalizeAgentId(agent.id)),hasKnownAgents=(agentIds?.length??0)>0,groupHistorySnapshot=params.msg.chatType===`group`?params.groupHistories.get(params.groupHistoryKey)??[]:void 0,processForAgent=async agentId=>{let normalizedAgentId=normalizeAgentId(agentId);if(hasKnownAgents&&!agentIds?.includes(normalizedAgentId))return whatsappInboundLog.warn(`Broadcast agent ${agentId} not found in agents.list; skipping`),!1;let agentRoute={...params.route,agentId:normalizedAgentId,sessionKey:buildAgentSessionKey({agentId:normalizedAgentId,channel:`whatsapp`,accountId:params.route.accountId,peer:{kind:params.msg.chatType===`group`?`group`:`direct`,id:params.peerId},dmScope:params.cfg.session?.dmScope,identityLinks:params.cfg.session?.identityLinks}),mainSessionKey:buildAgentMainSessionKey({agentId:normalizedAgentId,mainKey:DEFAULT_MAIN_KEY})};try{return await params.processMessage(params.msg,agentRoute,params.groupHistoryKey,{groupHistory:groupHistorySnapshot,suppressGroupHistoryClear:!0})}catch(err){return whatsappInboundLog.error(`Broadcast agent ${agentId} failed: ${formatError(err)}`),!1}};if(strategy===`sequential`)for(let agentId of broadcastAgents)await processForAgent(agentId);else await Promise.allSettled(broadcastAgents.map(processForAgent));return params.msg.chatType===`group`&¶ms.groupHistories.set(params.groupHistoryKey,[]),!0}function stripMentionsForCommand(text,mentionRegexes,selfE164){let result=text;for(let re of mentionRegexes)result=result.replace(re,` `);if(selfE164){let digits=selfE164.replace(/\D/g,``);if(digits){let pattern=RegExp(`\\+?${digits}`,`g`);result=result.replace(pattern,` `)}}return result.replace(/\s+/g,` `).trim()}function resolveGroupPolicyFor(cfg,conversationId){let groupId=resolveGroupSessionKey({From:conversationId,ChatType:`group`,Provider:`whatsapp`})?.id;return resolveChannelGroupPolicy({cfg,channel:`whatsapp`,groupId:groupId??conversationId})}function resolveGroupRequireMentionFor(cfg,conversationId){let groupId=resolveGroupSessionKey({From:conversationId,ChatType:`group`,Provider:`whatsapp`})?.id;return resolveChannelGroupRequireMention({cfg,channel:`whatsapp`,groupId:groupId??conversationId})}function resolveGroupActivationFor(params){let entry=loadSessionStore(resolveStorePath(params.cfg.session?.store,{agentId:params.agentId}))[params.sessionKey],defaultActivation=resolveGroupRequireMentionFor(params.cfg,params.conversationId)?`mention`:`always`;return normalizeGroupActivation(entry?.groupActivation)??defaultActivation}function noteGroupMember(groupMemberNames,conversationId,e164,name){if(!e164||!name)return;let key=normalizeE164(e164)??e164;if(!key)return;let roster=groupMemberNames.get(conversationId);roster||(roster=new Map,groupMemberNames.set(conversationId,roster)),roster.set(key,name)}function formatGroupMembers(params){let{participants,roster,fallbackE164}=params,seen=new Set,ordered=[];if(participants?.length)for(let entry of participants){if(!entry)continue;let normalized=normalizeE164(entry)??entry;!normalized||seen.has(normalized)||(seen.add(normalized),ordered.push(normalized))}if(roster)for(let entry of roster.keys()){let normalized=normalizeE164(entry)??entry;!normalized||seen.has(normalized)||(seen.add(normalized),ordered.push(normalized))}if(ordered.length===0&&fallbackE164){let normalized=normalizeE164(fallbackE164)??fallbackE164;normalized&&ordered.push(normalized)}if(ordered.length!==0)return ordered.map(entry=>{let name=roster?.get(entry);return name?`${name} (${entry})`:entry}).join(`, `)}function isOwnerSender(baseMentionConfig,msg){let sender=normalizeE164(msg.senderE164??``);return sender?resolveOwnerList(baseMentionConfig,msg.selfE164??void 0).includes(sender):!1}function recordPendingGroupHistoryEntry(params){let sender=params.msg.senderName&¶ms.msg.senderE164?`${params.msg.senderName} (${params.msg.senderE164})`:params.msg.senderName??params.msg.senderE164??`Unknown`;recordPendingHistoryEntryIfEnabled({historyMap:params.groupHistories,historyKey:params.groupHistoryKey,limit:params.groupHistoryLimit,entry:{sender,body:params.msg.body,timestamp:params.msg.timestamp,id:params.msg.id,senderJid:params.msg.senderJid}})}function applyGroupGating(params){let groupPolicy=resolveGroupPolicyFor(params.cfg,params.conversationId);if(groupPolicy.allowlistEnabled&&!groupPolicy.allowed)return params.logVerbose(`Skipping group message ${params.conversationId} (not in allowlist)`),{shouldProcess:!1};noteGroupMember(params.groupMemberNames,params.groupHistoryKey,params.msg.senderE164,params.msg.senderName);let mentionConfig=buildMentionConfig(params.cfg,params.agentId),commandBody=stripMentionsForCommand(params.msg.body,mentionConfig.mentionRegexes,params.msg.selfE164),activationCommand=parseActivationCommand(commandBody),owner=isOwnerSender(params.baseMentionConfig,params.msg),shouldBypassMention=owner&&hasControlCommand(commandBody,params.cfg);if(activationCommand.hasCommand&&!owner)return params.logVerbose(`Ignoring /activation from non-owner in group ${params.conversationId}`),recordPendingGroupHistoryEntry({msg:params.msg,groupHistories:params.groupHistories,groupHistoryKey:params.groupHistoryKey,groupHistoryLimit:params.groupHistoryLimit}),{shouldProcess:!1};let mentionDebug=debugMention(params.msg,mentionConfig,params.authDir);params.replyLogger.debug({conversationId:params.conversationId,wasMentioned:mentionDebug.wasMentioned,...mentionDebug.details},`group mention debug`);let wasMentioned=mentionDebug.wasMentioned,requireMention=resolveGroupActivationFor({cfg:params.cfg,agentId:params.agentId,sessionKey:params.sessionKey,conversationId:params.conversationId})!==`always`,selfJid=params.msg.selfJid?.replace(/:\\d+/,``),replySenderJid=params.msg.replyToSenderJid?.replace(/:\\d+/,``),selfE164=params.msg.selfE164?normalizeE164(params.msg.selfE164):null,replySenderE164=params.msg.replyToSenderE164?normalizeE164(params.msg.replyToSenderE164):null,mentionGate=resolveMentionGating({requireMention,canDetectMention:!0,wasMentioned,implicitMention:!!(selfJid&&replySenderJid&&selfJid===replySenderJid||selfE164&&replySenderE164&&selfE164===replySenderE164),shouldBypassMention});return params.msg.wasMentioned=mentionGate.effectiveWasMentioned,!shouldBypassMention&&requireMention&&mentionGate.shouldSkip?(params.logVerbose(`Group message stored for context (no mention detected) in ${params.conversationId}: ${params.msg.body}`),recordPendingGroupHistoryEntry({msg:params.msg,groupHistories:params.groupHistories,groupHistoryKey:params.groupHistoryKey,groupHistoryLimit:params.groupHistoryLimit}),{shouldProcess:!1}):{shouldProcess:!0}}function trackBackgroundTask(backgroundTasks,task){backgroundTasks.add(task),task.finally(()=>{backgroundTasks.delete(task)})}function updateLastRouteInBackground(params){let storePath=resolveStorePath(params.cfg.session?.store,{agentId:params.storeAgentId}),task=updateLastRoute({storePath,sessionKey:params.sessionKey,deliveryContext:{channel:params.channel,to:params.to,accountId:params.accountId},ctx:params.ctx}).catch(err=>{params.warn({error:formatError(err),storePath,sessionKey:params.sessionKey,to:params.to},`failed updating last route`)});trackBackgroundTask(params.backgroundTasks,task)}function resolvePeerId(msg){return msg.chatType===`group`?msg.conversationId??msg.from:msg.senderE164?normalizeE164(msg.senderE164)??msg.senderE164:msg.from.includes(`@`)?jidToE164(msg.from)??msg.from:normalizeE164(msg.from)??msg.from}async function deliverWebReply(params){let{replyResult,msg,maxMediaBytes,textLimit,replyLogger,connectionId,skipLog}=params,replyStarted=Date.now(),tableMode=params.tableMode??`code`,chunkMode=params.chunkMode??`length`,textChunks=chunkMarkdownTextWithMode(markdownToWhatsApp(convertMarkdownTables(replyResult.text||``,tableMode)),textLimit,chunkMode),mediaList=replyResult.mediaUrls?.length?replyResult.mediaUrls:replyResult.mediaUrl?[replyResult.mediaUrl]:[],sendWithRetry=async(fn,label,maxAttempts=3)=>{let lastErr;for(let attempt=1;attempt<=maxAttempts;attempt++)try{return await fn()}catch(err){lastErr=err;let errText=formatError(err),isLast=attempt===maxAttempts;if(!/closed|reset|timed\\s*out|disconnect/i.test(errText)||isLast)throw err;let backoffMs=500*attempt;logVerbose(`Retrying ${label} to ${msg.from} after failure (${attempt}/${maxAttempts-1}) in ${backoffMs}ms: ${errText}`),await sleep(backoffMs)}throw lastErr};if(mediaList.length===0&&textChunks.length){let totalChunks=textChunks.length;for(let[index,chunk]of textChunks.entries()){let chunkStarted=Date.now();if(await sendWithRetry(()=>msg.reply(chunk),`text`),!skipLog){let durationMs=Date.now()-chunkStarted;whatsappOutboundLog.debug(`Sent chunk ${index+1}/${totalChunks} to ${msg.from} (${durationMs.toFixed(0)}ms)`)}}replyLogger.info({correlationId:msg.id??newConnectionId(),connectionId:connectionId??null,to:msg.from,from:msg.to,text:elide(replyResult.text,240),mediaUrl:null,mediaSizeBytes:null,mediaKind:null,durationMs:Date.now()-replyStarted},`auto-reply sent (text)`);return}let remainingText=[...textChunks];for(let[index,mediaUrl]of mediaList.entries()){let caption=index===0&&remainingText.shift()||void 0;try{let media=await loadWebMedia(mediaUrl,{maxBytes:maxMediaBytes,localRoots:params.mediaLocalRoots});if(shouldLogVerbose()&&(logVerbose(`Web auto-reply media size: ${(media.buffer.length/(1024*1024)).toFixed(2)}MB`),logVerbose(`Web auto-reply media source: ${mediaUrl} (kind ${media.kind})`)),media.kind===`image`)await sendWithRetry(()=>msg.sendMedia({image:media.buffer,caption,mimetype:media.contentType}),`media:image`);else if(media.kind===`audio`)await sendWithRetry(()=>msg.sendMedia({audio:media.buffer,ptt:!0,mimetype:media.contentType,caption}),`media:audio`);else if(media.kind===`video`)await sendWithRetry(()=>msg.sendMedia({video:media.buffer,caption,mimetype:media.contentType}),`media:video`);else{let fileName=media.fileName??mediaUrl.split(`/`).pop()??`file`,mimetype=media.contentType??`application/octet-stream`;await sendWithRetry(()=>msg.sendMedia({document:media.buffer,fileName,caption,mimetype}),`media:document`)}whatsappOutboundLog.info(`Sent media reply to ${msg.from} (${(media.buffer.length/(1024*1024)).toFixed(2)}MB)`),replyLogger.info({correlationId:msg.id??newConnectionId(),connectionId:connectionId??null,to:msg.from,from:msg.to,text:caption??null,mediaUrl,mediaSizeBytes:media.buffer.length,mediaKind:media.kind,durationMs:Date.now()-replyStarted},`auto-reply sent (media)`)}catch(err){if(whatsappOutboundLog.error(`Failed sending web media to ${msg.from}: ${formatError(err)}`),replyLogger.warn({err,mediaUrl},`failed to send web media reply`),index===0){let warning=err instanceof Error?`⚠️ Media failed: ${err.message}`:`⚠️ Media failed.`,fallbackText=[remainingText.shift()??caption??``,warning].filter(Boolean).join(`
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{g as CONFIG_DIR}from"./registry-
|
|
1
|
+
import{g as CONFIG_DIR}from"./registry-CZHRcH-q.js";import{n as loadConfig}from"./config--Ci8Y91R.js";import{t as createSubsystemLogger}from"./subsystem-D0Ril4rt.js";import{i as isErrno}from"./errors-L3rugjUL.js";import path from"node:path";import fs from"node:fs";import os from"node:os";import{createHash,randomBytes}from"node:crypto";import"node:fs/promises";import{execFileSync,spawn}from"node:child_process";import{Buffer as Buffer$1}from"node:buffer";import{createServer}from"node:http";import WebSocket,{WebSocketServer}from"ws";import net from"node:net";function rawDataToString(data,encoding=`utf8`){return typeof data==`string`?data:Buffer$1.isBuffer(data)?data.toString(encoding):Array.isArray(data)?Buffer$1.concat(data).toString(encoding):data instanceof ArrayBuffer?Buffer$1.from(data).toString(encoding):Buffer$1.from(String(data)).toString(encoding)}const POSIX_BUILDERFORCE_AGENTS_TMP_DIR=`/tmp/builderforce`;function isNodeErrorWithCode(err,code){return typeof err==`object`&&!!err&&`code`in err&&err.code===code}function resolvePreferredBuilderForceAgentsTmpDir(options={}){let accessSync=options.accessSync??fs.accessSync,lstatSync=options.lstatSync??fs.lstatSync,mkdirSync=options.mkdirSync??fs.mkdirSync,getuid=options.getuid??(()=>{try{return typeof process.getuid==`function`?process.getuid():void 0}catch{return}}),tmpdir=options.tmpdir??os.tmpdir,uid=getuid(),isSecureDirForUser=st=>uid===void 0?!0:!(typeof st.uid==`number`&&st.uid!==uid||typeof st.mode==`number`&&st.mode&18),fallback=()=>{let base=tmpdir(),suffix=uid===void 0?`builderforce`:`builderforce-${uid}`;return path.join(base,suffix)};try{let preferred=lstatSync(POSIX_BUILDERFORCE_AGENTS_TMP_DIR);return!preferred.isDirectory()||preferred.isSymbolicLink()||(accessSync(POSIX_BUILDERFORCE_AGENTS_TMP_DIR,fs.constants.W_OK|fs.constants.X_OK),!isSecureDirForUser(preferred))?fallback():POSIX_BUILDERFORCE_AGENTS_TMP_DIR}catch(err){if(!isNodeErrorWithCode(err,`ENOENT`))return fallback()}try{accessSync(`/tmp`,fs.constants.W_OK|fs.constants.X_OK),mkdirSync(POSIX_BUILDERFORCE_AGENTS_TMP_DIR,{recursive:!0,mode:448});try{let preferred=lstatSync(POSIX_BUILDERFORCE_AGENTS_TMP_DIR);if(!preferred.isDirectory()||preferred.isSymbolicLink()||!isSecureDirForUser(preferred))return fallback()}catch{return fallback()}return POSIX_BUILDERFORCE_AGENTS_TMP_DIR}catch{return fallback()}}function isTailnetIPv4(address){let parts=address.split(`.`);if(parts.length!==4)return!1;let octets=parts.map(p=>Number.parseInt(p,10));if(octets.some(n=>!Number.isFinite(n)||n<0||n>255))return!1;let[a,b]=octets;return a===100&&b>=64&&b<=127}function isTailnetIPv6(address){return address.trim().toLowerCase().startsWith(`fd7a:115c:a1e0:`)}function listTailnetAddresses(){let ipv4=[],ipv6=[],ifaces=os.networkInterfaces();for(let entries of Object.values(ifaces))if(entries)for(let e of entries){if(!e||e.internal)continue;let address=e.address?.trim();address&&(isTailnetIPv4(address)&&ipv4.push(address),isTailnetIPv6(address)&&ipv6.push(address))}return{ipv4:[...new Set(ipv4)],ipv6:[...new Set(ipv6)]}}function pickPrimaryTailnetIPv4(){return listTailnetAddresses().ipv4[0]}function pickPrimaryLanIPv4(){let nets=os.networkInterfaces();for(let name of[`en0`,`eth0`]){let entry=nets[name]?.find(n=>n.family===`IPv4`&&!n.internal);if(entry?.address)return entry.address}for(let list of Object.values(nets)){let entry=list?.find(n=>n.family===`IPv4`&&!n.internal);if(entry?.address)return entry.address}}function isLoopbackAddress(ip){return ip?!!(ip===`127.0.0.1`||ip.startsWith(`127.`)||ip===`::1`||ip.startsWith(`::ffff:127.`)):!1}function isLoopbackHost(host){if(!host)return!1;let h=host.trim().toLowerCase();return h===`localhost`?!0:isLoopbackAddress(h.startsWith(`[`)&&h.endsWith(`]`)?h.slice(1,-1):h)}const DEFAULT_BUILDERFORCE_AGENTS_BROWSER_ENABLED=!0,DEFAULT_BROWSER_EVALUATE_ENABLED=!0,DEFAULT_BUILDERFORCE_AGENTS_BROWSER_COLOR=`#FF4500`,DEFAULT_BUILDERFORCE_AGENTS_BROWSER_PROFILE_NAME=`builderforce`,DEFAULT_BROWSER_DEFAULT_PROFILE_NAME=`chrome`,DEFAULT_AI_SNAPSHOT_MAX_CHARS=8e4,DEFAULT_AI_SNAPSHOT_EFFICIENT_MAX_CHARS=1e4,DEFAULT_AI_SNAPSHOT_EFFICIENT_DEPTH=6,RELAY_AUTH_HEADER=`x-builderforce-relay-token`;function headerValue(value){if(value)return Array.isArray(value)?value[0]:value}function getHeader(req,name){return headerValue(req.headers[name.toLowerCase()])}function parseBaseUrl(raw){let parsed=new URL(raw.trim().replace(/\/$/,``));if(parsed.protocol!==`http:`&&parsed.protocol!==`https:`)throw Error(`extension relay cdpUrl must be http(s), got ${parsed.protocol}`);let host=parsed.hostname,port=parsed.port?.trim()===``?parsed.protocol===`https:`?443:80:Number(parsed.port);if(!Number.isFinite(port)||port<=0||port>65535)throw Error(`extension relay cdpUrl has invalid port: ${parsed.port||`(empty)`}`);return{host,port,baseUrl:parsed.toString().replace(/\/$/,``)}}function text(res,status,bodyText){let body=Buffer.from(bodyText);res.write(`HTTP/1.1 ${status} ${status===200?`OK`:`ERR`}\r\nContent-Type: text/plain; charset=utf-8\r
|
|
2
2
|
Content-Length: ${body.length}\r\nConnection: close\r
|
|
3
3
|
\r
|
|
4
4
|
`),res.write(body),res.end()}function rejectUpgrade(socket,status,bodyText){text(socket,status,bodyText);try{socket.destroy()}catch{}}const serversByPort=new Map,relayAuthByPort=new Map;function resolveGatewayAuthToken(){let envToken=process.env.BUILDERFORCE_AGENTS_GATEWAY_TOKEN?.trim()||process.env.BUILDERFORCE_AGENTS_GATEWAY_TOKEN?.trim();if(envToken)return envToken;try{let configToken=loadConfig().gateway?.auth?.token?.trim();if(configToken)return configToken}catch{}return null}function deriveDeterministicRelayAuthToken(port){let gatewayToken=resolveGatewayAuthToken();return gatewayToken?createHash(`sha256`).update(`builderforce-relay:${port}:`).update(gatewayToken).digest(`base64url`):null}function resolveRelayAuthToken(port){return deriveDeterministicRelayAuthToken(port)??randomBytes(32).toString(`base64url`)}function isAddrInUseError(err){return typeof err==`object`&&!!err&&`code`in err&&err.code===`EADDRINUSE`}async function looksLikeBuilderForceAgentsRelay(baseUrl){let ctrl=new AbortController,timer=setTimeout(()=>ctrl.abort(),500);try{let statusUrl=new URL(`/extension/status`,`${baseUrl}/`).toString(),res=await fetch(statusUrl,{signal:ctrl.signal});return res.ok?typeof(await res.json()).connected==`boolean`:!1}catch{return!1}finally{clearTimeout(timer)}}function relayAuthTokenForUrl(url){try{let parsed=new URL(url);if(!isLoopbackHost(parsed.hostname))return null;let port=parsed.port?.trim()===``?parsed.protocol===`https:`||parsed.protocol===`wss:`?443:80:Number(parsed.port);return Number.isFinite(port)?relayAuthByPort.get(port)??deriveDeterministicRelayAuthToken(port):null}catch{return null}}function getChromeExtensionRelayAuthHeaders(url){let token=relayAuthTokenForUrl(url);return token?{[RELAY_AUTH_HEADER]:token}:{}}async function ensureChromeExtensionRelayServer(opts){let info=parseBaseUrl(opts.cdpUrl);if(!isLoopbackHost(info.host))throw Error(`extension relay requires loopback cdpUrl host (got ${info.host})`);let existing=serversByPort.get(info.port);if(existing)return existing;let relayAuthToken=resolveRelayAuthToken(info.port),extensionWs=null,cdpClients=new Set,connectedTargets=new Map,pendingExtension=new Map,nextExtensionId=1,sendToExtension=async payload=>{let ws=extensionWs;if(!ws||ws.readyState!==WebSocket.OPEN)throw Error(`Chrome extension not connected`);return ws.send(JSON.stringify(payload)),await new Promise((resolve,reject)=>{let timer=setTimeout(()=>{pendingExtension.delete(payload.id),reject(Error(`extension request timeout: ${payload.params.method}`))},3e4);pendingExtension.set(payload.id,{resolve,reject,timer})})},broadcastToCdpClients=evt=>{let msg=JSON.stringify(evt);for(let ws of cdpClients)ws.readyState===WebSocket.OPEN&&ws.send(msg)},sendResponseToCdp=(ws,res)=>{ws.readyState===WebSocket.OPEN&&ws.send(JSON.stringify(res))},ensureTargetEventsForClient=(ws,mode)=>{for(let target of connectedTargets.values())mode===`autoAttach`?ws.send(JSON.stringify({method:`Target.attachedToTarget`,params:{sessionId:target.sessionId,targetInfo:{...target.targetInfo,attached:!0},waitingForDebugger:!1}})):ws.send(JSON.stringify({method:`Target.targetCreated`,params:{targetInfo:{...target.targetInfo,attached:!0}}}))},routeCdpCommand=async cmd=>{switch(cmd.method){case`Browser.getVersion`:return{protocolVersion:`1.3`,product:`Chrome/BuilderForceAgents-Extension-Relay`,revision:`0`,userAgent:`BuilderForceAgents-Extension-Relay`,jsVersion:`V8`};case`Browser.setDownloadBehavior`:return{};case`Target.setAutoAttach`:case`Target.setDiscoverTargets`:return{};case`Target.getTargets`:return{targetInfos:Array.from(connectedTargets.values()).map(t=>({...t.targetInfo,attached:!0}))};case`Target.getTargetInfo`:{let params=cmd.params??{},targetId=typeof params.targetId==`string`?params.targetId:void 0;if(targetId){for(let t of connectedTargets.values())if(t.targetId===targetId)return{targetInfo:t.targetInfo}}if(cmd.sessionId&&connectedTargets.has(cmd.sessionId)){let t=connectedTargets.get(cmd.sessionId);if(t)return{targetInfo:t.targetInfo}}return{targetInfo:Array.from(connectedTargets.values())[0]?.targetInfo}}case`Target.attachToTarget`:{let params=cmd.params??{},targetId=typeof params.targetId==`string`?params.targetId:void 0;if(!targetId)throw Error(`targetId required`);for(let t of connectedTargets.values())if(t.targetId===targetId)return{sessionId:t.sessionId};throw Error(`target not found`)}default:return await sendToExtension({id:nextExtensionId++,method:`forwardCDPCommand`,params:{method:cmd.method,sessionId:cmd.sessionId,params:cmd.params}})}},server=createServer((req,res)=>{let path=new URL(req.url??`/`,info.baseUrl).pathname;if(path.startsWith(`/json`)){let token=getHeader(req,RELAY_AUTH_HEADER);if(!token||token!==relayAuthToken){res.writeHead(401),res.end(`Unauthorized`);return}}if(req.method===`HEAD`&&path===`/`){res.writeHead(200),res.end();return}if(path===`/`){res.writeHead(200,{"Content-Type":`text/plain; charset=utf-8`}),res.end(`OK`);return}if(path===`/extension/status`){res.writeHead(200,{"Content-Type":`application/json`}),res.end(JSON.stringify({connected:!!extensionWs}));return}let cdpWsUrl=`${`ws://${req.headers.host?.trim()||`${info.host}:${info.port}`}`}/cdp`;if((path===`/json/version`||path===`/json/version/`)&&(req.method===`GET`||req.method===`PUT`)){let payload={Browser:`BuilderForceAgents/extension-relay`,"Protocol-Version":`1.3`};extensionWs&&(payload.webSocketDebuggerUrl=cdpWsUrl),res.writeHead(200,{"Content-Type":`application/json`}),res.end(JSON.stringify(payload));return}if(new Set([`/json`,`/json/`,`/json/list`,`/json/list/`]).has(path)&&(req.method===`GET`||req.method===`PUT`)){let list=Array.from(connectedTargets.values()).map(t=>({id:t.targetId,type:t.targetInfo.type??`page`,title:t.targetInfo.title??``,description:t.targetInfo.title??``,url:t.targetInfo.url??``,webSocketDebuggerUrl:cdpWsUrl,devtoolsFrontendUrl:`/devtools/inspector.html?ws=${cdpWsUrl.replace(`ws://`,``)}`}));res.writeHead(200,{"Content-Type":`application/json`}),res.end(JSON.stringify(list));return}let activateMatch=path.match(/^\/json\/activate\/(.+)$/);if(activateMatch&&(req.method===`GET`||req.method===`PUT`)){let targetId=decodeURIComponent(activateMatch[1]??``).trim();if(!targetId){res.writeHead(400),res.end(`targetId required`);return}(async()=>{try{await sendToExtension({id:nextExtensionId++,method:`forwardCDPCommand`,params:{method:`Target.activateTarget`,params:{targetId}}})}catch{}})(),res.writeHead(200),res.end(`OK`);return}let closeMatch=path.match(/^\/json\/close\/(.+)$/);if(closeMatch&&(req.method===`GET`||req.method===`PUT`)){let targetId=decodeURIComponent(closeMatch[1]??``).trim();if(!targetId){res.writeHead(400),res.end(`targetId required`);return}(async()=>{try{await sendToExtension({id:nextExtensionId++,method:`forwardCDPCommand`,params:{method:`Target.closeTarget`,params:{targetId}}})}catch{}})(),res.writeHead(200),res.end(`OK`);return}res.writeHead(404),res.end(`not found`)}),wssExtension=new WebSocketServer({noServer:!0}),wssCdp=new WebSocketServer({noServer:!0});server.on(`upgrade`,(req,socket,head)=>{let pathname=new URL(req.url??`/`,info.baseUrl).pathname,remote=req.socket.remoteAddress;if(!isLoopbackAddress(remote)){rejectUpgrade(socket,403,`Forbidden`);return}let origin=headerValue(req.headers.origin);if(origin&&!origin.startsWith(`chrome-extension://`)){rejectUpgrade(socket,403,`Forbidden: invalid origin`);return}if(pathname===`/extension`){if(extensionWs){rejectUpgrade(socket,409,`Extension already connected`);return}wssExtension.handleUpgrade(req,socket,head,ws=>{wssExtension.emit(`connection`,ws,req)});return}if(pathname===`/cdp`){let token=getHeader(req,RELAY_AUTH_HEADER);if(!token||token!==relayAuthToken){rejectUpgrade(socket,401,`Unauthorized`);return}if(!extensionWs){rejectUpgrade(socket,503,`Extension not connected`);return}wssCdp.handleUpgrade(req,socket,head,ws=>{wssCdp.emit(`connection`,ws,req)});return}rejectUpgrade(socket,404,`Not Found`)}),wssExtension.on(`connection`,ws=>{extensionWs=ws;let ping=setInterval(()=>{ws.readyState===WebSocket.OPEN&&ws.send(JSON.stringify({method:`ping`}))},5e3);ws.on(`message`,data=>{let parsed=null;try{parsed=JSON.parse(rawDataToString(data))}catch{return}if(parsed&&typeof parsed==`object`&&`id`in parsed&&typeof parsed.id==`number`){let pending=pendingExtension.get(parsed.id);if(!pending)return;pendingExtension.delete(parsed.id),clearTimeout(pending.timer),`error`in parsed&&typeof parsed.error==`string`&&parsed.error.trim()?pending.reject(Error(parsed.error)):pending.resolve(parsed.result);return}if(parsed&&typeof parsed==`object`&&`method`in parsed){if(parsed.method===`pong`||parsed.method!==`forwardCDPEvent`)return;let evt=parsed,method=evt.params?.method,params=evt.params?.params,sessionId=evt.params?.sessionId;if(!method||typeof method!=`string`)return;if(method===`Target.attachedToTarget`){let attached=params??{};if((attached?.targetInfo?.type??`page`)!==`page`)return;if(attached?.sessionId&&attached?.targetInfo?.targetId){let prev=connectedTargets.get(attached.sessionId),nextTargetId=attached.targetInfo.targetId,prevTargetId=prev?.targetId,changedTarget=!!(prev&&prevTargetId&&prevTargetId!==nextTargetId);connectedTargets.set(attached.sessionId,{sessionId:attached.sessionId,targetId:nextTargetId,targetInfo:attached.targetInfo}),changedTarget&&prevTargetId&&broadcastToCdpClients({method:`Target.detachedFromTarget`,params:{sessionId:attached.sessionId,targetId:prevTargetId},sessionId:attached.sessionId}),(!prev||changedTarget)&&broadcastToCdpClients({method,params,sessionId});return}}if(method===`Target.detachedFromTarget`){let detached=params??{};detached?.sessionId&&connectedTargets.delete(detached.sessionId),broadcastToCdpClients({method,params,sessionId});return}if(method===`Target.targetInfoChanged`){let targetInfo=(params??{})?.targetInfo,targetId=targetInfo?.targetId;if(targetId&&(targetInfo?.type??`page`)===`page`)for(let[sid,target]of connectedTargets)target.targetId===targetId&&connectedTargets.set(sid,{...target,targetInfo:{...target.targetInfo,...targetInfo}})}broadcastToCdpClients({method,params,sessionId})}}),ws.on(`close`,()=>{clearInterval(ping),extensionWs=null;for(let[,pending]of pendingExtension)clearTimeout(pending.timer),pending.reject(Error(`extension disconnected`));pendingExtension.clear(),connectedTargets.clear();for(let client of cdpClients)try{client.close(1011,`extension disconnected`)}catch{}cdpClients.clear()})}),wssCdp.on(`connection`,ws=>{cdpClients.add(ws),ws.on(`message`,async data=>{let cmd=null;try{cmd=JSON.parse(rawDataToString(data))}catch{return}if(!(!cmd||typeof cmd!=`object`)&&!(typeof cmd.id!=`number`||typeof cmd.method!=`string`)){if(!extensionWs){sendResponseToCdp(ws,{id:cmd.id,sessionId:cmd.sessionId,error:{message:`Extension not connected`}});return}try{let result=await routeCdpCommand(cmd);if(cmd.method===`Target.setAutoAttach`&&!cmd.sessionId&&ensureTargetEventsForClient(ws,`autoAttach`),cmd.method===`Target.setDiscoverTargets`&&(cmd.params??{}).discover===!0&&ensureTargetEventsForClient(ws,`discover`),cmd.method===`Target.attachToTarget`){let params=cmd.params??{},targetId=typeof params.targetId==`string`?params.targetId:void 0;if(targetId){let target=Array.from(connectedTargets.values()).find(t=>t.targetId===targetId);target&&ws.send(JSON.stringify({method:`Target.attachedToTarget`,params:{sessionId:target.sessionId,targetInfo:{...target.targetInfo,attached:!0},waitingForDebugger:!1}}))}}sendResponseToCdp(ws,{id:cmd.id,sessionId:cmd.sessionId,result})}catch(err){sendResponseToCdp(ws,{id:cmd.id,sessionId:cmd.sessionId,error:{message:err instanceof Error?err.message:String(err)}})}}}),ws.on(`close`,()=>{cdpClients.delete(ws)})});try{await new Promise((resolve,reject)=>{server.listen(info.port,info.host,()=>resolve()),server.once(`error`,reject)})}catch(err){if(isAddrInUseError(err)&&await looksLikeBuilderForceAgentsRelay(info.baseUrl)){let existingRelay={host:info.host,port:info.port,baseUrl:info.baseUrl,cdpWsUrl:`ws://${info.host}:${info.port}/cdp`,extensionConnected:()=>!1,stop:async()=>{serversByPort.delete(info.port),relayAuthByPort.delete(info.port)}};return relayAuthByPort.set(info.port,relayAuthToken),serversByPort.set(info.port,existingRelay),existingRelay}throw err}let port=server.address()?.port??info.port,host=info.host,relay={host,port,baseUrl:`${new URL(info.baseUrl).protocol}//${host}:${port}`,cdpWsUrl:`ws://${host}:${port}/cdp`,extensionConnected:()=>!!extensionWs,stop:async()=>{serversByPort.delete(port),relayAuthByPort.delete(port);try{extensionWs?.close(1001,`server stopping`)}catch{}for(let ws of cdpClients)try{ws.close(1001,`server stopping`)}catch{}await new Promise(resolve=>{server.close(()=>resolve())}),wssExtension.close(),wssCdp.close()}};return relayAuthByPort.set(port,relayAuthToken),serversByPort.set(port,relay),relay}async function stopChromeExtensionRelayServer(opts){let info=parseBaseUrl(opts.cdpUrl),existing=serversByPort.get(info.port);return existing?(await existing.stop(),relayAuthByPort.delete(info.port),!0):!1}function getHeadersWithAuth(url,headers={}){let mergedHeaders={...getChromeExtensionRelayAuthHeaders(url),...headers};try{let parsed=new URL(url);if(Object.keys(mergedHeaders).some(key=>key.toLowerCase()===`authorization`))return mergedHeaders;if(parsed.username||parsed.password){let auth=Buffer.from(`${parsed.username}:${parsed.password}`).toString(`base64`);return{...mergedHeaders,Authorization:`Basic ${auth}`}}}catch{}return mergedHeaders}function appendCdpPath(cdpUrl,path){let url=new URL(cdpUrl);return url.pathname=`${url.pathname.replace(/\/$/,``)}${path.startsWith(`/`)?path:`/${path}`}`,url.toString()}function createCdpSender(ws){let nextId=1,pending=new Map,send=(method,params,sessionId)=>{let id=nextId++,msg={id,method,params,sessionId};return ws.send(JSON.stringify(msg)),new Promise((resolve,reject)=>{pending.set(id,{resolve,reject})})},closeWithError=err=>{for(let[,p]of pending)p.reject(err);pending.clear();try{ws.close()}catch{}};return ws.on(`error`,err=>{closeWithError(err instanceof Error?err:Error(String(err)))}),ws.on(`message`,data=>{try{let parsed=JSON.parse(rawDataToString(data));if(typeof parsed.id!=`number`)return;let p=pending.get(parsed.id);if(!p)return;if(pending.delete(parsed.id),parsed.error?.message){p.reject(Error(parsed.error.message));return}p.resolve(parsed.result)}catch{}}),ws.on(`close`,()=>{closeWithError(Error(`CDP socket closed`))}),{send,closeWithError}}async function fetchJson(url,timeoutMs=1500,init){return await(await fetchChecked(url,timeoutMs,init)).json()}async function fetchChecked(url,timeoutMs=1500,init){let ctrl=new AbortController,t=setTimeout(ctrl.abort.bind(ctrl),timeoutMs);try{let headers=getHeadersWithAuth(url,init?.headers||{}),res=await fetch(url,{...init,headers,signal:ctrl.signal});if(!res.ok)throw Error(`HTTP ${res.status}`);return res}finally{clearTimeout(t)}}async function fetchOk(url,timeoutMs=1500,init){await fetchChecked(url,timeoutMs,init)}async function withCdpSocket(wsUrl,fn,opts){let headers=getHeadersWithAuth(wsUrl,opts?.headers??{}),ws=new WebSocket(wsUrl,{handshakeTimeout:typeof opts?.handshakeTimeoutMs==`number`&&Number.isFinite(opts.handshakeTimeoutMs)?Math.max(1,Math.floor(opts.handshakeTimeoutMs)):5e3,...Object.keys(headers).length?{headers}:{}}),{send,closeWithError}=createCdpSender(ws),openPromise=new Promise((resolve,reject)=>{ws.once(`open`,()=>resolve()),ws.once(`error`,err=>reject(err)),ws.once(`close`,()=>reject(Error(`CDP socket closed`)))});try{await openPromise}catch(err){throw closeWithError(err instanceof Error?err:Error(String(err))),err}try{return await fn(send)}catch(err){throw closeWithError(err instanceof Error?err:Error(String(err))),err}finally{try{ws.close()}catch{}}}function normalizeCdpWsUrl(wsUrl,cdpUrl){let ws=new URL(wsUrl),cdp=new URL(cdpUrl);if(isLoopbackHost(ws.hostname)&&!isLoopbackHost(cdp.hostname)){ws.hostname=cdp.hostname;let cdpPort=cdp.port||(cdp.protocol===`https:`?`443`:`80`);cdpPort&&(ws.port=cdpPort),ws.protocol=cdp.protocol===`https:`?`wss:`:`ws:`}cdp.protocol===`https:`&&ws.protocol===`ws:`&&(ws.protocol=`wss:`),!ws.username&&!ws.password&&(cdp.username||cdp.password)&&(ws.username=cdp.username,ws.password=cdp.password);for(let[key,value]of cdp.searchParams.entries())ws.searchParams.has(key)||ws.searchParams.append(key,value);return ws.toString()}async function captureScreenshot(opts){return await withCdpSocket(opts.wsUrl,async send=>{await send(`Page.enable`);let clip;if(opts.fullPage){let metrics=await send(`Page.getLayoutMetrics`),size=metrics?.cssContentSize??metrics?.contentSize,width=Number(size?.width??0),height=Number(size?.height??0);width>0&&height>0&&(clip={x:0,y:0,width,height,scale:1})}let format=opts.format??`png`,quality=format===`jpeg`?Math.max(0,Math.min(100,Math.round(opts.quality??85))):void 0,base64=(await send(`Page.captureScreenshot`,{format,...quality===void 0?{}:{quality},fromSurface:!0,captureBeyondViewport:!0,...clip?{clip}:{}}))?.data;if(!base64)throw Error(`Screenshot failed: missing data`);return Buffer.from(base64,`base64`)})}async function createTargetViaCdp(opts){let version=await fetchJson(appendCdpPath(opts.cdpUrl,`/json/version`),1500),wsUrlRaw=String(version?.webSocketDebuggerUrl??``).trim(),wsUrl=wsUrlRaw?normalizeCdpWsUrl(wsUrlRaw,opts.cdpUrl):``;if(!wsUrl)throw Error(`CDP /json/version missing webSocketDebuggerUrl`);return await withCdpSocket(wsUrl,async send=>{let created=await send(`Target.createTarget`,{url:opts.url}),targetId=String(created?.targetId??``).trim();if(!targetId)throw Error(`CDP Target.createTarget returned no targetId`);return{targetId}})}function axValue(v){if(!v||typeof v!=`object`)return``;let value=v.value;return typeof value==`string`?value:typeof value==`number`||typeof value==`boolean`?String(value):``}function formatAriaSnapshot(nodes,limit){let byId=new Map;for(let n of nodes)n.nodeId&&byId.set(n.nodeId,n);let referenced=new Set;for(let n of nodes)for(let c of n.childIds??[])referenced.add(c);let root=nodes.find(n=>n.nodeId&&!referenced.has(n.nodeId))??nodes[0];if(!root?.nodeId)return[];let out=[],stack=[{id:root.nodeId,depth:0}];for(;stack.length&&out.length<limit;){let popped=stack.pop();if(!popped)break;let{id,depth}=popped,n=byId.get(id);if(!n)continue;let role=axValue(n.role),name=axValue(n.name),value=axValue(n.value),description=axValue(n.description),ref=`ax${out.length+1}`;out.push({ref,role:role||`unknown`,name:name||``,...value?{value}:{},...description?{description}:{},...typeof n.backendDOMNodeId==`number`?{backendDOMNodeId:n.backendDOMNodeId}:{},depth});let children=(n.childIds??[]).filter(c=>byId.has(c));for(let i=children.length-1;i>=0;i--){let child=children[i];child&&stack.push({id:child,depth:depth+1})}}return out}async function snapshotAria(opts){let limit=Math.max(1,Math.min(2e3,Math.floor(opts.limit??500)));return await withCdpSocket(opts.wsUrl,async send=>{await send(`Accessibility.enable`).catch(()=>{});let res=await send(`Accessibility.getFullAXTree`);return{nodes:formatAriaSnapshot(Array.isArray(res?.nodes)?res.nodes:[],limit)}})}const CHROMIUM_BUNDLE_IDS=new Set([`com.google.Chrome`,`com.google.Chrome.beta`,`com.google.Chrome.canary`,`com.google.Chrome.dev`,`com.brave.Browser`,`com.brave.Browser.beta`,`com.brave.Browser.nightly`,`com.microsoft.Edge`,`com.microsoft.EdgeBeta`,`com.microsoft.EdgeDev`,`com.microsoft.EdgeCanary`,`org.chromium.Chromium`,`com.vivaldi.Vivaldi`,`com.operasoftware.Opera`,`com.operasoftware.OperaGX`,`com.yandex.desktop.yandex-browser`,`company.thebrowser.Browser`]),CHROMIUM_DESKTOP_IDS=new Set([`google-chrome.desktop`,`google-chrome-beta.desktop`,`google-chrome-unstable.desktop`,`brave-browser.desktop`,`microsoft-edge.desktop`,`microsoft-edge-beta.desktop`,`microsoft-edge-dev.desktop`,`microsoft-edge-canary.desktop`,`chromium.desktop`,`chromium-browser.desktop`,`vivaldi.desktop`,`vivaldi-stable.desktop`,`opera.desktop`,`opera-gx.desktop`,`yandex-browser.desktop`,`org.chromium.Chromium.desktop`]),CHROMIUM_EXE_NAMES=new Set(`chrome.exe,msedge.exe,brave.exe,brave-browser.exe,chromium.exe,vivaldi.exe,opera.exe,launcher.exe,yandex.exe,yandexbrowser.exe,google chrome,google chrome canary,brave browser,microsoft edge,chromium,chrome,brave,msedge,brave-browser,google-chrome,google-chrome-stable,google-chrome-beta,google-chrome-unstable,microsoft-edge,microsoft-edge-beta,microsoft-edge-dev,microsoft-edge-canary,chromium-browser,vivaldi,vivaldi-stable,opera,opera-stable,opera-gx,yandex-browser`.split(`,`));function exists$1(filePath){try{return fs.existsSync(filePath)}catch{return!1}}function execText(command,args,timeoutMs=1200,maxBuffer=1024*1024){try{let output=execFileSync(command,args,{timeout:timeoutMs,encoding:`utf8`,maxBuffer});return String(output??``).trim()||null}catch{return null}}function inferKindFromIdentifier(identifier){let id=identifier.toLowerCase();return id.includes(`brave`)?`brave`:id.includes(`edge`)?`edge`:id.includes(`chromium`)?`chromium`:id.includes(`canary`)?`canary`:id.includes(`opera`)||id.includes(`vivaldi`)||id.includes(`yandex`)||id.includes(`thebrowser`)?`chromium`:`chrome`}function inferKindFromExecutableName(name){let lower=name.toLowerCase();return lower.includes(`brave`)?`brave`:lower.includes(`edge`)||lower.includes(`msedge`)?`edge`:lower.includes(`chromium`)?`chromium`:lower.includes(`canary`)||lower.includes(`sxs`)?`canary`:lower.includes(`opera`)||lower.includes(`vivaldi`)||lower.includes(`yandex`)?`chromium`:`chrome`}function detectDefaultChromiumExecutable(platform){return platform===`darwin`?detectDefaultChromiumExecutableMac():platform===`linux`?detectDefaultChromiumExecutableLinux():platform===`win32`?detectDefaultChromiumExecutableWindows():null}function detectDefaultChromiumExecutableMac(){let bundleId=detectDefaultBrowserBundleIdMac();if(!bundleId||!CHROMIUM_BUNDLE_IDS.has(bundleId))return null;let appPathRaw=execText(`/usr/bin/osascript`,[`-e`,`POSIX path of (path to application id "${bundleId}")`]);if(!appPathRaw)return null;let appPath=appPathRaw.trim().replace(/\/$/,``),exeName=execText(`/usr/bin/defaults`,[`read`,path.join(appPath,`Contents`,`Info`),`CFBundleExecutable`]);if(!exeName)return null;let exePath=path.join(appPath,`Contents`,`MacOS`,exeName.trim());return exists$1(exePath)?{kind:inferKindFromIdentifier(bundleId),path:exePath}:null}function detectDefaultBrowserBundleIdMac(){let plistPath=path.join(os.homedir(),`Library/Preferences/com.apple.LaunchServices/com.apple.launchservices.secure.plist`);if(!exists$1(plistPath))return null;let handlersRaw=execText(`/usr/bin/plutil`,[`-extract`,`LSHandlers`,`json`,`-o`,`-`,`--`,plistPath],2e3,5*1024*1024);if(!handlersRaw)return null;let handlers;try{handlers=JSON.parse(handlersRaw)}catch{return null}if(!Array.isArray(handlers))return null;let resolveScheme=scheme=>{let candidate=null;for(let entry of handlers){if(!entry||typeof entry!=`object`)continue;let record=entry;if(record.LSHandlerURLScheme!==scheme)continue;let role=typeof record.LSHandlerRoleAll==`string`&&record.LSHandlerRoleAll||typeof record.LSHandlerRoleViewer==`string`&&record.LSHandlerRoleViewer||null;role&&(candidate=role)}return candidate};return resolveScheme(`http`)??resolveScheme(`https`)}function detectDefaultChromiumExecutableLinux(){let desktopId=execText(`xdg-settings`,[`get`,`default-web-browser`])||execText(`xdg-mime`,[`query`,`default`,`x-scheme-handler/http`]);if(!desktopId)return null;let trimmed=desktopId.trim();if(!CHROMIUM_DESKTOP_IDS.has(trimmed))return null;let desktopPath=findDesktopFilePath(trimmed);if(!desktopPath)return null;let execLine=readDesktopExecLine(desktopPath);if(!execLine)return null;let command=extractExecutableFromExecLine(execLine);if(!command)return null;let resolved=resolveLinuxExecutablePath(command);if(!resolved)return null;let exeName=path.posix.basename(resolved).toLowerCase();return CHROMIUM_EXE_NAMES.has(exeName)?{kind:inferKindFromExecutableName(exeName),path:resolved}:null}function detectDefaultChromiumExecutableWindows(){let progId=readWindowsProgId(),command=(progId?readWindowsCommandForProgId(progId):null)||readWindowsCommandForProgId(`http`);if(!command)return null;let exePath=extractWindowsExecutablePath(expandWindowsEnvVars(command));if(!exePath||!exists$1(exePath))return null;let exeName=path.win32.basename(exePath).toLowerCase();return CHROMIUM_EXE_NAMES.has(exeName)?{kind:inferKindFromExecutableName(exeName),path:exePath}:null}function findDesktopFilePath(desktopId){let candidates=[path.join(os.homedir(),`.local`,`share`,`applications`,desktopId),path.join(`/usr/local/share/applications`,desktopId),path.join(`/usr/share/applications`,desktopId),path.join(`/var/lib/snapd/desktop/applications`,desktopId)];for(let candidate of candidates)if(exists$1(candidate))return candidate;return null}function readDesktopExecLine(desktopPath){try{let lines=fs.readFileSync(desktopPath,`utf8`).split(/\r?\n/);for(let line of lines)if(line.startsWith(`Exec=`))return line.slice(5).trim()}catch{}return null}function extractExecutableFromExecLine(execLine){let tokens=splitExecLine(execLine);for(let token of tokens)if(token&&token!==`env`&&!(token.includes(`=`)&&!token.startsWith(`/`)&&!token.includes(`\\`)))return token.replace(/^["']|["']$/g,``);return null}function splitExecLine(line){let tokens=[],current=``,inQuotes=!1,quoteChar=``;for(let i=0;i<line.length;i+=1){let ch=line[i];if((ch===`"`||ch===`'`)&&(!inQuotes||ch===quoteChar)){inQuotes?(inQuotes=!1,quoteChar=``):(inQuotes=!0,quoteChar=ch);continue}if(!inQuotes&&/\s/.test(ch)){current&&=(tokens.push(current),``);continue}current+=ch}return current&&tokens.push(current),tokens}function resolveLinuxExecutablePath(command){let cleaned=command.trim().replace(/%[a-zA-Z]/g,``);if(!cleaned)return null;if(cleaned.startsWith(`/`))return cleaned;let resolved=execText(`which`,[cleaned],800);return resolved?resolved.trim():null}function readWindowsProgId(){let output=execText(`reg`,[`query`,`HKCU\\Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\http\\UserChoice`,`/v`,`ProgId`]);return output&&output.match(/ProgId\s+REG_\w+\s+(.+)$/im)?.[1]?.trim()||null}function readWindowsCommandForProgId(progId){let output=execText(`reg`,[`query`,progId===`http`?`HKCR\\http\\shell\\open\\command`:`HKCR\\${progId}\\shell\\open\\command`,`/ve`]);return output&&output.match(/REG_\w+\s+(.+)$/im)?.[1]?.trim()||null}function expandWindowsEnvVars(value){return value.replace(/%([^%]+)%/g,(_match,name)=>{let key=String(name??``).trim();return key?process.env[key]??`%${key}%`:_match})}function extractWindowsExecutablePath(command){let quoted=command.match(/"([^"]+\\.exe)"/i);if(quoted?.[1])return quoted[1];let unquoted=command.match(/([^\\s]+\\.exe)/i);return unquoted?.[1]?unquoted[1]:null}function findFirstExecutable(candidates){for(let candidate of candidates)if(exists$1(candidate.path))return candidate;return null}function findChromeExecutableMac(){return findFirstExecutable([{kind:`chrome`,path:`/Applications/Google Chrome.app/Contents/MacOS/Google Chrome`},{kind:`chrome`,path:path.join(os.homedir(),`Applications/Google Chrome.app/Contents/MacOS/Google Chrome`)},{kind:`brave`,path:`/Applications/Brave Browser.app/Contents/MacOS/Brave Browser`},{kind:`brave`,path:path.join(os.homedir(),`Applications/Brave Browser.app/Contents/MacOS/Brave Browser`)},{kind:`edge`,path:`/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge`},{kind:`edge`,path:path.join(os.homedir(),`Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge`)},{kind:`chromium`,path:`/Applications/Chromium.app/Contents/MacOS/Chromium`},{kind:`chromium`,path:path.join(os.homedir(),`Applications/Chromium.app/Contents/MacOS/Chromium`)},{kind:`canary`,path:`/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary`},{kind:`canary`,path:path.join(os.homedir(),`Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary`)}])}function findChromeExecutableLinux(){return findFirstExecutable([{kind:`chrome`,path:`/usr/bin/google-chrome`},{kind:`chrome`,path:`/usr/bin/google-chrome-stable`},{kind:`chrome`,path:`/usr/bin/chrome`},{kind:`brave`,path:`/usr/bin/brave-browser`},{kind:`brave`,path:`/usr/bin/brave-browser-stable`},{kind:`brave`,path:`/usr/bin/brave`},{kind:`brave`,path:`/snap/bin/brave`},{kind:`edge`,path:`/usr/bin/microsoft-edge`},{kind:`edge`,path:`/usr/bin/microsoft-edge-stable`},{kind:`chromium`,path:`/usr/bin/chromium`},{kind:`chromium`,path:`/usr/bin/chromium-browser`},{kind:`chromium`,path:`/snap/bin/chromium`}])}function findChromeExecutableWindows(){let localAppData=process.env.LOCALAPPDATA??``,programFiles=process.env.ProgramFiles??`C:\\Program Files`,programFilesX86=process.env[`ProgramFiles(x86)`]??`C:\\Program Files (x86)`,joinWin=path.win32.join,candidates=[];return localAppData&&(candidates.push({kind:`chrome`,path:joinWin(localAppData,`Google`,`Chrome`,`Application`,`chrome.exe`)}),candidates.push({kind:`brave`,path:joinWin(localAppData,`BraveSoftware`,`Brave-Browser`,`Application`,`brave.exe`)}),candidates.push({kind:`edge`,path:joinWin(localAppData,`Microsoft`,`Edge`,`Application`,`msedge.exe`)}),candidates.push({kind:`chromium`,path:joinWin(localAppData,`Chromium`,`Application`,`chrome.exe`)}),candidates.push({kind:`canary`,path:joinWin(localAppData,`Google`,`Chrome SxS`,`Application`,`chrome.exe`)})),candidates.push({kind:`chrome`,path:joinWin(programFiles,`Google`,`Chrome`,`Application`,`chrome.exe`)}),candidates.push({kind:`chrome`,path:joinWin(programFilesX86,`Google`,`Chrome`,`Application`,`chrome.exe`)}),candidates.push({kind:`brave`,path:joinWin(programFiles,`BraveSoftware`,`Brave-Browser`,`Application`,`brave.exe`)}),candidates.push({kind:`brave`,path:joinWin(programFilesX86,`BraveSoftware`,`Brave-Browser`,`Application`,`brave.exe`)}),candidates.push({kind:`edge`,path:joinWin(programFiles,`Microsoft`,`Edge`,`Application`,`msedge.exe`)}),candidates.push({kind:`edge`,path:joinWin(programFilesX86,`Microsoft`,`Edge`,`Application`,`msedge.exe`)}),findFirstExecutable(candidates)}function resolveBrowserExecutableForPlatform(resolved,platform){if(resolved.executablePath){if(!exists$1(resolved.executablePath))throw Error(`browser.executablePath not found: ${resolved.executablePath}`);return{kind:`custom`,path:resolved.executablePath}}return detectDefaultChromiumExecutable(platform)||(platform===`darwin`?findChromeExecutableMac():platform===`linux`?findChromeExecutableLinux():platform===`win32`?findChromeExecutableWindows():null)}process.platform;var PortInUseError=class extends Error{constructor(port,details){super(`Port ${port} is already in use.`),this.name=`PortInUseError`,this.port=port,this.details=details}};async function ensurePortAvailable(port){try{await new Promise((resolve,reject)=>{let tester=net.createServer().once(`error`,err=>reject(err)).once(`listening`,()=>{tester.close(()=>resolve())}).listen(port)})}catch(err){throw isErrno(err)&&err.code===`EADDRINUSE`?new PortInUseError(port):err}}function decoratedMarkerPath(userDataDir){return path.join(userDataDir,`.builderforce-profile-decorated`)}function safeReadJson(filePath){try{if(!fs.existsSync(filePath))return null;let raw=fs.readFileSync(filePath,`utf-8`),parsed=JSON.parse(raw);return typeof parsed!=`object`||!parsed||Array.isArray(parsed)?null:parsed}catch{return null}}function safeWriteJson(filePath,data){fs.mkdirSync(path.dirname(filePath),{recursive:!0}),fs.writeFileSync(filePath,JSON.stringify(data,null,2))}function setDeep(obj,keys,value){let node=obj;for(let key of keys.slice(0,-1)){let next=node[key];(typeof next!=`object`||!next||Array.isArray(next))&&(node[key]={}),node=node[key]}node[keys[keys.length-1]??``]=value}function parseHexRgbToSignedArgbInt(hex){let cleaned=hex.trim().replace(/^#/,``);if(!/^[0-9a-fA-F]{6}$/.test(cleaned))return null;let argbUnsigned=255<<24|Number.parseInt(cleaned,16);return argbUnsigned>2147483647?argbUnsigned-4294967296:argbUnsigned}function isProfileDecorated(userDataDir,desiredName,desiredColorHex){let desiredColorInt=parseHexRgbToSignedArgbInt(desiredColorHex),localStatePath=path.join(userDataDir,`Local State`),preferencesPath=path.join(userDataDir,`Default`,`Preferences`),profile=safeReadJson(localStatePath)?.profile,infoCache=typeof profile==`object`&&profile&&!Array.isArray(profile)?profile.info_cache:null,info=typeof infoCache==`object`&&infoCache&&!Array.isArray(infoCache)&&typeof infoCache.Default==`object`&&infoCache.Default!==null&&!Array.isArray(infoCache.Default)?infoCache.Default:null,prefs=safeReadJson(preferencesPath),browserTheme=(()=>{let browser=prefs?.browser,theme=typeof browser==`object`&&browser&&!Array.isArray(browser)?browser.theme:null;return typeof theme==`object`&&theme&&!Array.isArray(theme)?theme:null})(),autogeneratedTheme=(()=>{let autogenerated=prefs?.autogenerated,theme=typeof autogenerated==`object`&&autogenerated&&!Array.isArray(autogenerated)?autogenerated.theme:null;return typeof theme==`object`&&theme&&!Array.isArray(theme)?theme:null})(),nameOk=typeof info?.name==`string`?info.name===desiredName:!0;if(desiredColorInt==null)return nameOk;let localSeedOk=typeof info?.profile_color_seed==`number`?info.profile_color_seed===desiredColorInt:!1,prefOk=typeof browserTheme?.user_color2==`number`&&browserTheme.user_color2===desiredColorInt||typeof autogeneratedTheme?.color==`number`&&autogeneratedTheme.color===desiredColorInt;return nameOk&&localSeedOk&&prefOk}function decorateBuilderForceAgentsProfile(userDataDir,opts){let desiredName=opts?.name??DEFAULT_BUILDERFORCE_AGENTS_BROWSER_PROFILE_NAME,desiredColor=(opts?.color??DEFAULT_BUILDERFORCE_AGENTS_BROWSER_COLOR).toUpperCase(),desiredColorInt=parseHexRgbToSignedArgbInt(desiredColor),localStatePath=path.join(userDataDir,`Local State`),preferencesPath=path.join(userDataDir,`Default`,`Preferences`),localState=safeReadJson(localStatePath)??{};setDeep(localState,[`profile`,`info_cache`,`Default`,`name`],desiredName),setDeep(localState,[`profile`,`info_cache`,`Default`,`shortcut_name`],desiredName),setDeep(localState,[`profile`,`info_cache`,`Default`,`user_name`],desiredName),setDeep(localState,[`profile`,`info_cache`,`Default`,`profile_color`],desiredColor),setDeep(localState,[`profile`,`info_cache`,`Default`,`user_color`],desiredColor),desiredColorInt!=null&&(setDeep(localState,[`profile`,`info_cache`,`Default`,`profile_color_seed`],desiredColorInt),setDeep(localState,[`profile`,`info_cache`,`Default`,`profile_highlight_color`],desiredColorInt),setDeep(localState,[`profile`,`info_cache`,`Default`,`default_avatar_fill_color`],desiredColorInt),setDeep(localState,[`profile`,`info_cache`,`Default`,`default_avatar_stroke_color`],desiredColorInt)),safeWriteJson(localStatePath,localState);let prefs=safeReadJson(preferencesPath)??{};setDeep(prefs,[`profile`,`name`],desiredName),setDeep(prefs,[`profile`,`profile_color`],desiredColor),setDeep(prefs,[`profile`,`user_color`],desiredColor),desiredColorInt!=null&&(setDeep(prefs,[`autogenerated`,`theme`,`color`],desiredColorInt),setDeep(prefs,[`browser`,`theme`,`user_color2`],desiredColorInt)),safeWriteJson(preferencesPath,prefs);try{fs.writeFileSync(decoratedMarkerPath(userDataDir),`${Date.now()}\n`,`utf-8`)}catch{}}function ensureProfileCleanExit(userDataDir){let preferencesPath=path.join(userDataDir,`Default`,`Preferences`),prefs=safeReadJson(preferencesPath)??{};setDeep(prefs,[`exit_type`],`Normal`),setDeep(prefs,[`exited_cleanly`],!0),safeWriteJson(preferencesPath,prefs)}const log=createSubsystemLogger(`browser`).child(`chrome`);function exists(filePath){try{return fs.existsSync(filePath)}catch{return!1}}function resolveBrowserExecutable(resolved){return resolveBrowserExecutableForPlatform(resolved,process.platform)}function resolveBuilderForceAgentsUserDataDir(profileName=DEFAULT_BUILDERFORCE_AGENTS_BROWSER_PROFILE_NAME){return path.join(CONFIG_DIR,`browser`,profileName,`user-data`)}function cdpUrlForPort(cdpPort){return`http://127.0.0.1:${cdpPort}`}async function isChromeReachable(cdpUrl,timeoutMs=500){return!!await fetchChromeVersion(cdpUrl,timeoutMs)}async function fetchChromeVersion(cdpUrl,timeoutMs=500){let ctrl=new AbortController,t=setTimeout(ctrl.abort.bind(ctrl),timeoutMs);try{let versionUrl=appendCdpPath(cdpUrl,`/json/version`),res=await fetch(versionUrl,{signal:ctrl.signal,headers:getHeadersWithAuth(versionUrl)});if(!res.ok)return null;let data=await res.json();return!data||typeof data!=`object`?null:data}catch{return null}finally{clearTimeout(t)}}async function getChromeWebSocketUrl(cdpUrl,timeoutMs=500){let version=await fetchChromeVersion(cdpUrl,timeoutMs),wsUrl=String(version?.webSocketDebuggerUrl??``).trim();return wsUrl?normalizeCdpWsUrl(wsUrl,cdpUrl):null}async function canOpenWebSocket(wsUrl,timeoutMs=800){return await new Promise(resolve=>{let headers=getHeadersWithAuth(wsUrl),ws=new WebSocket(wsUrl,{handshakeTimeout:timeoutMs,...Object.keys(headers).length?{headers}:{}}),timer=setTimeout(()=>{try{ws.terminate()}catch{}resolve(!1)},Math.max(50,timeoutMs+25));ws.once(`open`,()=>{clearTimeout(timer);try{ws.close()}catch{}resolve(!0)}),ws.once(`error`,()=>{clearTimeout(timer),resolve(!1)})})}async function isChromeCdpReady(cdpUrl,timeoutMs=500,handshakeTimeoutMs=800){let wsUrl=await getChromeWebSocketUrl(cdpUrl,timeoutMs);return wsUrl?await canOpenWebSocket(wsUrl,handshakeTimeoutMs):!1}async function launchBuilderForceAgentsChrome(resolved,profile){if(!profile.cdpIsLoopback)throw Error(`Profile "${profile.name}" is remote; cannot launch local Chrome.`);await ensurePortAvailable(profile.cdpPort);let exe=resolveBrowserExecutable(resolved);if(!exe)throw Error(`No supported browser found (Chrome/Brave/Edge/Chromium on macOS, Linux, or Windows).`);let userDataDir=resolveBuilderForceAgentsUserDataDir(profile.name);fs.mkdirSync(userDataDir,{recursive:!0});let needsDecorate=!isProfileDecorated(userDataDir,profile.name,(profile.color??DEFAULT_BUILDERFORCE_AGENTS_BROWSER_COLOR).toUpperCase()),spawnOnce=()=>{let args=[`--remote-debugging-port=${profile.cdpPort}`,`--user-data-dir=${userDataDir}`,`--no-first-run`,`--no-default-browser-check`,`--disable-sync`,`--disable-background-networking`,`--disable-component-update`,`--disable-features=Translate,MediaRouter`,`--disable-session-crashed-bubble`,`--hide-crash-restore-bubble`,`--password-store=basic`];return resolved.headless&&(args.push(`--headless=new`),args.push(`--disable-gpu`)),resolved.noSandbox&&(args.push(`--no-sandbox`),args.push(`--disable-setuid-sandbox`)),process.platform===`linux`&&args.push(`--disable-dev-shm-usage`),args.push(`--disable-blink-features=AutomationControlled`),resolved.extraArgs.length>0&&args.push(...resolved.extraArgs),args.push(`about:blank`),spawn(exe.path,args,{stdio:`pipe`,env:{...process.env,HOME:os.homedir()}})},startedAt=Date.now(),localStatePath=path.join(userDataDir,`Local State`),preferencesPath=path.join(userDataDir,`Default`,`Preferences`);if(!exists(localStatePath)||!exists(preferencesPath)){let bootstrap=spawnOnce(),deadline=Date.now()+1e4;for(;Date.now()<deadline&&!(exists(localStatePath)&&exists(preferencesPath));)await new Promise(r=>setTimeout(r,100));try{bootstrap.kill(`SIGTERM`)}catch{}let exitDeadline=Date.now()+5e3;for(;Date.now()<exitDeadline&&bootstrap.exitCode==null;)await new Promise(r=>setTimeout(r,50))}if(needsDecorate)try{decorateBuilderForceAgentsProfile(userDataDir,{name:profile.name,color:profile.color}),log.info(`🤖 builderforce browser profile decorated (${profile.color})`)}catch(err){log.warn(`builderforce browser profile decoration failed: ${String(err)}`)}try{ensureProfileCleanExit(userDataDir)}catch(err){log.warn(`builderforce browser clean-exit prefs failed: ${String(err)}`)}let proc=spawnOnce(),readyDeadline=Date.now()+15e3;for(;Date.now()<readyDeadline&&!await isChromeReachable(profile.cdpUrl,500);)await new Promise(r=>setTimeout(r,200));if(!await isChromeReachable(profile.cdpUrl,500)){try{proc.kill(`SIGKILL`)}catch{}throw Error(`Failed to start Chrome CDP on port ${profile.cdpPort} for profile "${profile.name}".`)}let pid=proc.pid??-1;return log.info(`🤖 builderforce browser started (${exe.kind}) profile "${profile.name}" on 127.0.0.1:${profile.cdpPort} (pid ${pid})`),{pid,exe,userDataDir,cdpPort:profile.cdpPort,startedAt,proc}}async function stopBuilderForceAgentsChrome(running,timeoutMs=2500){let proc=running.proc;if(proc.killed)return;try{proc.kill(`SIGTERM`)}catch{}let start=Date.now();for(;Date.now()-start<timeoutMs&&!(!proc.exitCode&&proc.killed);){if(!await isChromeReachable(cdpUrlForPort(running.cdpPort),200))return;await new Promise(r=>setTimeout(r,100))}try{proc.kill(`SIGKILL`)}catch{}}export{pickPrimaryTailnetIPv4 as A,DEFAULT_BROWSER_DEFAULT_PROFILE_NAME as C,DEFAULT_BUILDERFORCE_AGENTS_BROWSER_PROFILE_NAME as D,DEFAULT_BUILDERFORCE_AGENTS_BROWSER_ENABLED as E,rawDataToString as M,isLoopbackHost as O,DEFAULT_AI_SNAPSHOT_MAX_CHARS as S,DEFAULT_BUILDERFORCE_AGENTS_BROWSER_COLOR as T,withCdpSocket as _,resolveBuilderForceAgentsUserDataDir as a,DEFAULT_AI_SNAPSHOT_EFFICIENT_DEPTH as b,captureScreenshot as c,normalizeCdpWsUrl as d,snapshotAria as f,getHeadersWithAuth as g,fetchOk as h,launchBuilderForceAgentsChrome as i,resolvePreferredBuilderForceAgentsTmpDir as j,pickPrimaryLanIPv4 as k,createTargetViaCdp as l,fetchJson as m,isChromeCdpReady as n,stopBuilderForceAgentsChrome as o,appendCdpPath as p,isChromeReachable as r,resolveBrowserExecutableForPlatform as s,getChromeWebSocketUrl as t,formatAriaSnapshot as u,ensureChromeExtensionRelayServer as v,DEFAULT_BROWSER_EVALUATE_ENABLED as w,DEFAULT_AI_SNAPSHOT_EFFICIENT_MAX_CHARS as x,stopChromeExtensionRelayServer as y};
|