114 lines
3.3 KiB
TypeScript
114 lines
3.3 KiB
TypeScript
import { randomUUID } from "node:crypto";
|
|
import { loadConfig } from "../config/config.js";
|
|
import { GatewayClient } from "./client.js";
|
|
import { PROTOCOL_VERSION } from "./protocol/index.js";
|
|
|
|
export type CallGatewayOptions = {
|
|
url?: string;
|
|
token?: string;
|
|
password?: string;
|
|
method: string;
|
|
params?: unknown;
|
|
expectFinal?: boolean;
|
|
timeoutMs?: number;
|
|
clientName?: string;
|
|
clientVersion?: string;
|
|
platform?: string;
|
|
mode?: string;
|
|
instanceId?: string;
|
|
minProtocol?: number;
|
|
maxProtocol?: number;
|
|
};
|
|
|
|
export async function callGateway<T = unknown>(
|
|
opts: CallGatewayOptions,
|
|
): Promise<T> {
|
|
const timeoutMs = opts.timeoutMs ?? 10_000;
|
|
const config = loadConfig();
|
|
const isRemoteMode = config.gateway?.mode === "remote";
|
|
const remote = isRemoteMode ? config.gateway.remote : undefined;
|
|
const url =
|
|
(typeof opts.url === "string" && opts.url.trim().length > 0
|
|
? opts.url.trim()
|
|
: undefined) ||
|
|
(typeof remote?.url === "string" && remote.url.trim().length > 0
|
|
? remote.url.trim()
|
|
: undefined) ||
|
|
"ws://127.0.0.1:18789";
|
|
const token =
|
|
(typeof opts.token === "string" && opts.token.trim().length > 0
|
|
? opts.token.trim()
|
|
: undefined) ||
|
|
(isRemoteMode
|
|
? typeof remote?.token === "string" && remote.token.trim().length > 0
|
|
? remote.token.trim()
|
|
: undefined
|
|
: process.env.CLAWDIS_GATEWAY_TOKEN?.trim() ||
|
|
(typeof config.gateway?.auth?.token === "string" &&
|
|
config.gateway.auth.token.trim().length > 0
|
|
? config.gateway.auth.token.trim()
|
|
: undefined));
|
|
const password =
|
|
(typeof opts.password === "string" && opts.password.trim().length > 0
|
|
? opts.password.trim()
|
|
: undefined) ||
|
|
process.env.CLAWDIS_GATEWAY_PASSWORD ||
|
|
(typeof remote?.password === "string" && remote.password.trim().length > 0
|
|
? remote.password.trim()
|
|
: undefined);
|
|
return await new Promise<T>((resolve, reject) => {
|
|
let settled = false;
|
|
let ignoreClose = false;
|
|
const stop = (err?: Error, value?: T) => {
|
|
if (settled) return;
|
|
settled = true;
|
|
clearTimeout(timer);
|
|
if (err) reject(err);
|
|
else resolve(value as T);
|
|
};
|
|
|
|
const client = new GatewayClient({
|
|
url,
|
|
token,
|
|
password,
|
|
instanceId: opts.instanceId ?? randomUUID(),
|
|
clientName: opts.clientName ?? "cli",
|
|
clientVersion: opts.clientVersion ?? "dev",
|
|
platform: opts.platform,
|
|
mode: opts.mode ?? "cli",
|
|
minProtocol: opts.minProtocol ?? PROTOCOL_VERSION,
|
|
maxProtocol: opts.maxProtocol ?? PROTOCOL_VERSION,
|
|
onHelloOk: async () => {
|
|
try {
|
|
const result = await client.request<T>(opts.method, opts.params, {
|
|
expectFinal: opts.expectFinal,
|
|
});
|
|
ignoreClose = true;
|
|
stop(undefined, result);
|
|
client.stop();
|
|
} catch (err) {
|
|
ignoreClose = true;
|
|
client.stop();
|
|
stop(err as Error);
|
|
}
|
|
},
|
|
onClose: (code, reason) => {
|
|
if (settled || ignoreClose) return;
|
|
stop(new Error(`gateway closed (${code}): ${reason}`));
|
|
},
|
|
});
|
|
|
|
const timer = setTimeout(() => {
|
|
ignoreClose = true;
|
|
client.stop();
|
|
stop(new Error("gateway timeout"));
|
|
}, timeoutMs);
|
|
|
|
client.start();
|
|
});
|
|
}
|
|
|
|
export function randomIdempotencyKey() {
|
|
return randomUUID();
|
|
}
|