mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-07 10:50:42 +00:00
128 lines
3.2 KiB
JavaScript
128 lines
3.2 KiB
JavaScript
import { WebSocket } from "ws";
|
|
|
|
const PROTOCOL_VERSION = 3;
|
|
|
|
const url = process.env.GW_URL;
|
|
const token = process.env.GW_TOKEN;
|
|
if (!url || !token) {
|
|
throw new Error("missing GW_URL/GW_TOKEN");
|
|
}
|
|
|
|
const deadlineMs = Number.parseInt(
|
|
process.env.OPENCLAW_GATEWAY_NETWORK_CLIENT_CONNECT_TIMEOUT_MS ??
|
|
process.env.OPENCLAW_GATEWAY_NETWORK_CONNECT_READY_TIMEOUT_MS ??
|
|
"80000",
|
|
10,
|
|
);
|
|
if (!Number.isFinite(deadlineMs) || deadlineMs < 0) {
|
|
throw new Error(`invalid gateway network client timeout: ${String(deadlineMs)}`);
|
|
}
|
|
const deadline = Date.now() + Math.max(1_000, deadlineMs);
|
|
|
|
function delay(ms) {
|
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
}
|
|
|
|
async function openSocket(timeoutMs = 10_000) {
|
|
const ws = new WebSocket(url);
|
|
await new Promise((resolve, reject) => {
|
|
const timer = setTimeout(() => {
|
|
ws.close();
|
|
reject(new Error("ws open timeout"));
|
|
}, timeoutMs);
|
|
ws.once("open", () => {
|
|
clearTimeout(timer);
|
|
resolve();
|
|
});
|
|
ws.once("error", (error) => {
|
|
clearTimeout(timer);
|
|
reject(error instanceof Error ? error : new Error(String(error)));
|
|
});
|
|
});
|
|
return ws;
|
|
}
|
|
|
|
function onceFrame(ws, filter, timeoutMs = 10_000) {
|
|
return new Promise((resolve, reject) => {
|
|
const timer = setTimeout(() => {
|
|
ws.off("message", handler);
|
|
reject(new Error("timeout"));
|
|
}, timeoutMs);
|
|
const handler = (data) => {
|
|
const obj = JSON.parse(String(data));
|
|
if (!filter(obj)) {
|
|
return;
|
|
}
|
|
clearTimeout(timer);
|
|
ws.off("message", handler);
|
|
resolve(obj);
|
|
};
|
|
ws.on("message", handler);
|
|
});
|
|
}
|
|
|
|
let lastError;
|
|
while (Date.now() < deadline) {
|
|
let ws;
|
|
try {
|
|
ws = await openSocket();
|
|
ws.send(
|
|
JSON.stringify({
|
|
type: "req",
|
|
id: "c1",
|
|
method: "connect",
|
|
params: {
|
|
minProtocol: PROTOCOL_VERSION,
|
|
maxProtocol: PROTOCOL_VERSION,
|
|
client: {
|
|
id: "test",
|
|
displayName: "docker-net-e2e",
|
|
version: "dev",
|
|
platform: process.platform,
|
|
mode: "test",
|
|
},
|
|
caps: [],
|
|
auth: { token },
|
|
},
|
|
}),
|
|
);
|
|
|
|
const connectRes = await onceFrame(ws, (frame) => frame?.type === "res" && frame?.id === "c1");
|
|
if (connectRes.ok) {
|
|
ws.close();
|
|
console.log("ok");
|
|
process.exit(0);
|
|
}
|
|
|
|
const message = connectRes.error?.message ?? "unknown";
|
|
lastError = new Error(`connect failed: ${message}`);
|
|
if (
|
|
!message.includes("gateway starting") &&
|
|
!message.includes("ws open timeout") &&
|
|
!message.includes("ECONNREFUSED") &&
|
|
!message.includes("ECONNRESET") &&
|
|
!message.includes("timeout")
|
|
) {
|
|
throw lastError;
|
|
}
|
|
} catch (error) {
|
|
lastError = error instanceof Error ? error : new Error(String(error));
|
|
const message = lastError.message;
|
|
if (
|
|
!message.includes("gateway starting") &&
|
|
!message.includes("ws open timeout") &&
|
|
!message.includes("ECONNREFUSED") &&
|
|
!message.includes("ECONNRESET") &&
|
|
!message.includes("timeout")
|
|
) {
|
|
throw lastError;
|
|
}
|
|
} finally {
|
|
ws?.close();
|
|
}
|
|
|
|
await delay(500);
|
|
}
|
|
|
|
throw lastError ?? new Error("connect failed: timeout");
|