UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

129 lines (128 loc) 6.61 kB
import { n as BROWSER_REQUEST_GATEWAY_SCOPE, t as BROWSER_REQUEST_GATEWAY_METHOD } from "./browser-gateway-contract-B6OC_gCs.js"; import { t as BrowserToolSchema } from "./browser-tool.schema-tt4NcGdm.js"; //#region extensions/browser/plugin-registration.ts const EAGER_BROWSER_CONTROL_SERVICE_ENV = "OPENCLAW_EAGER_BROWSER_CONTROL_SERVER"; let browserRegistrationRuntimeModulePromise = null; const loadBrowserRegistrationRuntimeModule = async () => { browserRegistrationRuntimeModulePromise ??= import("./extensions/browser/register.runtime.js"); return await browserRegistrationRuntimeModulePromise; }; function isTruthyEnvValue(value) { return /^(?:1|true|yes|on)$/iu.test(value?.trim() ?? ""); } function deriveChatTypeFromSessionKey(sessionKey) { const tokens = new Set(sessionKey?.toLowerCase().split(":").filter(Boolean) ?? []); if (tokens.has("group")) return "group"; if (tokens.has("channel")) return "channel"; if (tokens.has("direct") || tokens.has("dm")) return "direct"; } const BROWSER_CLI_DESCRIPTOR = { name: "browser", description: "Manage OpenClaw's dedicated browser (Chrome/Chromium)", hasSubcommands: true }; function createLazyBrowserTool(opts) { const targetDefault = opts?.sandboxBridgeUrl ? "sandbox" : "host"; const hostHint = opts?.allowHostControl === false ? "Host target blocked by policy." : "Host target allowed."; return { label: "Browser", name: "browser", description: [ "Control the browser via OpenClaw's browser control server (status/start/stop/profiles/tabs/open/snapshot/screenshot/actions).", "Browser choice: omit profile by default for the isolated OpenClaw-managed browser (`openclaw`).", "For the logged-in user browser, use profile=\"user\". A supported Chromium-based browser (v144+) must be running on the selected host or browser node. Use only when existing logins/cookies matter and the user is present.", "For profile=\"user\" or other existing-session profiles, omit timeoutMs on act:type, evaluate, hover, scrollIntoView, drag, select, and fill; that driver rejects per-call timeout overrides for those actions.", "When a node-hosted browser proxy is available, the tool may auto-route to it. Pin a node with node=<id|name> or target=\"node\".", "When using refs from snapshot (e.g. e12), keep the same tab: prefer passing targetId from the snapshot response into subsequent actions (act/click/type/etc). For tab operations, targetId also accepts tabId handles (t1) and labels from action=tabs.", "For multi-step browser work, login checks, stale refs, duplicate tabs, or Google Meet flows, use the bundled browser-automation skill when it is available.", "For stable, self-resolving refs across calls, use snapshot with refs=\"aria\" (Playwright aria-ref ids). Default refs=\"role\" are role+name-based.", "Use snapshot+act for UI automation. Avoid act:wait by default; use only in exceptional cases when no reliable UI state exists.", `target selects browser location (sandbox|host|node). Default: ${targetDefault}.`, hostHint ].join(" "), parameters: BrowserToolSchema, execute: async (toolCallId, args, signal, onUpdate) => { const { createBrowserTool } = await loadBrowserRegistrationRuntimeModule(); return await createBrowserTool(opts).execute(toolCallId, args, signal, onUpdate); } }; } function createBrowserToolOptions(ctx) { const mediaChannel = ctx.deliveryContext?.channel ?? ctx.messageChannel; const mediaChatType = deriveChatTypeFromSessionKey(ctx.sessionKey); return { ...ctx.browser?.sandboxBridgeUrl ? { sandboxBridgeUrl: ctx.browser.sandboxBridgeUrl } : {}, ...ctx.browser?.allowHostControl !== void 0 ? { allowHostControl: ctx.browser.allowHostControl } : {}, ...ctx.sessionKey ? { agentSessionKey: ctx.sessionKey } : {}, ...ctx.agentDir ? { agentDir: ctx.agentDir } : {}, ...ctx.workspaceDir ? { workspaceDir: ctx.workspaceDir } : {}, ...ctx.activeModel?.provider || ctx.activeModel?.modelId ? { activeModel: { provider: ctx.activeModel.provider, model: ctx.activeModel.modelId } } : {}, ...ctx.sessionKey || mediaChannel ? { mediaScope: { ...ctx.sessionKey ? { sessionKey: ctx.sessionKey } : {}, ...mediaChannel ? { channel: mediaChannel } : {}, ...mediaChatType ? { chatType: mediaChatType } : {} } } : {} }; } /** Browser plugin reload policy. */ const browserPluginReload = { restartPrefixes: ["browser"] }; /** Node-host command descriptors exposed by the Browser plugin. */ const browserPluginNodeHostCommands = [{ command: "browser.proxy", cap: "browser", handle: async (paramsJSON) => { const { runBrowserProxyCommand } = await loadBrowserRegistrationRuntimeModule(); return await runBrowserProxyCommand(paramsJSON); } }]; /** Security audit collectors contributed by the Browser plugin. */ const browserSecurityAuditCollectors = [async (ctx) => { const { collectBrowserSecurityAuditFindings } = await loadBrowserRegistrationRuntimeModule(); return collectBrowserSecurityAuditFindings(ctx); }]; function createLazyBrowserPluginService() { let service = null; const loadService = async () => { if (!service) { const { createBrowserPluginService } = await loadBrowserRegistrationRuntimeModule(); service = createBrowserPluginService(); } return service; }; return { id: "browser-control", start: async (ctx) => { if (!isTruthyEnvValue(process.env[EAGER_BROWSER_CONTROL_SERVICE_ENV])) return; await (await loadService()).start(ctx); }, stop: async (ctx) => { if (!service) { const { stopBrowserControlService } = await import("./control-service-C-wICWzm.js"); await stopBrowserControlService().catch(() => {}); return; } await service.stop?.(ctx); } }; } /** Register Browser tool factories, CLI, gateway methods, services, and audits. */ function registerBrowserPlugin(api) { api.registerTool(((ctx) => createLazyBrowserTool(createBrowserToolOptions(ctx)))); api.registerCli(async ({ program }) => { const { registerBrowserCli } = await import("./browser-cli-BjDTtaOz.js"); registerBrowserCli(program); }, { commands: ["browser"], descriptors: [BROWSER_CLI_DESCRIPTOR] }); api.registerGatewayMethod(BROWSER_REQUEST_GATEWAY_METHOD, async (opts) => { const { handleBrowserGatewayRequest } = await loadBrowserRegistrationRuntimeModule(); return await handleBrowserGatewayRequest(opts); }, { scope: BROWSER_REQUEST_GATEWAY_SCOPE }); api.registerService(createLazyBrowserPluginService()); } //#endregion export { registerBrowserPlugin as i, browserPluginReload as n, browserSecurityAuditCollectors as r, browserPluginNodeHostCommands as t };