openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
121 lines (120 loc) • 8.08 kB
JavaScript
import { A as writeExternalFileWithinRoot } from "../../fs-safe-B6pvPGnf.js";
import { t as definePluginEntry } from "../../plugin-entry-zfBGJaNO.js";
import { n as resolveExistingPathsWithinRoot } from "../../security-runtime-Ckf0kc0h.js";
import { n as redactCdpUrl } from "../../browser-cdp-DfRHhv02.js";
import { f as DEFAULT_OPENCLAW_BROWSER_COLOR, m as DEFAULT_OPENCLAW_BROWSER_PROFILE_NAME, r as DEFAULT_AI_SNAPSHOT_MAX_CHARS, s as DEFAULT_BROWSER_EVALUATE_ENABLED } from "../../constants-DKjTvIBP.js";
import { a as resolveProfile, r as resolveBrowserConfig } from "../../config-BosO4Zbt.js";
import { t as getBrowserProfileCapabilities } from "../../profile-capabilities-B30ig3n7.js";
import { n as installBrowserAuthMiddleware, r as installBrowserCommonMiddleware } from "../../server-middleware-CwDqkWQc.js";
import "../../sdk-security-runtime-De1urFYo.js";
import { d as parseBrowserMajorVersion, f as readBrowserVersion, m as resolveGoogleChromeExecutableForPlatform } from "../../chrome-CtUCaDWQ.js";
import { r as DEFAULT_UPLOAD_DIR } from "../../paths-CA_QMzCv.js";
import { r as stopBrowserRuntime, t as createBrowserRuntimeState } from "../../runtime-lifecycle-DhKurfgJ.js";
import { a as untrackSessionBrowserTab, i as trackSessionBrowserTab, t as closeTrackedBrowserTabsForSessions } from "../../session-tab-registry-7B39oGZ2.js";
import { n as stopBrowserBridgeServer, t as startBrowserBridgeServer } from "../../bridge-server-BAaCS-Bc.js";
import { n as resolveBrowserControlAuth, t as ensureBrowserControlAuth } from "../../control-auth-DxPMmxz-.js";
import { t as createBrowserRouteContext } from "../../server-context-CSIC6Xps.js";
import { t as movePathToTrash } from "../../trash-BWuUMhs8.js";
import { a as createBrowserTool, c as browserAct, d as browserNavigate, f as browserScreenshotAction, i as runBrowserProxyCommand, l as browserArmDialog, n as browserHandlers, o as browserConsoleMessages, r as handleBrowserGatewayRequest, s as browserPdfSave, t as createBrowserPluginService, u as browserArmFileChooser } from "../../plugin-service-CaWAXW9h.js";
import { _ as browserTabs, a as browserDoctor, c as browserOpenTab, d as browserSnapshot, f as browserStart, g as browserTabAction, i as browserDeleteProfile, l as browserProfiles, m as browserStop, o as browserFocusTab, p as browserStatus, r as browserCreateProfile, t as browserCloseTab, u as browserResetProfile } from "../../client-x-IUPjVX.js";
import { t as registerBrowserRoutes } from "../../routes-g8jdcRKn.js";
import { a as resolveRequestedBrowserProfile, i as normalizeBrowserRequestPath, r as isPersistentBrowserProfileMutation, t as createBrowserRouteDispatcher } from "../../dispatcher-wCUy7gxn.js";
import { n as normalizeBrowserFormField, r as normalizeBrowserFormFieldValue } from "../../form-fields-Deu-DeE_.js";
import { r as getBrowserControlState, t as createBrowserControlContext } from "../../browser-control-state-BwkjlfAE.js";
import { n as stopBrowserControlService, t as startBrowserControlServiceFromConfig } from "../../control-service-DCNNOWdd.js";
import { n as closePlaywrightBrowserConnection } from "../../pw-session-BRMikH-G.js";
import { t as registerBrowserCli } from "../../browser-cli-Bdbn-r9L.js";
import path from "node:path";
import { chmod, copyFile } from "node:fs/promises";
import { randomBytes } from "node:crypto";
//#region extensions/browser/src/attached-browser-tool-runtime.ts
/**
* Attach-only Browser tool runtime for a caller-owned loopback Chrome process.
*
* The bridge owns only authenticated Browser HTTP ingress. Chrome remains owned
* by the caller and survives bridge disposal.
*/
const ATTACHED_PROFILE_NAME = "worker";
async function persistAttachedScreenshot(params) {
const extension = params.type === "jpeg" ? "jpg" : "png";
const fileName = `screenshot-${randomBytes(8).toString("hex")}.${extension}`;
return (await writeExternalFileWithinRoot({
rootDir: params.workspaceDir,
path: path.join(".artifacts", "cloud-worker-browser", fileName),
fallbackFileName: fileName,
write: async (stagedPath) => {
await copyFile(params.sourcePath, stagedPath);
await chmod(stagedPath, 384);
}
})).path;
}
function normalizeAttachedCdpUrl(raw) {
let parsed;
try {
parsed = new URL(raw);
} catch {
throw new Error("Attached Browser CDP URL must be a loopback HTTP URL with an explicit port.");
}
const port = Number(parsed.port);
if (parsed.protocol !== "http:" || parsed.hostname !== "127.0.0.1" || parsed.username !== "" || parsed.password !== "" || parsed.port === "" || !Number.isInteger(port) || port < 1 || port > 65535 || parsed.pathname !== "/" || parsed.search !== "" || parsed.hash !== "") throw new Error("Attached Browser CDP URL must be a loopback HTTP URL with an explicit port.");
return parsed.toString().replace(/\/$/u, "");
}
/** Create a normal Browser agent tool pinned to one raw, attach-only CDP profile. */
async function createAttachedBrowserToolRuntime(params) {
const cdpUrl = normalizeAttachedCdpUrl(params.cdpUrl);
const resolved = resolveBrowserConfig({
enabled: true,
attachOnly: true,
cdpUrl,
defaultProfile: ATTACHED_PROFILE_NAME,
profiles: { [ATTACHED_PROFILE_NAME]: {
driver: "openclaw",
attachOnly: true,
cdpUrl
} }
});
resolved.profiles = { [ATTACHED_PROFILE_NAME]: {
driver: "openclaw",
attachOnly: true,
cdpUrl
} };
resolved.extensionRelayPorts = {};
resolved.extensionRelayInternalTokens = {};
const bridge = await startBrowserBridgeServer({
resolved,
host: "127.0.0.1",
port: 0,
authToken: randomBytes(32).toString("base64url"),
onEnsureAttachTarget: async () => await params.ensureAttachTarget()
});
const dispose = async () => {
try {
await stopBrowserBridgeServer(bridge.server);
} finally {
await closePlaywrightBrowserConnection({ cdpUrl });
}
};
try {
return {
tool: createBrowserTool({
sandboxBridgeUrl: bridge.baseUrl,
allowHostControl: false,
...params.agentSessionKey !== void 0 ? { agentSessionKey: params.agentSessionKey } : {},
...params.agentDir !== void 0 ? { agentDir: params.agentDir } : {},
...params.workspaceDir !== void 0 ? { workspaceDir: params.workspaceDir } : {},
screenshotResultMode: "path",
persistScreenshot: async ({ sourcePath, type }) => await persistAttachedScreenshot({
sourcePath,
workspaceDir: params.workspaceDir,
type
})
}),
dispose
};
} catch (error) {
await dispose();
throw error;
}
}
//#endregion
export { DEFAULT_AI_SNAPSHOT_MAX_CHARS, DEFAULT_BROWSER_EVALUATE_ENABLED, DEFAULT_OPENCLAW_BROWSER_COLOR, DEFAULT_OPENCLAW_BROWSER_PROFILE_NAME, DEFAULT_UPLOAD_DIR, browserAct, browserArmDialog, browserArmFileChooser, browserCloseTab, browserConsoleMessages, browserCreateProfile, browserDeleteProfile, browserDoctor, browserFocusTab, browserHandlers, browserNavigate, browserOpenTab, browserPdfSave, browserProfiles, browserResetProfile, browserScreenshotAction, browserSnapshot, browserStart, browserStatus, browserStop, browserTabAction, browserTabs, closeTrackedBrowserTabsForSessions, createAttachedBrowserToolRuntime, createBrowserControlContext, createBrowserPluginService, createBrowserRouteContext, createBrowserRouteDispatcher, createBrowserRuntimeState, createBrowserTool, definePluginEntry, ensureBrowserControlAuth, getBrowserControlState, getBrowserProfileCapabilities, handleBrowserGatewayRequest, installBrowserAuthMiddleware, installBrowserCommonMiddleware, isPersistentBrowserProfileMutation, movePathToTrash, normalizeBrowserFormField, normalizeBrowserFormFieldValue, normalizeBrowserRequestPath, parseBrowserMajorVersion, readBrowserVersion, redactCdpUrl, registerBrowserCli, registerBrowserRoutes, resolveBrowserConfig, resolveBrowserControlAuth, resolveExistingPathsWithinRoot, resolveGoogleChromeExecutableForPlatform, resolveProfile, resolveRequestedBrowserProfile, runBrowserProxyCommand, startBrowserBridgeServer, startBrowserControlServiceFromConfig, stopBrowserBridgeServer, stopBrowserControlService, stopBrowserRuntime, trackSessionBrowserTab, untrackSessionBrowserTab };