mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 04:01:23 +00:00
refactor: lint cleanups and helpers
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { createServer } from "node:net";
|
||||
import { afterEach, describe, expect, test } from "vitest";
|
||||
import { WebSocketServer } from "ws";
|
||||
import { rawDataToString } from "../infra/ws.js";
|
||||
import { GatewayClient } from "./client.js";
|
||||
|
||||
// Find a free localhost port for ad-hoc WS servers.
|
||||
@@ -30,7 +31,7 @@ describe("GatewayClient", () => {
|
||||
|
||||
wss.on("connection", (socket) => {
|
||||
socket.once("message", (data) => {
|
||||
const first = JSON.parse(String(data)) as { id?: string };
|
||||
const first = JSON.parse(rawDataToString(data)) as { id?: string };
|
||||
const id = first.id ?? "connect";
|
||||
// Respond with tiny tick interval to trigger watchdog quickly.
|
||||
const helloOk = {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { randomUUID } from "node:crypto";
|
||||
import { WebSocket } from "ws";
|
||||
import { rawDataToString } from "../infra/ws.js";
|
||||
import { logDebug, logError } from "../logger.js";
|
||||
import {
|
||||
type ConnectParams,
|
||||
@@ -57,14 +58,15 @@ export class GatewayClient {
|
||||
this.ws = new WebSocket(url, { maxPayload: 25 * 1024 * 1024 });
|
||||
|
||||
this.ws.on("open", () => this.sendConnect());
|
||||
this.ws.on("message", (data) => this.handleMessage(data.toString()));
|
||||
this.ws.on("message", (data) => this.handleMessage(rawDataToString(data)));
|
||||
this.ws.on("close", (code, reason) => {
|
||||
const reasonText = rawDataToString(reason);
|
||||
this.ws = null;
|
||||
this.flushPendingErrors(
|
||||
new Error(`gateway closed (${code}): ${reason.toString()}`),
|
||||
new Error(`gateway closed (${code}): ${reasonText}`),
|
||||
);
|
||||
this.scheduleReconnect();
|
||||
this.opts.onClose?.(code, reason.toString());
|
||||
this.opts.onClose?.(code, reasonText);
|
||||
});
|
||||
this.ws.on("error", (err) => {
|
||||
logDebug(`gateway client error: ${String(err)}`);
|
||||
|
||||
@@ -10,6 +10,7 @@ import { readConfigFileSnapshot, writeConfigFile } from "../config/config.js";
|
||||
import { emitAgentEvent } from "../infra/agent-events.js";
|
||||
import { GatewayLockError } from "../infra/gateway-lock.js";
|
||||
import { emitHeartbeatEvent } from "../infra/heartbeat-events.js";
|
||||
import { rawDataToString } from "../infra/ws.js";
|
||||
import { PROTOCOL_VERSION } from "./protocol/index.js";
|
||||
import {
|
||||
__resetModelCatalogCacheForTest,
|
||||
@@ -298,7 +299,7 @@ function onceMessage<T = unknown>(
|
||||
reject(new Error(`closed ${code}: ${reason.toString()}`));
|
||||
};
|
||||
const handler = (data: WebSocket.RawData) => {
|
||||
const obj = JSON.parse(String(data));
|
||||
const obj = JSON.parse(rawDataToString(data));
|
||||
if (filter(obj)) {
|
||||
clearTimeout(timer);
|
||||
ws.off("message", handler);
|
||||
@@ -678,7 +679,7 @@ describe("gateway server", () => {
|
||||
expect(res1.ok).toBe(true);
|
||||
const req1 = (res1.payload as { request?: { requestId?: unknown } } | null)
|
||||
?.request;
|
||||
const requestId = String(req1?.requestId ?? "");
|
||||
const requestId = typeof req1?.requestId === "string" ? req1.requestId : "";
|
||||
expect(requestId.length).toBeGreaterThan(0);
|
||||
|
||||
const evt1 = await requestedP;
|
||||
@@ -731,10 +732,10 @@ describe("gateway server", () => {
|
||||
payload?: unknown;
|
||||
}>(ws, (o) => o.type === "res" && o.id === "pair-approve-1");
|
||||
expect(approveRes.ok).toBe(true);
|
||||
const token = String(
|
||||
(approveRes.payload as { node?: { token?: unknown } } | null)?.node
|
||||
?.token ?? "",
|
||||
);
|
||||
const tokenValue = (
|
||||
approveRes.payload as { node?: { token?: unknown } } | null
|
||||
)?.node?.token;
|
||||
const token = typeof tokenValue === "string" ? tokenValue : "";
|
||||
expect(token.length).toBeGreaterThan(0);
|
||||
|
||||
const evt2 = await resolvedP;
|
||||
@@ -1235,7 +1236,8 @@ describe("gateway server", () => {
|
||||
payload?: unknown;
|
||||
}>(ws, (o) => o.type === "res" && o.id === "cron-add-log-1");
|
||||
expect(addRes.ok).toBe(true);
|
||||
const jobId = String((addRes.payload as { id?: unknown } | null)?.id ?? "");
|
||||
const jobIdValue = (addRes.payload as { id?: unknown } | null)?.id;
|
||||
const jobId = typeof jobIdValue === "string" ? jobIdValue : "";
|
||||
expect(jobId.length > 0).toBe(true);
|
||||
|
||||
ws.send(
|
||||
@@ -1345,7 +1347,8 @@ describe("gateway server", () => {
|
||||
payload?: unknown;
|
||||
}>(ws, (o) => o.type === "res" && o.id === "cron-add-log-2");
|
||||
expect(addRes.ok).toBe(true);
|
||||
const jobId = String((addRes.payload as { id?: unknown } | null)?.id ?? "");
|
||||
const jobIdValue = (addRes.payload as { id?: unknown } | null)?.id;
|
||||
const jobId = typeof jobIdValue === "string" ? jobIdValue : "";
|
||||
expect(jobId.length > 0).toBe(true);
|
||||
|
||||
ws.send(
|
||||
@@ -1451,7 +1454,11 @@ describe("gateway server", () => {
|
||||
| { enabled?: unknown; storePath?: unknown }
|
||||
| undefined;
|
||||
expect(statusPayload?.enabled).toBe(true);
|
||||
expect(String(statusPayload?.storePath ?? "")).toContain("jobs.json");
|
||||
const storePath =
|
||||
typeof statusPayload?.storePath === "string"
|
||||
? statusPayload.storePath
|
||||
: "";
|
||||
expect(storePath).toContain("jobs.json");
|
||||
|
||||
const atMs = Date.now() + 80;
|
||||
ws.send(
|
||||
@@ -1475,9 +1482,8 @@ describe("gateway server", () => {
|
||||
payload?: unknown;
|
||||
}>(ws, (o) => o.type === "res" && o.id === "cron-add-auto-1");
|
||||
expect(addRes.ok).toBe(true);
|
||||
const jobId = String(
|
||||
(addRes.payload as { id?: unknown } | null)?.id ?? "",
|
||||
);
|
||||
const jobIdValue = (addRes.payload as { id?: unknown } | null)?.id;
|
||||
const jobId = typeof jobIdValue === "string" ? jobIdValue : "";
|
||||
expect(jobId.length > 0).toBe(true);
|
||||
|
||||
const finishedEvt = await onceMessage<{
|
||||
|
||||
@@ -105,6 +105,7 @@ import {
|
||||
WIDE_AREA_DISCOVERY_DOMAIN,
|
||||
writeWideAreaBridgeZone,
|
||||
} from "../infra/widearea-dns.js";
|
||||
import { rawDataToString } from "../infra/ws.js";
|
||||
import {
|
||||
createSubsystemLogger,
|
||||
getChildLogger,
|
||||
@@ -1144,10 +1145,18 @@ const wsInflightSince = new Map<string, number>();
|
||||
function formatError(err: unknown): string {
|
||||
if (err instanceof Error) return err.message;
|
||||
if (typeof err === "string") return err;
|
||||
const status = (err as { status?: unknown })?.status;
|
||||
const code = (err as { code?: unknown })?.code;
|
||||
if (status || code)
|
||||
return `status=${status ?? "unknown"} code=${code ?? "unknown"}`;
|
||||
const statusValue = (err as { status?: unknown })?.status;
|
||||
const codeValue = (err as { code?: unknown })?.code;
|
||||
const statusText =
|
||||
typeof statusValue === "string" || typeof statusValue === "number"
|
||||
? String(statusValue)
|
||||
: undefined;
|
||||
const codeText =
|
||||
typeof codeValue === "string" || typeof codeValue === "number"
|
||||
? String(codeValue)
|
||||
: undefined;
|
||||
if (statusText || codeText)
|
||||
return `status=${statusText ?? "unknown"} code=${codeText ?? "unknown"}`;
|
||||
return JSON.stringify(err, null, 2);
|
||||
}
|
||||
|
||||
@@ -1161,8 +1170,7 @@ async function refreshHealthSnapshot(_opts?: { probe?: boolean }) {
|
||||
broadcastHealthUpdate(snap);
|
||||
}
|
||||
return snap;
|
||||
})();
|
||||
healthRefresh.finally(() => {
|
||||
})().finally(() => {
|
||||
healthRefresh = null;
|
||||
});
|
||||
}
|
||||
@@ -1183,13 +1191,17 @@ export async function startGatewayServer(
|
||||
}
|
||||
const controlUiEnabled =
|
||||
opts.controlUiEnabled ?? cfgAtStart.gateway?.controlUi?.enabled ?? true;
|
||||
const authBase = cfgAtStart.gateway?.auth ?? {};
|
||||
const authOverrides = opts.auth ?? {};
|
||||
const authConfig = {
|
||||
...(cfgAtStart.gateway?.auth ?? {}),
|
||||
...(opts.auth ?? {}),
|
||||
...authBase,
|
||||
...authOverrides,
|
||||
};
|
||||
const tailscaleBase = cfgAtStart.gateway?.tailscale ?? {};
|
||||
const tailscaleOverrides = opts.tailscale ?? {};
|
||||
const tailscaleConfig = {
|
||||
...(cfgAtStart.gateway?.tailscale ?? {}),
|
||||
...(opts.tailscale ?? {}),
|
||||
...tailscaleBase,
|
||||
...tailscaleOverrides,
|
||||
};
|
||||
const tailscaleMode = tailscaleConfig.mode ?? "off";
|
||||
const token = getGatewayToken();
|
||||
@@ -1849,8 +1861,17 @@ export async function startGatewayServer(
|
||||
},
|
||||
};
|
||||
}
|
||||
const raw = String((params as { raw?: unknown }).raw ?? "");
|
||||
const parsedRes = parseConfigJson5(raw);
|
||||
const rawValue = (params as { raw?: unknown }).raw;
|
||||
if (typeof rawValue !== "string") {
|
||||
return {
|
||||
ok: false,
|
||||
error: {
|
||||
code: ErrorCodes.INVALID_REQUEST,
|
||||
message: "invalid config.set params: raw (string) required",
|
||||
},
|
||||
};
|
||||
}
|
||||
const parsedRes = parseConfigJson5(rawValue);
|
||||
if (!parsedRes.ok) {
|
||||
return {
|
||||
ok: false,
|
||||
@@ -2949,7 +2970,9 @@ export async function startGatewayServer(
|
||||
const payload = {
|
||||
...base,
|
||||
state: "error",
|
||||
errorMessage: evt.data.error ? String(evt.data.error) : undefined,
|
||||
errorMessage: evt.data.error
|
||||
? formatForLog(evt.data.error)
|
||||
: undefined,
|
||||
};
|
||||
broadcast("chat", payload);
|
||||
bridgeSendToSession(sessionKey, "chat", payload);
|
||||
@@ -3061,7 +3084,7 @@ export async function startGatewayServer(
|
||||
|
||||
socket.on("message", async (data) => {
|
||||
if (closed) return;
|
||||
const text = data.toString();
|
||||
const text = rawDataToString(data);
|
||||
try {
|
||||
const parsed = JSON.parse(text);
|
||||
if (!client) {
|
||||
@@ -4034,8 +4057,19 @@ export async function startGatewayServer(
|
||||
);
|
||||
break;
|
||||
}
|
||||
const raw = String((params as { raw?: unknown }).raw ?? "");
|
||||
const parsedRes = parseConfigJson5(raw);
|
||||
const rawValue = (params as { raw?: unknown }).raw;
|
||||
if (typeof rawValue !== "string") {
|
||||
respond(
|
||||
false,
|
||||
undefined,
|
||||
errorShape(
|
||||
ErrorCodes.INVALID_REQUEST,
|
||||
"invalid config.set params: raw (string) required",
|
||||
),
|
||||
);
|
||||
break;
|
||||
}
|
||||
const parsedRes = parseConfigJson5(rawValue);
|
||||
if (!parsedRes.ok) {
|
||||
respond(
|
||||
false,
|
||||
@@ -4147,8 +4181,10 @@ export async function startGatewayServer(
|
||||
env?: Record<string, string>;
|
||||
};
|
||||
const cfg = loadConfig();
|
||||
const skills = { ...(cfg.skills ?? {}) };
|
||||
const current = { ...(skills[p.skillKey] ?? {}) };
|
||||
const skills = cfg.skills ? { ...cfg.skills } : {};
|
||||
const current = skills[p.skillKey]
|
||||
? { ...skills[p.skillKey] }
|
||||
: {};
|
||||
if (typeof p.enabled === "boolean") {
|
||||
current.enabled = p.enabled;
|
||||
}
|
||||
@@ -4158,11 +4194,11 @@ export async function startGatewayServer(
|
||||
else delete current.apiKey;
|
||||
}
|
||||
if (p.env && typeof p.env === "object") {
|
||||
const nextEnv = { ...(current.env ?? {}) };
|
||||
const nextEnv = current.env ? { ...current.env } : {};
|
||||
for (const [key, value] of Object.entries(p.env)) {
|
||||
const trimmedKey = key.trim();
|
||||
if (!trimmedKey) continue;
|
||||
const trimmedVal = String(value ?? "").trim();
|
||||
const trimmedVal = value.trim();
|
||||
if (!trimmedVal) delete nextEnv[trimmedKey];
|
||||
else nextEnv[trimmedKey] = trimmedVal;
|
||||
}
|
||||
@@ -4541,7 +4577,8 @@ export async function startGatewayServer(
|
||||
}
|
||||
case "system-event": {
|
||||
const params = (req.params ?? {}) as Record<string, unknown>;
|
||||
const text = String(params.text ?? "").trim();
|
||||
const text =
|
||||
typeof params.text === "string" ? params.text.trim() : "";
|
||||
if (!text) {
|
||||
respond(
|
||||
false,
|
||||
|
||||
Reference in New Issue
Block a user