feat(browser): support direct WebSocket CDP URLs for Browserbase

Browserbase uses direct WebSocket connections (wss://) rather than the
standard HTTP-based /json/version CDP discovery flow used by Browserless.
This change teaches the browser tool to accept ws:// and wss:// URLs as
cdpUrl values: when a WebSocket URL is detected, OpenClaw connects
directly instead of attempting HTTP discovery.

Changes:
- config.ts: accept ws:// and wss:// in cdpUrl validation
- cdp.helpers.ts: add isWebSocketUrl() helper
- cdp.ts: skip /json/version when cdpUrl is already a WebSocket URL
- chrome.ts: probe WSS endpoints via WebSocket handshake instead of HTTP
- cdp.test.ts: add test for direct WebSocket target creation
- docs/tools/browser.md: update Browserbase section with correct URL
  format and notes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
shrey150
2026-03-02 00:49:55 -08:00
committed by Peter Steinberger
parent 3cf75f760c
commit 75602014db
6 changed files with 106 additions and 17 deletions

View File

@@ -95,6 +95,34 @@ describe("cdp", () => {
expect(created.targetId).toBe("TARGET_123");
});
it("creates a target via direct WebSocket URL (skips /json/version)", async () => {
const wsPort = await startWsServerWithMessages((msg, socket) => {
if (msg.method !== "Target.createTarget") {
return;
}
socket.send(
JSON.stringify({
id: msg.id,
result: { targetId: "TARGET_WS_DIRECT" },
}),
);
});
const fetchSpy = vi.spyOn(globalThis, "fetch");
try {
const created = await createTargetViaCdp({
cdpUrl: `ws://127.0.0.1:${wsPort}/devtools/browser/TEST`,
url: "https://example.com",
});
expect(created.targetId).toBe("TARGET_WS_DIRECT");
// /json/version should NOT have been called — direct WS skips HTTP discovery
expect(fetchSpy).not.toHaveBeenCalled();
} finally {
fetchSpy.mockRestore();
}
});
it("blocks private navigation targets by default", async () => {
const fetchSpy = vi.spyOn(globalThis, "fetch");
try {