mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-03 03:03:24 -04:00
refactor: rename to openclaw
This commit is contained in:
@@ -1,10 +1,13 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
import { DEFAULT_CLAWD_BROWSER_COLOR, DEFAULT_CLAWD_BROWSER_PROFILE_NAME } from "./constants.js";
|
||||
import {
|
||||
DEFAULT_OPENCLAW_BROWSER_COLOR,
|
||||
DEFAULT_OPENCLAW_BROWSER_PROFILE_NAME,
|
||||
} from "./constants.js";
|
||||
|
||||
function decoratedMarkerPath(userDataDir: string) {
|
||||
return path.join(userDataDir, ".clawd-profile-decorated");
|
||||
return path.join(userDataDir, ".openclaw-profile-decorated");
|
||||
}
|
||||
|
||||
function safeReadJson(filePath: string): Record<string, unknown> | null {
|
||||
@@ -118,12 +121,12 @@ export function isProfileDecorated(
|
||||
* Best-effort profile decoration (name + lobster-orange). Chrome preference keys
|
||||
* vary by version; we keep this conservative and idempotent.
|
||||
*/
|
||||
export function decorateClawdProfile(
|
||||
export function decorateOpenClawProfile(
|
||||
userDataDir: string,
|
||||
opts?: { name?: string; color?: string },
|
||||
) {
|
||||
const desiredName = opts?.name ?? DEFAULT_CLAWD_BROWSER_PROFILE_NAME;
|
||||
const desiredColor = (opts?.color ?? DEFAULT_CLAWD_BROWSER_COLOR).toUpperCase();
|
||||
const desiredName = opts?.name ?? DEFAULT_OPENCLAW_BROWSER_PROFILE_NAME;
|
||||
const desiredColor = (opts?.color ?? DEFAULT_OPENCLAW_BROWSER_COLOR).toUpperCase();
|
||||
const desiredColorInt = parseHexRgbToSignedArgbInt(desiredColor);
|
||||
|
||||
const localStatePath = path.join(userDataDir, "Local State");
|
||||
|
||||
@@ -6,15 +6,18 @@ import path from "node:path";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
import {
|
||||
decorateClawdProfile,
|
||||
decorateOpenClawProfile,
|
||||
ensureProfileCleanExit,
|
||||
findChromeExecutableMac,
|
||||
findChromeExecutableWindows,
|
||||
isChromeReachable,
|
||||
resolveBrowserExecutableForPlatform,
|
||||
stopClawdChrome,
|
||||
stopOpenClawChrome,
|
||||
} from "./chrome.js";
|
||||
import { DEFAULT_CLAWD_BROWSER_COLOR, DEFAULT_CLAWD_BROWSER_PROFILE_NAME } from "./constants.js";
|
||||
import {
|
||||
DEFAULT_OPENCLAW_BROWSER_COLOR,
|
||||
DEFAULT_OPENCLAW_BROWSER_PROFILE_NAME,
|
||||
} from "./constants.js";
|
||||
|
||||
async function readJson(filePath: string): Promise<Record<string, unknown>> {
|
||||
const raw = await fsp.readFile(filePath, "utf-8");
|
||||
@@ -28,9 +31,9 @@ describe("browser chrome profile decoration", () => {
|
||||
});
|
||||
|
||||
it("writes expected name + signed ARGB seed to Chrome prefs", async () => {
|
||||
const userDataDir = await fsp.mkdtemp(path.join(os.tmpdir(), "moltbot-chrome-test-"));
|
||||
const userDataDir = await fsp.mkdtemp(path.join(os.tmpdir(), "openclaw-chrome-test-"));
|
||||
try {
|
||||
decorateClawdProfile(userDataDir, { color: DEFAULT_CLAWD_BROWSER_COLOR });
|
||||
decorateOpenClawProfile(userDataDir, { color: DEFAULT_OPENCLAW_BROWSER_COLOR });
|
||||
|
||||
const expectedSignedArgb = ((0xff << 24) | 0xff4500) >> 0;
|
||||
|
||||
@@ -39,8 +42,8 @@ describe("browser chrome profile decoration", () => {
|
||||
const infoCache = profile.info_cache as Record<string, unknown>;
|
||||
const def = infoCache.Default as Record<string, unknown>;
|
||||
|
||||
expect(def.name).toBe(DEFAULT_CLAWD_BROWSER_PROFILE_NAME);
|
||||
expect(def.shortcut_name).toBe(DEFAULT_CLAWD_BROWSER_PROFILE_NAME);
|
||||
expect(def.name).toBe(DEFAULT_OPENCLAW_BROWSER_PROFILE_NAME);
|
||||
expect(def.shortcut_name).toBe(DEFAULT_OPENCLAW_BROWSER_PROFILE_NAME);
|
||||
expect(def.profile_color_seed).toBe(expectedSignedArgb);
|
||||
expect(def.profile_highlight_color).toBe(expectedSignedArgb);
|
||||
expect(def.default_avatar_fill_color).toBe(expectedSignedArgb);
|
||||
@@ -56,7 +59,7 @@ describe("browser chrome profile decoration", () => {
|
||||
expect(autogeneratedTheme.color).toBe(expectedSignedArgb);
|
||||
|
||||
const marker = await fsp.readFile(
|
||||
path.join(userDataDir, ".clawd-profile-decorated"),
|
||||
path.join(userDataDir, ".openclaw-profile-decorated"),
|
||||
"utf-8",
|
||||
);
|
||||
expect(marker.trim()).toMatch(/^\d+$/);
|
||||
@@ -66,15 +69,15 @@ describe("browser chrome profile decoration", () => {
|
||||
});
|
||||
|
||||
it("best-effort writes name when color is invalid", async () => {
|
||||
const userDataDir = await fsp.mkdtemp(path.join(os.tmpdir(), "moltbot-chrome-test-"));
|
||||
const userDataDir = await fsp.mkdtemp(path.join(os.tmpdir(), "openclaw-chrome-test-"));
|
||||
try {
|
||||
decorateClawdProfile(userDataDir, { color: "lobster-orange" });
|
||||
decorateOpenClawProfile(userDataDir, { color: "lobster-orange" });
|
||||
const localState = await readJson(path.join(userDataDir, "Local State"));
|
||||
const profile = localState.profile as Record<string, unknown>;
|
||||
const infoCache = profile.info_cache as Record<string, unknown>;
|
||||
const def = infoCache.Default as Record<string, unknown>;
|
||||
|
||||
expect(def.name).toBe(DEFAULT_CLAWD_BROWSER_PROFILE_NAME);
|
||||
expect(def.name).toBe(DEFAULT_OPENCLAW_BROWSER_PROFILE_NAME);
|
||||
expect(def.profile_color_seed).toBeUndefined();
|
||||
} finally {
|
||||
await fsp.rm(userDataDir, { recursive: true, force: true });
|
||||
@@ -82,7 +85,7 @@ describe("browser chrome profile decoration", () => {
|
||||
});
|
||||
|
||||
it("recovers from missing/invalid preference files", async () => {
|
||||
const userDataDir = await fsp.mkdtemp(path.join(os.tmpdir(), "moltbot-chrome-test-"));
|
||||
const userDataDir = await fsp.mkdtemp(path.join(os.tmpdir(), "openclaw-chrome-test-"));
|
||||
try {
|
||||
await fsp.mkdir(path.join(userDataDir, "Default"), { recursive: true });
|
||||
await fsp.writeFile(path.join(userDataDir, "Local State"), "{", "utf-8"); // invalid JSON
|
||||
@@ -92,7 +95,7 @@ describe("browser chrome profile decoration", () => {
|
||||
"utf-8",
|
||||
);
|
||||
|
||||
decorateClawdProfile(userDataDir, { color: DEFAULT_CLAWD_BROWSER_COLOR });
|
||||
decorateOpenClawProfile(userDataDir, { color: DEFAULT_OPENCLAW_BROWSER_COLOR });
|
||||
|
||||
const localState = await readJson(path.join(userDataDir, "Local State"));
|
||||
expect(typeof localState.profile).toBe("object");
|
||||
@@ -105,7 +108,7 @@ describe("browser chrome profile decoration", () => {
|
||||
});
|
||||
|
||||
it("writes clean exit prefs to avoid restore prompts", async () => {
|
||||
const userDataDir = await fsp.mkdtemp(path.join(os.tmpdir(), "moltbot-chrome-test-"));
|
||||
const userDataDir = await fsp.mkdtemp(path.join(os.tmpdir(), "openclaw-chrome-test-"));
|
||||
try {
|
||||
ensureProfileCleanExit(userDataDir);
|
||||
const prefs = await readJson(path.join(userDataDir, "Default", "Preferences"));
|
||||
@@ -117,14 +120,14 @@ describe("browser chrome profile decoration", () => {
|
||||
});
|
||||
|
||||
it("is idempotent when rerun on an existing profile", async () => {
|
||||
const userDataDir = await fsp.mkdtemp(path.join(os.tmpdir(), "moltbot-chrome-test-"));
|
||||
const userDataDir = await fsp.mkdtemp(path.join(os.tmpdir(), "openclaw-chrome-test-"));
|
||||
try {
|
||||
decorateClawdProfile(userDataDir, { color: DEFAULT_CLAWD_BROWSER_COLOR });
|
||||
decorateClawdProfile(userDataDir, { color: DEFAULT_CLAWD_BROWSER_COLOR });
|
||||
decorateOpenClawProfile(userDataDir, { color: DEFAULT_OPENCLAW_BROWSER_COLOR });
|
||||
decorateOpenClawProfile(userDataDir, { color: DEFAULT_OPENCLAW_BROWSER_COLOR });
|
||||
|
||||
const prefs = await readJson(path.join(userDataDir, "Default", "Preferences"));
|
||||
const profile = prefs.profile as Record<string, unknown>;
|
||||
expect(profile.name).toBe(DEFAULT_CLAWD_BROWSER_PROFILE_NAME);
|
||||
expect(profile.name).toBe(DEFAULT_OPENCLAW_BROWSER_PROFILE_NAME);
|
||||
} finally {
|
||||
await fsp.rm(userDataDir, { recursive: true, force: true });
|
||||
}
|
||||
@@ -231,26 +234,26 @@ describe("browser chrome helpers", () => {
|
||||
await expect(isChromeReachable("http://127.0.0.1:12345", 50)).resolves.toBe(false);
|
||||
});
|
||||
|
||||
it("stopClawdChrome no-ops when process is already killed", async () => {
|
||||
it("stopOpenClawChrome no-ops when process is already killed", async () => {
|
||||
const proc = { killed: true, exitCode: null, kill: vi.fn() };
|
||||
await stopClawdChrome(
|
||||
await stopOpenClawChrome(
|
||||
{
|
||||
proc,
|
||||
cdpPort: 12345,
|
||||
} as unknown as Parameters<typeof stopClawdChrome>[0],
|
||||
} as unknown as Parameters<typeof stopOpenClawChrome>[0],
|
||||
10,
|
||||
);
|
||||
expect(proc.kill).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("stopClawdChrome sends SIGTERM and returns once CDP is down", async () => {
|
||||
it("stopOpenClawChrome sends SIGTERM and returns once CDP is down", async () => {
|
||||
vi.stubGlobal("fetch", vi.fn().mockRejectedValue(new Error("down")));
|
||||
const proc = { killed: false, exitCode: null, kill: vi.fn() };
|
||||
await stopClawdChrome(
|
||||
await stopOpenClawChrome(
|
||||
{
|
||||
proc,
|
||||
cdpPort: 12345,
|
||||
} as unknown as Parameters<typeof stopClawdChrome>[0],
|
||||
} as unknown as Parameters<typeof stopOpenClawChrome>[0],
|
||||
10,
|
||||
);
|
||||
expect(proc.kill).toHaveBeenCalledWith("SIGTERM");
|
||||
|
||||
@@ -14,12 +14,15 @@ import {
|
||||
resolveBrowserExecutableForPlatform,
|
||||
} from "./chrome.executables.js";
|
||||
import {
|
||||
decorateClawdProfile,
|
||||
decorateOpenClawProfile,
|
||||
ensureProfileCleanExit,
|
||||
isProfileDecorated,
|
||||
} from "./chrome.profile-decoration.js";
|
||||
import type { ResolvedBrowserConfig, ResolvedBrowserProfile } from "./config.js";
|
||||
import { DEFAULT_CLAWD_BROWSER_COLOR, DEFAULT_CLAWD_BROWSER_PROFILE_NAME } from "./constants.js";
|
||||
import {
|
||||
DEFAULT_OPENCLAW_BROWSER_COLOR,
|
||||
DEFAULT_OPENCLAW_BROWSER_PROFILE_NAME,
|
||||
} from "./constants.js";
|
||||
|
||||
const log = createSubsystemLogger("browser").child("chrome");
|
||||
|
||||
@@ -31,7 +34,7 @@ export {
|
||||
resolveBrowserExecutableForPlatform,
|
||||
} from "./chrome.executables.js";
|
||||
export {
|
||||
decorateClawdProfile,
|
||||
decorateOpenClawProfile,
|
||||
ensureProfileCleanExit,
|
||||
isProfileDecorated,
|
||||
} from "./chrome.profile-decoration.js";
|
||||
@@ -57,7 +60,7 @@ function resolveBrowserExecutable(resolved: ResolvedBrowserConfig): BrowserExecu
|
||||
return resolveBrowserExecutableForPlatform(resolved, process.platform);
|
||||
}
|
||||
|
||||
export function resolveClawdUserDataDir(profileName = DEFAULT_CLAWD_BROWSER_PROFILE_NAME) {
|
||||
export function resolveOpenClawUserDataDir(profileName = DEFAULT_OPENCLAW_BROWSER_PROFILE_NAME) {
|
||||
return path.join(CONFIG_DIR, "browser", profileName, "user-data");
|
||||
}
|
||||
|
||||
@@ -150,7 +153,7 @@ export async function isChromeCdpReady(
|
||||
return await canOpenWebSocket(wsUrl, handshakeTimeoutMs);
|
||||
}
|
||||
|
||||
export async function launchClawdChrome(
|
||||
export async function launchOpenClawChrome(
|
||||
resolved: ResolvedBrowserConfig,
|
||||
profile: ResolvedBrowserProfile,
|
||||
): Promise<RunningChrome> {
|
||||
@@ -166,13 +169,13 @@ export async function launchClawdChrome(
|
||||
);
|
||||
}
|
||||
|
||||
const userDataDir = resolveClawdUserDataDir(profile.name);
|
||||
const userDataDir = resolveOpenClawUserDataDir(profile.name);
|
||||
fs.mkdirSync(userDataDir, { recursive: true });
|
||||
|
||||
const needsDecorate = !isProfileDecorated(
|
||||
userDataDir,
|
||||
profile.name,
|
||||
(profile.color ?? DEFAULT_CLAWD_BROWSER_COLOR).toUpperCase(),
|
||||
(profile.color ?? DEFAULT_OPENCLAW_BROWSER_COLOR).toUpperCase(),
|
||||
);
|
||||
|
||||
// First launch to create preference files if missing, then decorate and relaunch.
|
||||
@@ -246,20 +249,20 @@ export async function launchClawdChrome(
|
||||
|
||||
if (needsDecorate) {
|
||||
try {
|
||||
decorateClawdProfile(userDataDir, {
|
||||
decorateOpenClawProfile(userDataDir, {
|
||||
name: profile.name,
|
||||
color: profile.color,
|
||||
});
|
||||
log.info(`🦞 clawd browser profile decorated (${profile.color})`);
|
||||
log.info(`🦞 openclaw browser profile decorated (${profile.color})`);
|
||||
} catch (err) {
|
||||
log.warn(`clawd browser profile decoration failed: ${String(err)}`);
|
||||
log.warn(`openclaw browser profile decoration failed: ${String(err)}`);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
ensureProfileCleanExit(userDataDir);
|
||||
} catch (err) {
|
||||
log.warn(`clawd browser clean-exit prefs failed: ${String(err)}`);
|
||||
log.warn(`openclaw browser clean-exit prefs failed: ${String(err)}`);
|
||||
}
|
||||
|
||||
const proc = spawnOnce();
|
||||
@@ -283,7 +286,7 @@ export async function launchClawdChrome(
|
||||
|
||||
const pid = proc.pid ?? -1;
|
||||
log.info(
|
||||
`🦞 clawd browser started (${exe.kind}) profile "${profile.name}" on 127.0.0.1:${profile.cdpPort} (pid ${pid})`,
|
||||
`🦞 openclaw browser started (${exe.kind}) profile "${profile.name}" on 127.0.0.1:${profile.cdpPort} (pid ${pid})`,
|
||||
);
|
||||
|
||||
return {
|
||||
@@ -296,7 +299,7 @@ export async function launchClawdChrome(
|
||||
};
|
||||
}
|
||||
|
||||
export async function stopClawdChrome(running: RunningChrome, timeoutMs = 2500) {
|
||||
export async function stopOpenClawChrome(running: RunningChrome, timeoutMs = 2500) {
|
||||
const proc = running.proc;
|
||||
if (proc.killed) return;
|
||||
try {
|
||||
|
||||
@@ -12,7 +12,7 @@ function isAbsoluteHttp(url: string): boolean {
|
||||
function enhanceBrowserFetchError(url: string, err: unknown, timeoutMs: number): Error {
|
||||
const hint = isAbsoluteHttp(url)
|
||||
? "If this is a sandboxed session, ensure the sandbox browser is running and try again."
|
||||
: `Start (or restart) the Moltbot gateway (Moltbot.app menubar, or \`${formatCliCommand("moltbot gateway")}\`) and try again.`;
|
||||
: `Start (or restart) the OpenClaw gateway (OpenClaw.app menubar, or \`${formatCliCommand("openclaw gateway")}\`) and try again.`;
|
||||
const msg = String(err);
|
||||
const msgLower = msg.toLowerCase();
|
||||
const looksLikeTimeout =
|
||||
@@ -23,10 +23,10 @@ function enhanceBrowserFetchError(url: string, err: unknown, timeoutMs: number):
|
||||
msgLower.includes("aborterror");
|
||||
if (looksLikeTimeout) {
|
||||
return new Error(
|
||||
`Can't reach the clawd browser control service (timed out after ${timeoutMs}ms). ${hint}`,
|
||||
`Can't reach the openclaw browser control service (timed out after ${timeoutMs}ms). ${hint}`,
|
||||
);
|
||||
}
|
||||
return new Error(`Can't reach the clawd browser control service. ${hint} (${msg})`);
|
||||
return new Error(`Can't reach the openclaw browser control service. ${hint} (${msg})`);
|
||||
}
|
||||
|
||||
async function fetchHttpJson<T>(
|
||||
|
||||
@@ -161,7 +161,7 @@ export async function browserCreateProfile(
|
||||
name: string;
|
||||
color?: string;
|
||||
cdpUrl?: string;
|
||||
driver?: "clawd" | "extension";
|
||||
driver?: "openclaw" | "extension";
|
||||
},
|
||||
): Promise<BrowserCreateProfileResult> {
|
||||
return await fetchBrowserJson<BrowserCreateProfileResult>(
|
||||
|
||||
@@ -16,17 +16,17 @@ describe("browser config", () => {
|
||||
expect(profile?.cdpPort).toBe(18792);
|
||||
expect(profile?.cdpUrl).toBe("http://127.0.0.1:18792");
|
||||
|
||||
const clawd = resolveProfile(resolved, "clawd");
|
||||
expect(clawd?.driver).toBe("clawd");
|
||||
expect(clawd?.cdpPort).toBe(18800);
|
||||
expect(clawd?.cdpUrl).toBe("http://127.0.0.1:18800");
|
||||
const openclaw = resolveProfile(resolved, "openclaw");
|
||||
expect(openclaw?.driver).toBe("openclaw");
|
||||
expect(openclaw?.cdpPort).toBe(18800);
|
||||
expect(openclaw?.cdpUrl).toBe("http://127.0.0.1:18800");
|
||||
expect(resolved.remoteCdpTimeoutMs).toBe(1500);
|
||||
expect(resolved.remoteCdpHandshakeTimeoutMs).toBe(3000);
|
||||
});
|
||||
|
||||
it("derives default ports from CLAWDBOT_GATEWAY_PORT when unset", () => {
|
||||
const prev = process.env.CLAWDBOT_GATEWAY_PORT;
|
||||
process.env.CLAWDBOT_GATEWAY_PORT = "19001";
|
||||
it("derives default ports from OPENCLAW_GATEWAY_PORT when unset", () => {
|
||||
const prev = process.env.OPENCLAW_GATEWAY_PORT;
|
||||
process.env.OPENCLAW_GATEWAY_PORT = "19001";
|
||||
try {
|
||||
const resolved = resolveBrowserConfig(undefined);
|
||||
expect(resolved.controlPort).toBe(19003);
|
||||
@@ -35,21 +35,21 @@ describe("browser config", () => {
|
||||
expect(chrome?.cdpPort).toBe(19004);
|
||||
expect(chrome?.cdpUrl).toBe("http://127.0.0.1:19004");
|
||||
|
||||
const clawd = resolveProfile(resolved, "clawd");
|
||||
expect(clawd?.cdpPort).toBe(19012);
|
||||
expect(clawd?.cdpUrl).toBe("http://127.0.0.1:19012");
|
||||
const openclaw = resolveProfile(resolved, "openclaw");
|
||||
expect(openclaw?.cdpPort).toBe(19012);
|
||||
expect(openclaw?.cdpUrl).toBe("http://127.0.0.1:19012");
|
||||
} finally {
|
||||
if (prev === undefined) {
|
||||
delete process.env.CLAWDBOT_GATEWAY_PORT;
|
||||
delete process.env.OPENCLAW_GATEWAY_PORT;
|
||||
} else {
|
||||
process.env.CLAWDBOT_GATEWAY_PORT = prev;
|
||||
process.env.OPENCLAW_GATEWAY_PORT = prev;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("derives default ports from gateway.port when env is unset", () => {
|
||||
const prev = process.env.CLAWDBOT_GATEWAY_PORT;
|
||||
delete process.env.CLAWDBOT_GATEWAY_PORT;
|
||||
const prev = process.env.OPENCLAW_GATEWAY_PORT;
|
||||
delete process.env.OPENCLAW_GATEWAY_PORT;
|
||||
try {
|
||||
const resolved = resolveBrowserConfig(undefined, { gateway: { port: 19011 } });
|
||||
expect(resolved.controlPort).toBe(19013);
|
||||
@@ -58,14 +58,14 @@ describe("browser config", () => {
|
||||
expect(chrome?.cdpPort).toBe(19014);
|
||||
expect(chrome?.cdpUrl).toBe("http://127.0.0.1:19014");
|
||||
|
||||
const clawd = resolveProfile(resolved, "clawd");
|
||||
expect(clawd?.cdpPort).toBe(19022);
|
||||
expect(clawd?.cdpUrl).toBe("http://127.0.0.1:19022");
|
||||
const openclaw = resolveProfile(resolved, "openclaw");
|
||||
expect(openclaw?.cdpPort).toBe(19022);
|
||||
expect(openclaw?.cdpUrl).toBe("http://127.0.0.1:19022");
|
||||
} finally {
|
||||
if (prev === undefined) {
|
||||
delete process.env.CLAWDBOT_GATEWAY_PORT;
|
||||
delete process.env.OPENCLAW_GATEWAY_PORT;
|
||||
} else {
|
||||
process.env.CLAWDBOT_GATEWAY_PORT = prev;
|
||||
process.env.OPENCLAW_GATEWAY_PORT = prev;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -97,7 +97,7 @@ describe("browser config", () => {
|
||||
const resolved = resolveBrowserConfig({
|
||||
cdpUrl: "http://example.com:9222",
|
||||
});
|
||||
const profile = resolveProfile(resolved, "clawd");
|
||||
const profile = resolveProfile(resolved, "openclaw");
|
||||
expect(profile?.cdpIsLoopback).toBe(false);
|
||||
});
|
||||
|
||||
@@ -105,7 +105,7 @@ describe("browser config", () => {
|
||||
const resolved = resolveBrowserConfig({
|
||||
cdpUrl: "http://example.com:9222",
|
||||
});
|
||||
const profile = resolveProfile(resolved, "clawd");
|
||||
const profile = resolveProfile(resolved, "openclaw");
|
||||
expect(profile?.cdpPort).toBe(9222);
|
||||
expect(profile?.cdpUrl).toBe("http://example.com:9222");
|
||||
expect(profile?.cdpIsLoopback).toBe(false);
|
||||
@@ -143,10 +143,10 @@ describe("browser config", () => {
|
||||
it("does not add the built-in chrome extension profile if the derived relay port is already used", () => {
|
||||
const resolved = resolveBrowserConfig({
|
||||
profiles: {
|
||||
clawd: { cdpPort: 18792, color: "#FF4500" },
|
||||
openclaw: { cdpPort: 18792, color: "#FF4500" },
|
||||
},
|
||||
});
|
||||
expect(resolveProfile(resolved, "chrome")).toBe(null);
|
||||
expect(resolved.defaultProfile).toBe("clawd");
|
||||
expect(resolved.defaultProfile).toBe("openclaw");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { BrowserConfig, BrowserProfileConfig, MoltbotConfig } from "../config/config.js";
|
||||
import type { BrowserConfig, BrowserProfileConfig, OpenClawConfig } from "../config/config.js";
|
||||
import {
|
||||
deriveDefaultBrowserCdpPortRange,
|
||||
deriveDefaultBrowserControlPort,
|
||||
@@ -6,11 +6,11 @@ import {
|
||||
} from "../config/port-defaults.js";
|
||||
import { resolveGatewayPort } from "../config/paths.js";
|
||||
import {
|
||||
DEFAULT_CLAWD_BROWSER_COLOR,
|
||||
DEFAULT_CLAWD_BROWSER_ENABLED,
|
||||
DEFAULT_OPENCLAW_BROWSER_COLOR,
|
||||
DEFAULT_OPENCLAW_BROWSER_ENABLED,
|
||||
DEFAULT_BROWSER_EVALUATE_ENABLED,
|
||||
DEFAULT_BROWSER_DEFAULT_PROFILE_NAME,
|
||||
DEFAULT_CLAWD_BROWSER_PROFILE_NAME,
|
||||
DEFAULT_OPENCLAW_BROWSER_PROFILE_NAME,
|
||||
} from "./constants.js";
|
||||
import { CDP_PORT_RANGE_START, getUsedPorts } from "./profiles.js";
|
||||
|
||||
@@ -39,7 +39,7 @@ export type ResolvedBrowserProfile = {
|
||||
cdpHost: string;
|
||||
cdpIsLoopback: boolean;
|
||||
color: string;
|
||||
driver: "clawd" | "extension";
|
||||
driver: "openclaw" | "extension";
|
||||
};
|
||||
|
||||
function isLoopbackHost(host: string) {
|
||||
@@ -57,9 +57,9 @@ function isLoopbackHost(host: string) {
|
||||
|
||||
function normalizeHexColor(raw: string | undefined) {
|
||||
const value = (raw ?? "").trim();
|
||||
if (!value) return DEFAULT_CLAWD_BROWSER_COLOR;
|
||||
if (!value) return DEFAULT_OPENCLAW_BROWSER_COLOR;
|
||||
const normalized = value.startsWith("#") ? value : `#${value}`;
|
||||
if (!/^#[0-9a-fA-F]{6}$/.test(normalized)) return DEFAULT_CLAWD_BROWSER_COLOR;
|
||||
if (!/^#[0-9a-fA-F]{6}$/.test(normalized)) return DEFAULT_OPENCLAW_BROWSER_COLOR;
|
||||
return normalized.toUpperCase();
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ export function parseHttpUrl(raw: string, label: string) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the default "clawd" profile exists in the profiles map.
|
||||
* Ensure the default "openclaw" profile exists in the profiles map.
|
||||
* Auto-creates it with the legacy CDP port (from browser.cdpUrl) or first port if missing.
|
||||
*/
|
||||
function ensureDefaultProfile(
|
||||
@@ -104,8 +104,8 @@ function ensureDefaultProfile(
|
||||
derivedDefaultCdpPort?: number,
|
||||
): Record<string, BrowserProfileConfig> {
|
||||
const result = { ...profiles };
|
||||
if (!result[DEFAULT_CLAWD_BROWSER_PROFILE_NAME]) {
|
||||
result[DEFAULT_CLAWD_BROWSER_PROFILE_NAME] = {
|
||||
if (!result[DEFAULT_OPENCLAW_BROWSER_PROFILE_NAME]) {
|
||||
result[DEFAULT_OPENCLAW_BROWSER_PROFILE_NAME] = {
|
||||
cdpPort: legacyCdpPort ?? derivedDefaultCdpPort ?? CDP_PORT_RANGE_START,
|
||||
color: defaultColor,
|
||||
};
|
||||
@@ -116,7 +116,7 @@ function ensureDefaultProfile(
|
||||
/**
|
||||
* Ensure a built-in "chrome" profile exists for the Chrome extension relay.
|
||||
*
|
||||
* Note: this is a Moltbot browser profile (routing config), not a Chrome user profile.
|
||||
* Note: this is an OpenClaw browser profile (routing config), not a Chrome user profile.
|
||||
* It points at the local relay CDP endpoint (controlPort + 1).
|
||||
*/
|
||||
function ensureDefaultChromeExtensionProfile(
|
||||
@@ -128,7 +128,7 @@ function ensureDefaultChromeExtensionProfile(
|
||||
const relayPort = controlPort + 1;
|
||||
if (!Number.isFinite(relayPort) || relayPort <= 0 || relayPort > 65535) return result;
|
||||
// Avoid adding the built-in profile if the derived relay port is already used by another profile
|
||||
// (legacy single-profile configs may use controlPort+1 for clawd CDP).
|
||||
// (legacy single-profile configs may use controlPort+1 for openclaw/openclaw CDP).
|
||||
if (getUsedPorts(result).has(relayPort)) return result;
|
||||
result.chrome = {
|
||||
driver: "extension",
|
||||
@@ -139,9 +139,9 @@ function ensureDefaultChromeExtensionProfile(
|
||||
}
|
||||
export function resolveBrowserConfig(
|
||||
cfg: BrowserConfig | undefined,
|
||||
rootConfig?: MoltbotConfig,
|
||||
rootConfig?: OpenClawConfig,
|
||||
): ResolvedBrowserConfig {
|
||||
const enabled = cfg?.enabled ?? DEFAULT_CLAWD_BROWSER_ENABLED;
|
||||
const enabled = cfg?.enabled ?? DEFAULT_OPENCLAW_BROWSER_ENABLED;
|
||||
const evaluateEnabled = cfg?.evaluateEnabled ?? DEFAULT_BROWSER_EVALUATE_ENABLED;
|
||||
const gatewayPort = resolveGatewayPort(rootConfig);
|
||||
const controlPort = deriveDefaultBrowserControlPort(gatewayPort ?? DEFAULT_BROWSER_CONTROL_PORT);
|
||||
@@ -196,7 +196,7 @@ export function resolveBrowserConfig(
|
||||
defaultProfileFromConfig ??
|
||||
(profiles[DEFAULT_BROWSER_DEFAULT_PROFILE_NAME]
|
||||
? DEFAULT_BROWSER_DEFAULT_PROFILE_NAME
|
||||
: DEFAULT_CLAWD_BROWSER_PROFILE_NAME);
|
||||
: DEFAULT_OPENCLAW_BROWSER_PROFILE_NAME);
|
||||
|
||||
return {
|
||||
enabled,
|
||||
@@ -232,7 +232,7 @@ export function resolveProfile(
|
||||
let cdpHost = resolved.cdpHost;
|
||||
let cdpPort = profile.cdpPort ?? 0;
|
||||
let cdpUrl = "";
|
||||
const driver = profile.driver === "extension" ? "extension" : "clawd";
|
||||
const driver = profile.driver === "extension" ? "extension" : "openclaw";
|
||||
|
||||
if (rawProfileUrl) {
|
||||
const parsed = parseHttpUrl(rawProfileUrl, `browser.profiles.${profileName}.cdpUrl`);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
export const DEFAULT_CLAWD_BROWSER_ENABLED = true;
|
||||
export const DEFAULT_OPENCLAW_BROWSER_ENABLED = true;
|
||||
export const DEFAULT_BROWSER_EVALUATE_ENABLED = true;
|
||||
export const DEFAULT_CLAWD_BROWSER_COLOR = "#FF4500";
|
||||
export const DEFAULT_CLAWD_BROWSER_PROFILE_NAME = "clawd";
|
||||
export const DEFAULT_OPENCLAW_BROWSER_COLOR = "#FF4500";
|
||||
export const DEFAULT_OPENCLAW_BROWSER_PROFILE_NAME = "openclaw";
|
||||
export const DEFAULT_BROWSER_DEFAULT_PROFILE_NAME = "chrome";
|
||||
export const DEFAULT_AI_SNAPSHOT_MAX_CHARS = 80_000;
|
||||
export const DEFAULT_AI_SNAPSHOT_EFFICIENT_MAX_CHARS = 10_000;
|
||||
|
||||
@@ -65,7 +65,7 @@ export async function stopBrowserControlService(): Promise<void> {
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
logService.warn(`clawd browser stop failed: ${String(err)}`);
|
||||
logService.warn(`openclaw browser stop failed: ${String(err)}`);
|
||||
}
|
||||
|
||||
state = null;
|
||||
|
||||
@@ -231,9 +231,9 @@ export async function ensureChromeExtensionRelayServer(opts: {
|
||||
case "Browser.getVersion":
|
||||
return {
|
||||
protocolVersion: "1.3",
|
||||
product: "Chrome/Moltbot-Extension-Relay",
|
||||
product: "Chrome/OpenClaw-Extension-Relay",
|
||||
revision: "0",
|
||||
userAgent: "Moltbot-Extension-Relay",
|
||||
userAgent: "OpenClaw-Extension-Relay",
|
||||
jsVersion: "V8",
|
||||
};
|
||||
case "Browser.setDownloadBehavior":
|
||||
@@ -318,7 +318,7 @@ export async function ensureChromeExtensionRelayServer(opts: {
|
||||
(req.method === "GET" || req.method === "PUT")
|
||||
) {
|
||||
const payload: Record<string, unknown> = {
|
||||
Browser: "Moltbot/extension-relay",
|
||||
Browser: "OpenClaw/extension-relay",
|
||||
"Protocol-Version": "1.3",
|
||||
};
|
||||
// Only advertise the WS URL if a real extension is connected.
|
||||
|
||||
@@ -21,11 +21,11 @@ vi.mock("./trash.js", () => ({
|
||||
}));
|
||||
|
||||
vi.mock("./chrome.js", () => ({
|
||||
resolveClawdUserDataDir: vi.fn(() => "/tmp/clawd-test/clawd/user-data"),
|
||||
resolveOpenClawUserDataDir: vi.fn(() => "/tmp/openclaw-test/openclaw/user-data"),
|
||||
}));
|
||||
|
||||
import { loadConfig, writeConfigFile } from "../config/config.js";
|
||||
import { resolveClawdUserDataDir } from "./chrome.js";
|
||||
import { resolveOpenClawUserDataDir } from "./chrome.js";
|
||||
import { movePathToTrash } from "./trash.js";
|
||||
|
||||
function createCtx(resolved: BrowserServerState["resolved"]) {
|
||||
@@ -101,9 +101,9 @@ describe("BrowserProfilesService", () => {
|
||||
|
||||
vi.mocked(loadConfig).mockReturnValue({
|
||||
browser: {
|
||||
defaultProfile: "clawd",
|
||||
defaultProfile: "openclaw",
|
||||
profiles: {
|
||||
clawd: { cdpPort: 18800, color: "#FF4500" },
|
||||
openclaw: { cdpPort: 18800, color: "#FF4500" },
|
||||
remote: { cdpUrl: "http://10.0.0.42:9222", color: "#0066CC" },
|
||||
},
|
||||
},
|
||||
@@ -127,18 +127,18 @@ describe("BrowserProfilesService", () => {
|
||||
|
||||
vi.mocked(loadConfig).mockReturnValue({
|
||||
browser: {
|
||||
defaultProfile: "clawd",
|
||||
defaultProfile: "openclaw",
|
||||
profiles: {
|
||||
clawd: { cdpPort: 18800, color: "#FF4500" },
|
||||
openclaw: { cdpPort: 18800, color: "#FF4500" },
|
||||
work: { cdpPort: 18801, color: "#0066CC" },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const tempDir = fs.mkdtempSync(path.join("/tmp", "clawd-profile-"));
|
||||
const tempDir = fs.mkdtempSync(path.join("/tmp", "openclaw-profile-"));
|
||||
const userDataDir = path.join(tempDir, "work", "user-data");
|
||||
fs.mkdirSync(path.dirname(userDataDir), { recursive: true });
|
||||
vi.mocked(resolveClawdUserDataDir).mockReturnValue(userDataDir);
|
||||
vi.mocked(resolveOpenClawUserDataDir).mockReturnValue(userDataDir);
|
||||
|
||||
const service = createBrowserProfilesService(ctx);
|
||||
const result = await service.deleteProfile("work");
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
import type { BrowserProfileConfig, MoltbotConfig } from "../config/config.js";
|
||||
import type { BrowserProfileConfig, OpenClawConfig } from "../config/config.js";
|
||||
import { loadConfig, writeConfigFile } from "../config/config.js";
|
||||
import { deriveDefaultBrowserCdpPortRange } from "../config/port-defaults.js";
|
||||
import { DEFAULT_BROWSER_DEFAULT_PROFILE_NAME } from "./constants.js";
|
||||
import { resolveClawdUserDataDir } from "./chrome.js";
|
||||
import { resolveOpenClawUserDataDir } from "./chrome.js";
|
||||
import { parseHttpUrl, resolveProfile } from "./config.js";
|
||||
import {
|
||||
allocateCdpPort,
|
||||
@@ -21,7 +21,7 @@ export type CreateProfileParams = {
|
||||
name: string;
|
||||
color?: string;
|
||||
cdpUrl?: string;
|
||||
driver?: "clawd" | "extension";
|
||||
driver?: "openclaw" | "extension";
|
||||
};
|
||||
|
||||
export type CreateProfileResult = {
|
||||
@@ -93,7 +93,7 @@ export function createBrowserProfilesService(ctx: BrowserRouteContext) {
|
||||
};
|
||||
}
|
||||
|
||||
const nextConfig: MoltbotConfig = {
|
||||
const nextConfig: OpenClawConfig = {
|
||||
...cfg,
|
||||
browser: {
|
||||
...cfg.browser,
|
||||
@@ -153,7 +153,7 @@ export function createBrowserProfilesService(ctx: BrowserRouteContext) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
const userDataDir = resolveClawdUserDataDir(name);
|
||||
const userDataDir = resolveOpenClawUserDataDir(name);
|
||||
const profileDir = path.dirname(userDataDir);
|
||||
if (fs.existsSync(profileDir)) {
|
||||
await movePathToTrash(profileDir);
|
||||
@@ -162,7 +162,7 @@ export function createBrowserProfilesService(ctx: BrowserRouteContext) {
|
||||
}
|
||||
|
||||
const { [name]: _removed, ...remainingProfiles } = profiles;
|
||||
const nextConfig: MoltbotConfig = {
|
||||
const nextConfig: OpenClawConfig = {
|
||||
...cfg,
|
||||
browser: {
|
||||
...cfg.browser,
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
|
||||
describe("profile name validation", () => {
|
||||
it("accepts valid lowercase names", () => {
|
||||
expect(isValidProfileName("clawd")).toBe(true);
|
||||
expect(isValidProfileName("openclaw")).toBe(true);
|
||||
expect(isValidProfileName("work")).toBe(true);
|
||||
expect(isValidProfileName("my-profile")).toBe(true);
|
||||
expect(isValidProfileName("test123")).toBe(true);
|
||||
@@ -109,7 +109,7 @@ describe("getUsedPorts", () => {
|
||||
|
||||
it("extracts ports from profile configs", () => {
|
||||
const profiles = {
|
||||
clawd: { cdpPort: 18792 },
|
||||
openclaw: { cdpPort: 18792 },
|
||||
work: { cdpPort: 18793 },
|
||||
personal: { cdpPort: 18795 },
|
||||
};
|
||||
@@ -147,7 +147,7 @@ describe("port collision prevention", () => {
|
||||
// Raw config shows empty - no ports used
|
||||
expect(usedFromRaw.size).toBe(0);
|
||||
|
||||
// But resolved config has implicit clawd at 18800
|
||||
// But resolved config has implicit openclaw at 18800
|
||||
const resolved = resolveBrowserConfig({});
|
||||
const usedFromResolved = getUsedPorts(resolved.profiles);
|
||||
expect(usedFromResolved.has(CDP_PORT_RANGE_START)).toBe(true);
|
||||
@@ -165,7 +165,7 @@ describe("port collision prevention", () => {
|
||||
// Raw config: first allocation gets 18800
|
||||
expect(buggyAllocatedPort).toBe(CDP_PORT_RANGE_START);
|
||||
|
||||
// Resolved config: includes implicit clawd at 18800
|
||||
// Resolved config: includes implicit openclaw at 18800
|
||||
const resolved = resolveBrowserConfig(rawConfig.browser);
|
||||
const fixedUsedPorts = getUsedPorts(resolved.profiles);
|
||||
const fixedAllocatedPort = allocateCdpPort(fixedUsedPorts);
|
||||
@@ -238,7 +238,7 @@ describe("getUsedColors", () => {
|
||||
|
||||
it("extracts and uppercases colors from profile configs", () => {
|
||||
const profiles = {
|
||||
clawd: { color: "#ff4500" },
|
||||
openclaw: { color: "#ff4500" },
|
||||
work: { color: "#0066CC" },
|
||||
};
|
||||
const used = getUsedColors(profiles);
|
||||
|
||||
@@ -69,7 +69,7 @@ export function getUsedPorts(
|
||||
}
|
||||
|
||||
export const PROFILE_COLORS = [
|
||||
"#FF4500", // Orange-red (clawd default)
|
||||
"#FF4500", // Orange-red (openclaw default)
|
||||
"#0066CC", // Blue
|
||||
"#00AA00", // Green
|
||||
"#9933FF", // Purple
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { describe, it } from "vitest";
|
||||
import { isTruthyEnvValue } from "../infra/env.js";
|
||||
|
||||
const LIVE = isTruthyEnvValue(process.env.LIVE) || isTruthyEnvValue(process.env.CLAWDBOT_LIVE_TEST);
|
||||
const CDP_URL = process.env.CLAWDBOT_LIVE_BROWSER_CDP_URL?.trim() || "";
|
||||
const LIVE = isTruthyEnvValue(process.env.LIVE) || isTruthyEnvValue(process.env.OPENCLAW_LIVE_TEST);
|
||||
const CDP_URL = process.env.OPENCLAW_LIVE_BROWSER_CDP_URL?.trim() || "";
|
||||
const describeLive = LIVE && CDP_URL ? describe : describe.skip;
|
||||
|
||||
async function waitFor(
|
||||
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
function buildTempDownloadPath(fileName: string): string {
|
||||
const id = crypto.randomUUID();
|
||||
const safeName = fileName.trim() ? fileName.trim() : "download.bin";
|
||||
return path.join("/tmp/moltbot/downloads", `${id}-${safeName}`);
|
||||
return path.join("/tmp/openclaw/downloads", `${id}-${safeName}`);
|
||||
}
|
||||
|
||||
function createPageDownloadWaiter(page: Page, timeoutMs: number) {
|
||||
|
||||
@@ -427,11 +427,11 @@ export async function screenshotWithLabelsViaPlaywright(opts: {
|
||||
try {
|
||||
if (boxes.length > 0) {
|
||||
await page.evaluate((labels) => {
|
||||
const existing = document.querySelectorAll("[data-moltbot-labels]");
|
||||
const existing = document.querySelectorAll("[data-openclaw-labels]");
|
||||
existing.forEach((el) => el.remove());
|
||||
|
||||
const root = document.createElement("div");
|
||||
root.setAttribute("data-moltbot-labels", "1");
|
||||
root.setAttribute("data-openclaw-labels", "1");
|
||||
root.style.position = "fixed";
|
||||
root.style.left = "0";
|
||||
root.style.top = "0";
|
||||
@@ -445,7 +445,7 @@ export async function screenshotWithLabelsViaPlaywright(opts: {
|
||||
|
||||
for (const label of labels) {
|
||||
const box = document.createElement("div");
|
||||
box.setAttribute("data-moltbot-labels", "1");
|
||||
box.setAttribute("data-openclaw-labels", "1");
|
||||
box.style.position = "absolute";
|
||||
box.style.left = `${label.x}px`;
|
||||
box.style.top = `${label.y}px`;
|
||||
@@ -455,7 +455,7 @@ export async function screenshotWithLabelsViaPlaywright(opts: {
|
||||
box.style.boxSizing = "border-box";
|
||||
|
||||
const tag = document.createElement("div");
|
||||
tag.setAttribute("data-moltbot-labels", "1");
|
||||
tag.setAttribute("data-openclaw-labels", "1");
|
||||
tag.textContent = label.ref;
|
||||
tag.style.position = "absolute";
|
||||
tag.style.left = `${label.x}px`;
|
||||
@@ -482,7 +482,7 @@ export async function screenshotWithLabelsViaPlaywright(opts: {
|
||||
} finally {
|
||||
await page
|
||||
.evaluate(() => {
|
||||
const existing = document.querySelectorAll("[data-moltbot-labels]");
|
||||
const existing = document.querySelectorAll("[data-openclaw-labels]");
|
||||
existing.forEach((el) => el.remove());
|
||||
})
|
||||
.catch(() => {});
|
||||
|
||||
@@ -66,7 +66,7 @@ export async function responseBodyViaPlaywright(opts: {
|
||||
cleanup();
|
||||
reject(
|
||||
new Error(
|
||||
`Response not found for url pattern "${pattern}". Run '${formatCliCommand("moltbot browser requests")}' to inspect recent network activity.`,
|
||||
`Response not found for url pattern "${pattern}". Run '${formatCliCommand("openclaw browser requests")}' to inspect recent network activity.`,
|
||||
),
|
||||
);
|
||||
}, timeout);
|
||||
|
||||
@@ -217,7 +217,7 @@ export function registerBrowserAgentActRoutes(
|
||||
403,
|
||||
[
|
||||
"wait --fn is disabled by config (browser.evaluateEnabled=false).",
|
||||
"Docs: /gateway/configuration#browser-clawd-managed-browser",
|
||||
"Docs: /gateway/configuration#browser-openclaw-managed-browser",
|
||||
].join("\n"),
|
||||
);
|
||||
}
|
||||
@@ -257,7 +257,7 @@ export function registerBrowserAgentActRoutes(
|
||||
403,
|
||||
[
|
||||
"act:evaluate is disabled by config (browser.evaluateEnabled=false).",
|
||||
"Docs: /gateway/configuration#browser-clawd-managed-browser",
|
||||
"Docs: /gateway/configuration#browser-openclaw-managed-browser",
|
||||
].join("\n"),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ export function registerBrowserAgentDebugRoutes(
|
||||
const pw = await requirePwAi(res, "trace stop");
|
||||
if (!pw) return;
|
||||
const id = crypto.randomUUID();
|
||||
const dir = "/tmp/moltbot";
|
||||
const dir = "/tmp/openclaw";
|
||||
await fs.mkdir(dir, { recursive: true });
|
||||
const tracePath = out.trim() || path.join(dir, `browser-trace-${id}.zip`);
|
||||
await pw.traceStopViaPlaywright({
|
||||
|
||||
@@ -127,7 +127,7 @@ export function registerBrowserBasicRoutes(app: BrowserRouteRegistrar, ctx: Brow
|
||||
const color = toStringOrEmpty((req.body as { color?: unknown })?.color);
|
||||
const cdpUrl = toStringOrEmpty((req.body as { cdpUrl?: unknown })?.cdpUrl);
|
||||
const driver = toStringOrEmpty((req.body as { driver?: unknown })?.driver) as
|
||||
| "clawd"
|
||||
| "openclaw"
|
||||
| "extension"
|
||||
| "";
|
||||
|
||||
|
||||
@@ -6,11 +6,11 @@ import { createBrowserRouteContext } from "./server-context.js";
|
||||
vi.mock("./chrome.js", () => ({
|
||||
isChromeCdpReady: vi.fn(async () => true),
|
||||
isChromeReachable: vi.fn(async () => true),
|
||||
launchClawdChrome: vi.fn(async () => {
|
||||
launchOpenClawChrome: vi.fn(async () => {
|
||||
throw new Error("unexpected launch");
|
||||
}),
|
||||
resolveClawdUserDataDir: vi.fn(() => "/tmp/clawd"),
|
||||
stopClawdChrome: vi.fn(async () => {}),
|
||||
resolveOpenClawUserDataDir: vi.fn(() => "/tmp/openclaw"),
|
||||
stopOpenClawChrome: vi.fn(async () => {}),
|
||||
}));
|
||||
|
||||
describe("browser server-context ensureTabAvailable", () => {
|
||||
@@ -78,7 +78,7 @@ describe("browser server-context ensureTabAvailable", () => {
|
||||
cdpPort: 18792,
|
||||
color: "#00AA00",
|
||||
},
|
||||
clawd: { cdpPort: 18800, color: "#FF4500" },
|
||||
openclaw: { cdpPort: 18800, color: "#FF4500" },
|
||||
},
|
||||
},
|
||||
profiles: new Map(),
|
||||
@@ -135,7 +135,7 @@ describe("browser server-context ensureTabAvailable", () => {
|
||||
cdpPort: 18792,
|
||||
color: "#00AA00",
|
||||
},
|
||||
clawd: { cdpPort: 18800, color: "#FF4500" },
|
||||
openclaw: { cdpPort: 18800, color: "#FF4500" },
|
||||
},
|
||||
},
|
||||
profiles: new Map(),
|
||||
@@ -182,7 +182,7 @@ describe("browser server-context ensureTabAvailable", () => {
|
||||
cdpPort: 18792,
|
||||
color: "#00AA00",
|
||||
},
|
||||
clawd: { cdpPort: 18800, color: "#FF4500" },
|
||||
openclaw: { cdpPort: 18800, color: "#FF4500" },
|
||||
},
|
||||
},
|
||||
profiles: new Map(),
|
||||
|
||||
@@ -5,15 +5,15 @@ import type { BrowserServerState } from "./server-context.js";
|
||||
vi.mock("./chrome.js", () => ({
|
||||
isChromeCdpReady: vi.fn(async () => true),
|
||||
isChromeReachable: vi.fn(async () => true),
|
||||
launchClawdChrome: vi.fn(async () => {
|
||||
launchOpenClawChrome: vi.fn(async () => {
|
||||
throw new Error("unexpected launch");
|
||||
}),
|
||||
resolveClawdUserDataDir: vi.fn(() => "/tmp/clawd"),
|
||||
stopClawdChrome: vi.fn(async () => {}),
|
||||
resolveOpenClawUserDataDir: vi.fn(() => "/tmp/openclaw"),
|
||||
stopOpenClawChrome: vi.fn(async () => {}),
|
||||
}));
|
||||
|
||||
function makeState(
|
||||
profile: "remote" | "clawd",
|
||||
profile: "remote" | "openclaw",
|
||||
): BrowserServerState & { profiles: Map<string, { lastTargetId?: string | null }> } {
|
||||
return {
|
||||
// biome-ignore lint/suspicious/noExplicitAny: test stub
|
||||
@@ -38,7 +38,7 @@ function makeState(
|
||||
cdpPort: 443,
|
||||
color: "#00AA00",
|
||||
},
|
||||
clawd: { cdpPort: 18800, color: "#FF4500" },
|
||||
openclaw: { cdpPort: 18800, color: "#FF4500" },
|
||||
},
|
||||
},
|
||||
profiles: new Map(),
|
||||
@@ -272,12 +272,12 @@ describe("browser server-context tab selection state", () => {
|
||||
global.fetch = fetchMock;
|
||||
|
||||
const { createBrowserRouteContext } = await import("./server-context.js");
|
||||
const state = makeState("clawd");
|
||||
const state = makeState("openclaw");
|
||||
const ctx = createBrowserRouteContext({ getState: () => state });
|
||||
const clawd = ctx.forProfile("clawd");
|
||||
const openclaw = ctx.forProfile("openclaw");
|
||||
|
||||
const opened = await clawd.openTab("https://created.example");
|
||||
const opened = await openclaw.openTab("https://created.example");
|
||||
expect(opened.targetId).toBe("CREATED");
|
||||
expect(state.profiles.get("clawd")?.lastTargetId).toBe("CREATED");
|
||||
expect(state.profiles.get("openclaw")?.lastTargetId).toBe("CREATED");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,9 +4,9 @@ import { appendCdpPath, createTargetViaCdp, getHeadersWithAuth, normalizeCdpWsUr
|
||||
import {
|
||||
isChromeCdpReady,
|
||||
isChromeReachable,
|
||||
launchClawdChrome,
|
||||
resolveClawdUserDataDir,
|
||||
stopClawdChrome,
|
||||
launchOpenClawChrome,
|
||||
resolveOpenClawUserDataDir,
|
||||
stopOpenClawChrome,
|
||||
} from "./chrome.js";
|
||||
import type { ResolvedBrowserProfile } from "./config.js";
|
||||
import { resolveProfile } from "./config.js";
|
||||
@@ -285,7 +285,7 @@ function createProfileContext(
|
||||
if (await isReachable(600)) return;
|
||||
// Relay server is up, but no attached tab yet. Prompt user to attach.
|
||||
throw new Error(
|
||||
`Chrome extension relay is running, but no tab is connected. Click the Moltbot Chrome extension icon on a tab to attach it (profile "${profile.name}").`,
|
||||
`Chrome extension relay is running, but no tab is connected. Click the OpenClaw Chrome extension icon on a tab to attach it (profile "${profile.name}").`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -301,7 +301,7 @@ function createProfileContext(
|
||||
: `Browser attachOnly is enabled and profile "${profile.name}" is not running.`,
|
||||
);
|
||||
}
|
||||
const launched = await launchClawdChrome(current.resolved, profile);
|
||||
const launched = await launchOpenClawChrome(current.resolved, profile);
|
||||
attachRunning(launched);
|
||||
return;
|
||||
}
|
||||
@@ -312,7 +312,7 @@ function createProfileContext(
|
||||
// HTTP responds but WebSocket fails - port in use by something else
|
||||
if (!profileState.running) {
|
||||
throw new Error(
|
||||
`Port ${profile.cdpPort} is in use for profile "${profile.name}" but not by moltbot. ` +
|
||||
`Port ${profile.cdpPort} is in use for profile "${profile.name}" but not by openclaw. ` +
|
||||
`Run action=reset-profile profile=${profile.name} to kill the process.`,
|
||||
);
|
||||
}
|
||||
@@ -330,10 +330,10 @@ function createProfileContext(
|
||||
);
|
||||
}
|
||||
|
||||
await stopClawdChrome(profileState.running);
|
||||
await stopOpenClawChrome(profileState.running);
|
||||
setProfileRunning(null);
|
||||
|
||||
const relaunched = await launchClawdChrome(current.resolved, profile);
|
||||
const relaunched = await launchOpenClawChrome(current.resolved, profile);
|
||||
attachRunning(relaunched);
|
||||
|
||||
if (!(await isReachable(600))) {
|
||||
@@ -351,7 +351,7 @@ function createProfileContext(
|
||||
if (profile.driver === "extension") {
|
||||
throw new Error(
|
||||
`tab not found (no attached Chrome tabs for profile "${profile.name}"). ` +
|
||||
"Click the Moltbot Browser Relay toolbar icon on the tab you want to control (badge ON).",
|
||||
"Click the OpenClaw Browser Relay toolbar icon on the tab you want to control (badge ON).",
|
||||
);
|
||||
}
|
||||
await openTab("about:blank");
|
||||
@@ -464,7 +464,7 @@ function createProfileContext(
|
||||
}
|
||||
const profileState = getProfileState();
|
||||
if (!profileState.running) return { stopped: false };
|
||||
await stopClawdChrome(profileState.running);
|
||||
await stopOpenClawChrome(profileState.running);
|
||||
setProfileRunning(null);
|
||||
return { stopped: true };
|
||||
};
|
||||
@@ -479,7 +479,7 @@ function createProfileContext(
|
||||
`reset-profile is only supported for local profiles (profile "${profile.name}" is remote).`,
|
||||
);
|
||||
}
|
||||
const userDataDir = resolveClawdUserDataDir(profile.name);
|
||||
const userDataDir = resolveOpenClawUserDataDir(profile.name);
|
||||
const profileState = getProfileState();
|
||||
|
||||
const httpReachable = await isHttpReachable(300);
|
||||
|
||||
@@ -94,9 +94,9 @@ vi.mock("../config/config.js", async (importOriginal) => {
|
||||
color: "#FF4500",
|
||||
attachOnly: cfgAttachOnly,
|
||||
headless: true,
|
||||
defaultProfile: "clawd",
|
||||
defaultProfile: "openclaw",
|
||||
profiles: {
|
||||
clawd: { cdpPort: testPort + 1, color: "#FF4500" },
|
||||
openclaw: { cdpPort: testPort + 1, color: "#FF4500" },
|
||||
},
|
||||
},
|
||||
}),
|
||||
@@ -108,20 +108,20 @@ const launchCalls = vi.hoisted(() => [] as Array<{ port: number }>);
|
||||
vi.mock("./chrome.js", () => ({
|
||||
isChromeCdpReady: vi.fn(async () => reachable),
|
||||
isChromeReachable: vi.fn(async () => reachable),
|
||||
launchClawdChrome: vi.fn(async (_resolved: unknown, profile: { cdpPort: number }) => {
|
||||
launchOpenClawChrome: vi.fn(async (_resolved: unknown, profile: { cdpPort: number }) => {
|
||||
launchCalls.push({ port: profile.cdpPort });
|
||||
reachable = true;
|
||||
return {
|
||||
pid: 123,
|
||||
exe: { kind: "chrome", path: "/fake/chrome" },
|
||||
userDataDir: "/tmp/clawd",
|
||||
userDataDir: "/tmp/openclaw",
|
||||
cdpPort: profile.cdpPort,
|
||||
startedAt: Date.now(),
|
||||
proc,
|
||||
};
|
||||
}),
|
||||
resolveClawdUserDataDir: vi.fn(() => "/tmp/clawd"),
|
||||
stopClawdChrome: vi.fn(async () => {
|
||||
resolveOpenClawUserDataDir: vi.fn(() => "/tmp/openclaw"),
|
||||
stopOpenClawChrome: vi.fn(async () => {
|
||||
reachable = false;
|
||||
}),
|
||||
}));
|
||||
@@ -200,8 +200,8 @@ describe("browser control server", () => {
|
||||
|
||||
testPort = await getFreePort();
|
||||
cdpBaseUrl = `http://127.0.0.1:${testPort + 1}`;
|
||||
prevGatewayPort = process.env.CLAWDBOT_GATEWAY_PORT;
|
||||
process.env.CLAWDBOT_GATEWAY_PORT = String(testPort - 2);
|
||||
prevGatewayPort = process.env.OPENCLAW_GATEWAY_PORT;
|
||||
process.env.OPENCLAW_GATEWAY_PORT = String(testPort - 2);
|
||||
|
||||
// Minimal CDP JSON endpoints used by the server.
|
||||
let putNewCalls = 0;
|
||||
@@ -254,9 +254,9 @@ describe("browser control server", () => {
|
||||
vi.unstubAllGlobals();
|
||||
vi.restoreAllMocks();
|
||||
if (prevGatewayPort === undefined) {
|
||||
delete process.env.CLAWDBOT_GATEWAY_PORT;
|
||||
delete process.env.OPENCLAW_GATEWAY_PORT;
|
||||
} else {
|
||||
process.env.CLAWDBOT_GATEWAY_PORT = prevGatewayPort;
|
||||
process.env.OPENCLAW_GATEWAY_PORT = prevGatewayPort;
|
||||
}
|
||||
const { stopBrowserControlServer } = await import("./server.js");
|
||||
await stopBrowserControlServer();
|
||||
|
||||
@@ -93,9 +93,9 @@ vi.mock("../config/config.js", async (importOriginal) => {
|
||||
color: "#FF4500",
|
||||
attachOnly: cfgAttachOnly,
|
||||
headless: true,
|
||||
defaultProfile: "clawd",
|
||||
defaultProfile: "openclaw",
|
||||
profiles: {
|
||||
clawd: { cdpPort: testPort + 1, color: "#FF4500" },
|
||||
openclaw: { cdpPort: testPort + 1, color: "#FF4500" },
|
||||
},
|
||||
},
|
||||
}),
|
||||
@@ -107,20 +107,20 @@ const launchCalls = vi.hoisted(() => [] as Array<{ port: number }>);
|
||||
vi.mock("./chrome.js", () => ({
|
||||
isChromeCdpReady: vi.fn(async () => reachable),
|
||||
isChromeReachable: vi.fn(async () => reachable),
|
||||
launchClawdChrome: vi.fn(async (_resolved: unknown, profile: { cdpPort: number }) => {
|
||||
launchOpenClawChrome: vi.fn(async (_resolved: unknown, profile: { cdpPort: number }) => {
|
||||
launchCalls.push({ port: profile.cdpPort });
|
||||
reachable = true;
|
||||
return {
|
||||
pid: 123,
|
||||
exe: { kind: "chrome", path: "/fake/chrome" },
|
||||
userDataDir: "/tmp/clawd",
|
||||
userDataDir: "/tmp/openclaw",
|
||||
cdpPort: profile.cdpPort,
|
||||
startedAt: Date.now(),
|
||||
proc,
|
||||
};
|
||||
}),
|
||||
resolveClawdUserDataDir: vi.fn(() => "/tmp/clawd"),
|
||||
stopClawdChrome: vi.fn(async () => {
|
||||
resolveOpenClawUserDataDir: vi.fn(() => "/tmp/openclaw"),
|
||||
stopOpenClawChrome: vi.fn(async () => {
|
||||
reachable = false;
|
||||
}),
|
||||
}));
|
||||
@@ -198,8 +198,8 @@ describe("browser control server", () => {
|
||||
|
||||
testPort = await getFreePort();
|
||||
cdpBaseUrl = `http://127.0.0.1:${testPort + 1}`;
|
||||
prevGatewayPort = process.env.CLAWDBOT_GATEWAY_PORT;
|
||||
process.env.CLAWDBOT_GATEWAY_PORT = String(testPort - 2);
|
||||
prevGatewayPort = process.env.OPENCLAW_GATEWAY_PORT;
|
||||
process.env.OPENCLAW_GATEWAY_PORT = String(testPort - 2);
|
||||
|
||||
// Minimal CDP JSON endpoints used by the server.
|
||||
let putNewCalls = 0;
|
||||
@@ -252,9 +252,9 @@ describe("browser control server", () => {
|
||||
vi.unstubAllGlobals();
|
||||
vi.restoreAllMocks();
|
||||
if (prevGatewayPort === undefined) {
|
||||
delete process.env.CLAWDBOT_GATEWAY_PORT;
|
||||
delete process.env.OPENCLAW_GATEWAY_PORT;
|
||||
} else {
|
||||
process.env.CLAWDBOT_GATEWAY_PORT = prevGatewayPort;
|
||||
process.env.OPENCLAW_GATEWAY_PORT = prevGatewayPort;
|
||||
}
|
||||
const { stopBrowserControlServer } = await import("./server.js");
|
||||
await stopBrowserControlServer();
|
||||
|
||||
@@ -92,9 +92,9 @@ vi.mock("../config/config.js", async (importOriginal) => {
|
||||
color: "#FF4500",
|
||||
attachOnly: cfgAttachOnly,
|
||||
headless: true,
|
||||
defaultProfile: "clawd",
|
||||
defaultProfile: "openclaw",
|
||||
profiles: {
|
||||
clawd: { cdpPort: testPort + 1, color: "#FF4500" },
|
||||
openclaw: { cdpPort: testPort + 1, color: "#FF4500" },
|
||||
},
|
||||
},
|
||||
}),
|
||||
@@ -106,20 +106,20 @@ const launchCalls = vi.hoisted(() => [] as Array<{ port: number }>);
|
||||
vi.mock("./chrome.js", () => ({
|
||||
isChromeCdpReady: vi.fn(async () => reachable),
|
||||
isChromeReachable: vi.fn(async () => reachable),
|
||||
launchClawdChrome: vi.fn(async (_resolved: unknown, profile: { cdpPort: number }) => {
|
||||
launchOpenClawChrome: vi.fn(async (_resolved: unknown, profile: { cdpPort: number }) => {
|
||||
launchCalls.push({ port: profile.cdpPort });
|
||||
reachable = true;
|
||||
return {
|
||||
pid: 123,
|
||||
exe: { kind: "chrome", path: "/fake/chrome" },
|
||||
userDataDir: "/tmp/clawd",
|
||||
userDataDir: "/tmp/openclaw",
|
||||
cdpPort: profile.cdpPort,
|
||||
startedAt: Date.now(),
|
||||
proc,
|
||||
};
|
||||
}),
|
||||
resolveClawdUserDataDir: vi.fn(() => "/tmp/clawd"),
|
||||
stopClawdChrome: vi.fn(async () => {
|
||||
resolveOpenClawUserDataDir: vi.fn(() => "/tmp/openclaw"),
|
||||
stopOpenClawChrome: vi.fn(async () => {
|
||||
reachable = false;
|
||||
}),
|
||||
}));
|
||||
@@ -197,8 +197,8 @@ describe("browser control server", () => {
|
||||
|
||||
testPort = await getFreePort();
|
||||
_cdpBaseUrl = `http://127.0.0.1:${testPort + 1}`;
|
||||
prevGatewayPort = process.env.CLAWDBOT_GATEWAY_PORT;
|
||||
process.env.CLAWDBOT_GATEWAY_PORT = String(testPort - 2);
|
||||
prevGatewayPort = process.env.OPENCLAW_GATEWAY_PORT;
|
||||
process.env.OPENCLAW_GATEWAY_PORT = String(testPort - 2);
|
||||
|
||||
// Minimal CDP JSON endpoints used by the server.
|
||||
let putNewCalls = 0;
|
||||
@@ -251,9 +251,9 @@ describe("browser control server", () => {
|
||||
vi.unstubAllGlobals();
|
||||
vi.restoreAllMocks();
|
||||
if (prevGatewayPort === undefined) {
|
||||
delete process.env.CLAWDBOT_GATEWAY_PORT;
|
||||
delete process.env.OPENCLAW_GATEWAY_PORT;
|
||||
} else {
|
||||
process.env.CLAWDBOT_GATEWAY_PORT = prevGatewayPort;
|
||||
process.env.OPENCLAW_GATEWAY_PORT = prevGatewayPort;
|
||||
}
|
||||
const { stopBrowserControlServer } = await import("./server.js");
|
||||
await stopBrowserControlServer();
|
||||
@@ -308,11 +308,11 @@ describe("backward compatibility (profile parameter)", () => {
|
||||
|
||||
testPort = await getFreePort();
|
||||
_cdpBaseUrl = `http://127.0.0.1:${testPort + 1}`;
|
||||
prevGatewayPort = process.env.CLAWDBOT_GATEWAY_PORT;
|
||||
process.env.CLAWDBOT_GATEWAY_PORT = String(testPort - 2);
|
||||
prevGatewayPort = process.env.OPENCLAW_GATEWAY_PORT;
|
||||
process.env.OPENCLAW_GATEWAY_PORT = String(testPort - 2);
|
||||
|
||||
prevGatewayPort = process.env.CLAWDBOT_GATEWAY_PORT;
|
||||
process.env.CLAWDBOT_GATEWAY_PORT = String(testPort - 2);
|
||||
prevGatewayPort = process.env.OPENCLAW_GATEWAY_PORT;
|
||||
process.env.OPENCLAW_GATEWAY_PORT = String(testPort - 2);
|
||||
|
||||
vi.stubGlobal(
|
||||
"fetch",
|
||||
@@ -350,9 +350,9 @@ describe("backward compatibility (profile parameter)", () => {
|
||||
vi.unstubAllGlobals();
|
||||
vi.restoreAllMocks();
|
||||
if (prevGatewayPort === undefined) {
|
||||
delete process.env.CLAWDBOT_GATEWAY_PORT;
|
||||
delete process.env.OPENCLAW_GATEWAY_PORT;
|
||||
} else {
|
||||
process.env.CLAWDBOT_GATEWAY_PORT = prevGatewayPort;
|
||||
process.env.OPENCLAW_GATEWAY_PORT = prevGatewayPort;
|
||||
}
|
||||
const { stopBrowserControlServer } = await import("./server.js");
|
||||
await stopBrowserControlServer();
|
||||
@@ -368,8 +368,8 @@ describe("backward compatibility (profile parameter)", () => {
|
||||
profile?: string;
|
||||
};
|
||||
expect(status.running).toBe(false);
|
||||
// Should use default profile (clawd)
|
||||
expect(status.profile).toBe("clawd");
|
||||
// Should use default profile (openclaw)
|
||||
expect(status.profile).toBe("openclaw");
|
||||
});
|
||||
|
||||
it("POST /start without profile uses default profile", async () => {
|
||||
@@ -382,7 +382,7 @@ describe("backward compatibility (profile parameter)", () => {
|
||||
profile?: string;
|
||||
};
|
||||
expect(result.ok).toBe(true);
|
||||
expect(result.profile).toBe("clawd");
|
||||
expect(result.profile).toBe("openclaw");
|
||||
});
|
||||
|
||||
it("POST /stop without profile uses default profile", async () => {
|
||||
@@ -397,7 +397,7 @@ describe("backward compatibility (profile parameter)", () => {
|
||||
profile?: string;
|
||||
};
|
||||
expect(result.ok).toBe(true);
|
||||
expect(result.profile).toBe("clawd");
|
||||
expect(result.profile).toBe("openclaw");
|
||||
});
|
||||
|
||||
it("GET /tabs without profile uses default profile", async () => {
|
||||
@@ -439,18 +439,18 @@ describe("backward compatibility (profile parameter)", () => {
|
||||
profiles: Array<{ name: string }>;
|
||||
};
|
||||
expect(Array.isArray(result.profiles)).toBe(true);
|
||||
// Should at least have the default clawd profile
|
||||
expect(result.profiles.some((p) => p.name === "clawd")).toBe(true);
|
||||
// Should at least have the default openclaw profile
|
||||
expect(result.profiles.some((p) => p.name === "openclaw")).toBe(true);
|
||||
});
|
||||
|
||||
it("GET /tabs?profile=clawd returns tabs for specified profile", async () => {
|
||||
it("GET /tabs?profile=openclaw returns tabs for specified profile", async () => {
|
||||
const { startBrowserControlServerFromConfig } = await import("./server.js");
|
||||
await startBrowserControlServerFromConfig();
|
||||
const base = `http://127.0.0.1:${testPort}`;
|
||||
|
||||
await realFetch(`${base}/start`, { method: "POST" });
|
||||
|
||||
const result = (await realFetch(`${base}/tabs?profile=clawd`).then((r) => r.json())) as {
|
||||
const result = (await realFetch(`${base}/tabs?profile=openclaw`).then((r) => r.json())) as {
|
||||
running: boolean;
|
||||
tabs: unknown[];
|
||||
};
|
||||
@@ -458,14 +458,14 @@ describe("backward compatibility (profile parameter)", () => {
|
||||
expect(Array.isArray(result.tabs)).toBe(true);
|
||||
});
|
||||
|
||||
it("POST /tabs/open?profile=clawd opens tab in specified profile", async () => {
|
||||
it("POST /tabs/open?profile=openclaw opens tab in specified profile", async () => {
|
||||
const { startBrowserControlServerFromConfig } = await import("./server.js");
|
||||
await startBrowserControlServerFromConfig();
|
||||
const base = `http://127.0.0.1:${testPort}`;
|
||||
|
||||
await realFetch(`${base}/start`, { method: "POST" });
|
||||
|
||||
const result = (await realFetch(`${base}/tabs/open?profile=clawd`, {
|
||||
const result = (await realFetch(`${base}/tabs/open?profile=openclaw`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ url: "https://example.com" }),
|
||||
|
||||
@@ -92,9 +92,9 @@ vi.mock("../config/config.js", async (importOriginal) => {
|
||||
color: "#FF4500",
|
||||
attachOnly: cfgAttachOnly,
|
||||
headless: true,
|
||||
defaultProfile: "clawd",
|
||||
defaultProfile: "openclaw",
|
||||
profiles: {
|
||||
clawd: { cdpPort: testPort + 1, color: "#FF4500" },
|
||||
openclaw: { cdpPort: testPort + 1, color: "#FF4500" },
|
||||
},
|
||||
},
|
||||
}),
|
||||
@@ -106,20 +106,20 @@ const launchCalls = vi.hoisted(() => [] as Array<{ port: number }>);
|
||||
vi.mock("./chrome.js", () => ({
|
||||
isChromeCdpReady: vi.fn(async () => reachable),
|
||||
isChromeReachable: vi.fn(async () => reachable),
|
||||
launchClawdChrome: vi.fn(async (_resolved: unknown, profile: { cdpPort: number }) => {
|
||||
launchOpenClawChrome: vi.fn(async (_resolved: unknown, profile: { cdpPort: number }) => {
|
||||
launchCalls.push({ port: profile.cdpPort });
|
||||
reachable = true;
|
||||
return {
|
||||
pid: 123,
|
||||
exe: { kind: "chrome", path: "/fake/chrome" },
|
||||
userDataDir: "/tmp/clawd",
|
||||
userDataDir: "/tmp/openclaw",
|
||||
cdpPort: profile.cdpPort,
|
||||
startedAt: Date.now(),
|
||||
proc,
|
||||
};
|
||||
}),
|
||||
resolveClawdUserDataDir: vi.fn(() => "/tmp/clawd"),
|
||||
stopClawdChrome: vi.fn(async () => {
|
||||
resolveOpenClawUserDataDir: vi.fn(() => "/tmp/openclaw"),
|
||||
stopOpenClawChrome: vi.fn(async () => {
|
||||
reachable = false;
|
||||
}),
|
||||
}));
|
||||
@@ -197,8 +197,8 @@ describe("browser control server", () => {
|
||||
|
||||
testPort = await getFreePort();
|
||||
_cdpBaseUrl = `http://127.0.0.1:${testPort + 1}`;
|
||||
prevGatewayPort = process.env.CLAWDBOT_GATEWAY_PORT;
|
||||
process.env.CLAWDBOT_GATEWAY_PORT = String(testPort - 2);
|
||||
prevGatewayPort = process.env.OPENCLAW_GATEWAY_PORT;
|
||||
process.env.OPENCLAW_GATEWAY_PORT = String(testPort - 2);
|
||||
|
||||
// Minimal CDP JSON endpoints used by the server.
|
||||
let putNewCalls = 0;
|
||||
@@ -251,9 +251,9 @@ describe("browser control server", () => {
|
||||
vi.unstubAllGlobals();
|
||||
vi.restoreAllMocks();
|
||||
if (prevGatewayPort === undefined) {
|
||||
delete process.env.CLAWDBOT_GATEWAY_PORT;
|
||||
delete process.env.OPENCLAW_GATEWAY_PORT;
|
||||
} else {
|
||||
process.env.CLAWDBOT_GATEWAY_PORT = prevGatewayPort;
|
||||
process.env.OPENCLAW_GATEWAY_PORT = prevGatewayPort;
|
||||
}
|
||||
const { stopBrowserControlServer } = await import("./server.js");
|
||||
await stopBrowserControlServer();
|
||||
@@ -285,11 +285,11 @@ describe("profile CRUD endpoints", () => {
|
||||
|
||||
testPort = await getFreePort();
|
||||
_cdpBaseUrl = `http://127.0.0.1:${testPort + 1}`;
|
||||
prevGatewayPort = process.env.CLAWDBOT_GATEWAY_PORT;
|
||||
process.env.CLAWDBOT_GATEWAY_PORT = String(testPort - 2);
|
||||
prevGatewayPort = process.env.OPENCLAW_GATEWAY_PORT;
|
||||
process.env.OPENCLAW_GATEWAY_PORT = String(testPort - 2);
|
||||
|
||||
prevGatewayPort = process.env.CLAWDBOT_GATEWAY_PORT;
|
||||
process.env.CLAWDBOT_GATEWAY_PORT = String(testPort - 2);
|
||||
prevGatewayPort = process.env.OPENCLAW_GATEWAY_PORT;
|
||||
process.env.OPENCLAW_GATEWAY_PORT = String(testPort - 2);
|
||||
|
||||
vi.stubGlobal(
|
||||
"fetch",
|
||||
@@ -305,9 +305,9 @@ describe("profile CRUD endpoints", () => {
|
||||
vi.unstubAllGlobals();
|
||||
vi.restoreAllMocks();
|
||||
if (prevGatewayPort === undefined) {
|
||||
delete process.env.CLAWDBOT_GATEWAY_PORT;
|
||||
delete process.env.OPENCLAW_GATEWAY_PORT;
|
||||
} else {
|
||||
process.env.CLAWDBOT_GATEWAY_PORT = prevGatewayPort;
|
||||
process.env.OPENCLAW_GATEWAY_PORT = prevGatewayPort;
|
||||
}
|
||||
const { stopBrowserControlServer } = await import("./server.js");
|
||||
await stopBrowserControlServer();
|
||||
@@ -348,11 +348,11 @@ describe("profile CRUD endpoints", () => {
|
||||
await startBrowserControlServerFromConfig();
|
||||
const base = `http://127.0.0.1:${testPort}`;
|
||||
|
||||
// "clawd" already exists as the default profile
|
||||
// "openclaw" already exists as the default profile
|
||||
const result = await realFetch(`${base}/profiles/create`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ name: "clawd" }),
|
||||
body: JSON.stringify({ name: "openclaw" }),
|
||||
});
|
||||
expect(result.status).toBe(409);
|
||||
const body = (await result.json()) as { error: string };
|
||||
@@ -413,8 +413,8 @@ describe("profile CRUD endpoints", () => {
|
||||
await startBrowserControlServerFromConfig();
|
||||
const base = `http://127.0.0.1:${testPort}`;
|
||||
|
||||
// clawd is the default profile
|
||||
const result = await realFetch(`${base}/profiles/clawd`, {
|
||||
// openclaw is the default profile
|
||||
const result = await realFetch(`${base}/profiles/openclaw`, {
|
||||
method: "DELETE",
|
||||
});
|
||||
expect(result.status).toBe(400);
|
||||
|
||||
@@ -92,9 +92,9 @@ vi.mock("../config/config.js", async (importOriginal) => {
|
||||
color: "#FF4500",
|
||||
attachOnly: cfgAttachOnly,
|
||||
headless: true,
|
||||
defaultProfile: "clawd",
|
||||
defaultProfile: "openclaw",
|
||||
profiles: {
|
||||
clawd: { cdpPort: testPort + 1, color: "#FF4500" },
|
||||
openclaw: { cdpPort: testPort + 1, color: "#FF4500" },
|
||||
},
|
||||
},
|
||||
}),
|
||||
@@ -106,20 +106,20 @@ const launchCalls = vi.hoisted(() => [] as Array<{ port: number }>);
|
||||
vi.mock("./chrome.js", () => ({
|
||||
isChromeCdpReady: vi.fn(async () => reachable),
|
||||
isChromeReachable: vi.fn(async () => reachable),
|
||||
launchClawdChrome: vi.fn(async (_resolved: unknown, profile: { cdpPort: number }) => {
|
||||
launchOpenClawChrome: vi.fn(async (_resolved: unknown, profile: { cdpPort: number }) => {
|
||||
launchCalls.push({ port: profile.cdpPort });
|
||||
reachable = true;
|
||||
return {
|
||||
pid: 123,
|
||||
exe: { kind: "chrome", path: "/fake/chrome" },
|
||||
userDataDir: "/tmp/clawd",
|
||||
userDataDir: "/tmp/openclaw",
|
||||
cdpPort: profile.cdpPort,
|
||||
startedAt: Date.now(),
|
||||
proc,
|
||||
};
|
||||
}),
|
||||
resolveClawdUserDataDir: vi.fn(() => "/tmp/clawd"),
|
||||
stopClawdChrome: vi.fn(async () => {
|
||||
resolveOpenClawUserDataDir: vi.fn(() => "/tmp/openclaw"),
|
||||
stopOpenClawChrome: vi.fn(async () => {
|
||||
reachable = false;
|
||||
}),
|
||||
}));
|
||||
@@ -197,8 +197,8 @@ describe("browser control server", () => {
|
||||
|
||||
testPort = await getFreePort();
|
||||
_cdpBaseUrl = `http://127.0.0.1:${testPort + 1}`;
|
||||
prevGatewayPort = process.env.CLAWDBOT_GATEWAY_PORT;
|
||||
process.env.CLAWDBOT_GATEWAY_PORT = String(testPort - 2);
|
||||
prevGatewayPort = process.env.OPENCLAW_GATEWAY_PORT;
|
||||
process.env.OPENCLAW_GATEWAY_PORT = String(testPort - 2);
|
||||
|
||||
// Minimal CDP JSON endpoints used by the server.
|
||||
let putNewCalls = 0;
|
||||
@@ -251,9 +251,9 @@ describe("browser control server", () => {
|
||||
vi.unstubAllGlobals();
|
||||
vi.restoreAllMocks();
|
||||
if (prevGatewayPort === undefined) {
|
||||
delete process.env.CLAWDBOT_GATEWAY_PORT;
|
||||
delete process.env.OPENCLAW_GATEWAY_PORT;
|
||||
} else {
|
||||
process.env.CLAWDBOT_GATEWAY_PORT = prevGatewayPort;
|
||||
process.env.OPENCLAW_GATEWAY_PORT = prevGatewayPort;
|
||||
}
|
||||
const { stopBrowserControlServer } = await import("./server.js");
|
||||
await stopBrowserControlServer();
|
||||
|
||||
@@ -92,9 +92,9 @@ vi.mock("../config/config.js", async (importOriginal) => {
|
||||
color: "#FF4500",
|
||||
attachOnly: cfgAttachOnly,
|
||||
headless: true,
|
||||
defaultProfile: "clawd",
|
||||
defaultProfile: "openclaw",
|
||||
profiles: {
|
||||
clawd: { cdpPort: testPort + 1, color: "#FF4500" },
|
||||
openclaw: { cdpPort: testPort + 1, color: "#FF4500" },
|
||||
},
|
||||
},
|
||||
}),
|
||||
@@ -106,20 +106,20 @@ const launchCalls = vi.hoisted(() => [] as Array<{ port: number }>);
|
||||
vi.mock("./chrome.js", () => ({
|
||||
isChromeCdpReady: vi.fn(async () => reachable),
|
||||
isChromeReachable: vi.fn(async () => reachable),
|
||||
launchClawdChrome: vi.fn(async (_resolved: unknown, profile: { cdpPort: number }) => {
|
||||
launchOpenClawChrome: vi.fn(async (_resolved: unknown, profile: { cdpPort: number }) => {
|
||||
launchCalls.push({ port: profile.cdpPort });
|
||||
reachable = true;
|
||||
return {
|
||||
pid: 123,
|
||||
exe: { kind: "chrome", path: "/fake/chrome" },
|
||||
userDataDir: "/tmp/clawd",
|
||||
userDataDir: "/tmp/openclaw",
|
||||
cdpPort: profile.cdpPort,
|
||||
startedAt: Date.now(),
|
||||
proc,
|
||||
};
|
||||
}),
|
||||
resolveClawdUserDataDir: vi.fn(() => "/tmp/clawd"),
|
||||
stopClawdChrome: vi.fn(async () => {
|
||||
resolveOpenClawUserDataDir: vi.fn(() => "/tmp/openclaw"),
|
||||
stopOpenClawChrome: vi.fn(async () => {
|
||||
reachable = false;
|
||||
}),
|
||||
}));
|
||||
@@ -197,8 +197,8 @@ describe("browser control server", () => {
|
||||
|
||||
testPort = await getFreePort();
|
||||
cdpBaseUrl = `http://127.0.0.1:${testPort + 1}`;
|
||||
prevGatewayPort = process.env.CLAWDBOT_GATEWAY_PORT;
|
||||
process.env.CLAWDBOT_GATEWAY_PORT = String(testPort - 2);
|
||||
prevGatewayPort = process.env.OPENCLAW_GATEWAY_PORT;
|
||||
process.env.OPENCLAW_GATEWAY_PORT = String(testPort - 2);
|
||||
|
||||
// Minimal CDP JSON endpoints used by the server.
|
||||
let putNewCalls = 0;
|
||||
@@ -251,9 +251,9 @@ describe("browser control server", () => {
|
||||
vi.unstubAllGlobals();
|
||||
vi.restoreAllMocks();
|
||||
if (prevGatewayPort === undefined) {
|
||||
delete process.env.CLAWDBOT_GATEWAY_PORT;
|
||||
delete process.env.OPENCLAW_GATEWAY_PORT;
|
||||
} else {
|
||||
process.env.CLAWDBOT_GATEWAY_PORT = prevGatewayPort;
|
||||
process.env.OPENCLAW_GATEWAY_PORT = prevGatewayPort;
|
||||
}
|
||||
const { stopBrowserControlServer } = await import("./server.js");
|
||||
await stopBrowserControlServer();
|
||||
@@ -409,9 +409,9 @@ describe("browser control server", () => {
|
||||
headless: true,
|
||||
noSandbox: false,
|
||||
attachOnly: true,
|
||||
defaultProfile: "clawd",
|
||||
defaultProfile: "openclaw",
|
||||
profiles: {
|
||||
clawd: { cdpPort: testPort + 1, color: "#FF4500" },
|
||||
openclaw: { cdpPort: testPort + 1, color: "#FF4500" },
|
||||
},
|
||||
},
|
||||
onEnsureAttachTarget: ensured,
|
||||
|
||||
@@ -33,7 +33,7 @@ export async function startBrowserControlServerFromConfig(): Promise<BrowserServ
|
||||
const s = app.listen(port, "127.0.0.1", () => resolve(s));
|
||||
s.once("error", reject);
|
||||
}).catch((err) => {
|
||||
logServer.error(`clawd browser server failed to bind 127.0.0.1:${port}: ${String(err)}`);
|
||||
logServer.error(`openclaw browser server failed to bind 127.0.0.1:${port}: ${String(err)}`);
|
||||
return null;
|
||||
});
|
||||
|
||||
@@ -80,7 +80,7 @@ export async function stopBrowserControlServer(): Promise<void> {
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
logServer.warn(`clawd browser stop failed: ${String(err)}`);
|
||||
logServer.warn(`openclaw browser stop failed: ${String(err)}`);
|
||||
}
|
||||
|
||||
if (current.server) {
|
||||
|
||||
Reference in New Issue
Block a user