Files
clawdbot/src/gateway/probe.ts
Peter Steinberger c379191f80 chore: migrate to oxlint and oxfmt
Co-authored-by: Christoph Nakazawa <christoph.pojer@gmail.com>
2026-01-14 15:02:19 +00:00

123 lines
3.1 KiB
TypeScript

import { randomUUID } from "node:crypto";
import type { SystemPresence } from "../infra/system-presence.js";
import { GATEWAY_CLIENT_MODES, GATEWAY_CLIENT_NAMES } from "../utils/message-channel.js";
import { GatewayClient } from "./client.js";
export type GatewayProbeAuth = {
token?: string;
password?: string;
};
export type GatewayProbeClose = {
code: number;
reason: string;
hint?: string;
};
export type GatewayProbeResult = {
ok: boolean;
url: string;
connectLatencyMs: number | null;
error: string | null;
close: GatewayProbeClose | null;
health: unknown;
status: unknown;
presence: SystemPresence[] | null;
configSnapshot: unknown;
};
function formatError(err: unknown): string {
if (err instanceof Error) return err.message;
return String(err);
}
export async function probeGateway(opts: {
url: string;
auth?: GatewayProbeAuth;
timeoutMs: number;
}): Promise<GatewayProbeResult> {
const startedAt = Date.now();
const instanceId = randomUUID();
let connectLatencyMs: number | null = null;
let connectError: string | null = null;
let close: GatewayProbeClose | null = null;
return await new Promise<GatewayProbeResult>((resolve) => {
let settled = false;
const settle = (result: Omit<GatewayProbeResult, "url">) => {
if (settled) return;
settled = true;
clearTimeout(timer);
client.stop();
resolve({ url: opts.url, ...result });
};
const client = new GatewayClient({
url: opts.url,
token: opts.auth?.token,
password: opts.auth?.password,
clientName: GATEWAY_CLIENT_NAMES.CLI,
clientVersion: "dev",
mode: GATEWAY_CLIENT_MODES.PROBE,
instanceId,
onConnectError: (err) => {
connectError = formatError(err);
},
onClose: (code, reason) => {
close = { code, reason };
},
onHelloOk: async () => {
connectLatencyMs = Date.now() - startedAt;
try {
const [health, status, presence, configSnapshot] = await Promise.all([
client.request("health"),
client.request("status"),
client.request("system-presence"),
client.request("config.get", {}),
]);
settle({
ok: true,
connectLatencyMs,
error: null,
close,
health,
status,
presence: Array.isArray(presence) ? (presence as SystemPresence[]) : null,
configSnapshot,
});
} catch (err) {
settle({
ok: false,
connectLatencyMs,
error: formatError(err),
close,
health: null,
status: null,
presence: null,
configSnapshot: null,
});
}
},
});
const timer = setTimeout(
() => {
settle({
ok: false,
connectLatencyMs,
error: connectError ? `connect failed: ${connectError}` : "timeout",
close,
health: null,
status: null,
presence: null,
configSnapshot: null,
});
},
Math.max(250, opts.timeoutMs),
);
client.start();
});
}