Files
openclaw/src/gateway/operator-approvals-client.ts
2026-04-06 17:31:16 +01:00

91 lines
2.4 KiB
TypeScript

import type { OpenClawConfig } from "../config/config.js";
import { GATEWAY_CLIENT_MODES, GATEWAY_CLIENT_NAMES } from "../utils/message-channel.js";
import { resolveGatewayClientBootstrap } from "./client-bootstrap.js";
import { GatewayClient, type GatewayClientOptions } from "./client.js";
export async function createOperatorApprovalsGatewayClient(
params: Pick<
GatewayClientOptions,
"clientDisplayName" | "onClose" | "onConnectError" | "onEvent" | "onHelloOk"
> & {
config: OpenClawConfig;
gatewayUrl?: string;
},
): Promise<GatewayClient> {
const bootstrap = await resolveGatewayClientBootstrap({
config: params.config,
gatewayUrl: params.gatewayUrl,
env: process.env,
});
return new GatewayClient({
url: bootstrap.url,
token: bootstrap.auth.token,
password: bootstrap.auth.password,
clientName: GATEWAY_CLIENT_NAMES.GATEWAY_CLIENT,
clientDisplayName: params.clientDisplayName,
mode: GATEWAY_CLIENT_MODES.BACKEND,
scopes: ["operator.approvals"],
onEvent: params.onEvent,
onHelloOk: params.onHelloOk,
onConnectError: params.onConnectError,
onClose: params.onClose,
});
}
export async function withOperatorApprovalsGatewayClient<T>(
params: {
config: OpenClawConfig;
gatewayUrl?: string;
clientDisplayName: string;
},
run: (client: GatewayClient) => Promise<T>,
): Promise<T> {
let readySettled = false;
let resolveReady!: () => void;
let rejectReady!: (err: unknown) => void;
const ready = new Promise<void>((resolve, reject) => {
resolveReady = resolve;
rejectReady = reject;
});
const markReady = () => {
if (readySettled) {
return;
}
readySettled = true;
resolveReady();
};
const failReady = (err: unknown) => {
if (readySettled) {
return;
}
readySettled = true;
rejectReady(err);
};
const gatewayClient = await createOperatorApprovalsGatewayClient({
config: params.config,
gatewayUrl: params.gatewayUrl,
clientDisplayName: params.clientDisplayName,
onHelloOk: () => {
markReady();
},
onConnectError: (err) => {
failReady(err);
},
onClose: (code, reason) => {
failReady(new Error(`gateway closed (${code}): ${reason}`));
},
});
try {
gatewayClient.start();
await ready;
return await run(gatewayClient);
} finally {
await gatewayClient.stopAndWait().catch(() => {
gatewayClient.stop();
});
}
}