























@@ -1,40 +1,120 @@
11import type {
2+AnyAgentTool,
23OpenClawPluginApi,
34OpenClawPluginNodeHostCommand,
5+OpenClawPluginSecurityAuditCollector,
6+OpenClawPluginService,
47OpenClawPluginToolContext,
58OpenClawPluginToolFactory,
69} from "openclaw/plugin-sdk/plugin-entry";
7-import {
8-collectBrowserSecurityAuditFindings,
9-createBrowserPluginService,
10-createBrowserTool,
11-handleBrowserGatewayRequest,
12-registerBrowserCli,
13-runBrowserProxyCommand,
14-} from "./register.runtime.js";
10+import { BrowserToolSchema } from "./src/browser-tool.schema.js";
11+12+const BROWSER_CLI_DESCRIPTOR = {
13+name: "browser",
14+description: "Manage OpenClaw's dedicated browser (Chrome/Chromium)",
15+hasSubcommands: true,
16+};
17+18+function createLazyBrowserTool(opts?: {
19+sandboxBridgeUrl?: string;
20+allowHostControl?: boolean;
21+agentSessionKey?: string;
22+}): AnyAgentTool {
23+const targetDefault = opts?.sandboxBridgeUrl ? "sandbox" : "host";
24+const hostHint =
25+opts?.allowHostControl === false ? "Host target blocked by policy." : "Host target allowed.";
26+return {
27+label: "Browser",
28+name: "browser",
29+description: [
30+"Control the browser via OpenClaw's browser control server (status/start/stop/profiles/tabs/open/snapshot/screenshot/actions).",
31+"Browser choice: omit profile by default for the isolated OpenClaw-managed browser (`openclaw`).",
32+'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.',
33+'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.',
34+'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".',
35+"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.",
36+"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.",
37+'For stable, self-resolving refs across calls, use snapshot with refs="aria" (Playwright aria-ref ids). Default refs="role" are role+name-based.',
38+"Use snapshot+act for UI automation. Avoid act:wait by default; use only in exceptional cases when no reliable UI state exists.",
39+`target selects browser location (sandbox|host|node). Default: ${targetDefault}.`,
40+hostHint,
41+].join(" "),
42+parameters: BrowserToolSchema,
43+execute: async (toolCallId, args, signal, onUpdate) => {
44+const { createBrowserTool } = await import("./register.runtime.js");
45+const tool = createBrowserTool(opts);
46+return await tool.execute(toolCallId, args, signal, onUpdate);
47+},
48+};
49+}
15501651export const browserPluginReload = { restartPrefixes: ["browser"] };
17521853export const browserPluginNodeHostCommands: OpenClawPluginNodeHostCommand[] = [
1954{
2055command: "browser.proxy",
2156cap: "browser",
22-handle: runBrowserProxyCommand,
57+handle: async (paramsJSON) => {
58+const { runBrowserProxyCommand } = await import("./register.runtime.js");
59+return await runBrowserProxyCommand(paramsJSON);
60+},
2361},
2462];
256326-export const browserSecurityAuditCollectors = [collectBrowserSecurityAuditFindings];
64+export const browserSecurityAuditCollectors: OpenClawPluginSecurityAuditCollector[] = [
65+async (ctx) => {
66+const { collectBrowserSecurityAuditFindings } = await import("./register.runtime.js");
67+return collectBrowserSecurityAuditFindings(ctx);
68+},
69+];
70+71+function createLazyBrowserPluginService(): OpenClawPluginService {
72+let service: OpenClawPluginService | null = null;
73+const loadService = async () => {
74+if (!service) {
75+const { createBrowserPluginService } = await import("./register.runtime.js");
76+service = createBrowserPluginService();
77+}
78+return service;
79+};
80+return {
81+id: "browser-control",
82+start: async (ctx) => {
83+const loaded = await loadService();
84+await loaded.start(ctx);
85+},
86+stop: async (ctx) => {
87+if (!service?.stop) {
88+return;
89+}
90+await service.stop(ctx);
91+},
92+};
93+}
27942895export function registerBrowserPlugin(api: OpenClawPluginApi) {
2996api.registerTool(((ctx: OpenClawPluginToolContext) =>
30-createBrowserTool({
97+createLazyBrowserTool({
3198sandboxBridgeUrl: ctx.browser?.sandboxBridgeUrl,
3299allowHostControl: ctx.browser?.allowHostControl,
33100agentSessionKey: ctx.sessionKey,
34101})) as OpenClawPluginToolFactory);
35-api.registerCli(({ program }) => registerBrowserCli(program), { commands: ["browser"] });
36-api.registerGatewayMethod("browser.request", handleBrowserGatewayRequest, {
37-scope: "operator.admin",
38-});
39-api.registerService(createBrowserPluginService());
102+api.registerCli(
103+async ({ program }) => {
104+const { registerBrowserCli } = await import("./src/cli/browser-cli.js");
105+registerBrowserCli(program);
106+},
107+{ commands: ["browser"], descriptors: [BROWSER_CLI_DESCRIPTOR] },
108+);
109+api.registerGatewayMethod(
110+"browser.request",
111+async (opts) => {
112+const { handleBrowserGatewayRequest } = await import("./register.runtime.js");
113+return await handleBrowserGatewayRequest(opts);
114+},
115+{
116+scope: "operator.admin",
117+},
118+);
119+api.registerService(createLazyBrowserPluginService());
40120}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。