mirror of https://github.com/openclaw/openclaw.git
99 lines
2.6 KiB
TypeScript
99 lines
2.6 KiB
TypeScript
import { createServer } from "node:http";
|
|
import type { AddressInfo } from "node:net";
|
|
import { vi } from "vitest";
|
|
import type { ClawdbotConfig } from "../runtime-api.js";
|
|
import type { monitorFeishuProvider } from "./monitor.js";
|
|
|
|
export async function getFreePort(): Promise<number> {
|
|
const server = createServer();
|
|
await new Promise<void>((resolve) => server.listen(0, "127.0.0.1", () => resolve()));
|
|
const address = server.address() as AddressInfo | null;
|
|
if (!address) {
|
|
throw new Error("missing server address");
|
|
}
|
|
await new Promise<void>((resolve) => server.close(() => resolve()));
|
|
return address.port;
|
|
}
|
|
|
|
async function waitUntilServerReady(url: string): Promise<void> {
|
|
for (let i = 0; i < 50; i += 1) {
|
|
try {
|
|
const response = await fetch(url, { method: "GET" });
|
|
if (response.status >= 200 && response.status < 500) {
|
|
return;
|
|
}
|
|
} catch {
|
|
// retry
|
|
}
|
|
await new Promise((resolve) => setTimeout(resolve, 20));
|
|
}
|
|
throw new Error(`server did not start: ${url}`);
|
|
}
|
|
|
|
export function buildWebhookConfig(params: {
|
|
accountId: string;
|
|
path: string;
|
|
port: number;
|
|
verificationToken?: string;
|
|
encryptKey?: string;
|
|
}): ClawdbotConfig {
|
|
return {
|
|
channels: {
|
|
feishu: {
|
|
enabled: true,
|
|
accounts: {
|
|
[params.accountId]: {
|
|
enabled: true,
|
|
appId: "cli_test",
|
|
appSecret: "secret_test", // pragma: allowlist secret
|
|
connectionMode: "webhook",
|
|
webhookHost: "127.0.0.1",
|
|
webhookPort: params.port,
|
|
webhookPath: params.path,
|
|
encryptKey: params.encryptKey,
|
|
verificationToken: params.verificationToken,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
} as ClawdbotConfig;
|
|
}
|
|
|
|
export async function withRunningWebhookMonitor(
|
|
params: {
|
|
accountId: string;
|
|
path: string;
|
|
verificationToken: string;
|
|
encryptKey: string;
|
|
},
|
|
monitor: typeof monitorFeishuProvider,
|
|
run: (url: string) => Promise<void>,
|
|
) {
|
|
const port = await getFreePort();
|
|
const cfg = buildWebhookConfig({
|
|
accountId: params.accountId,
|
|
path: params.path,
|
|
port,
|
|
encryptKey: params.encryptKey,
|
|
verificationToken: params.verificationToken,
|
|
});
|
|
|
|
const abortController = new AbortController();
|
|
const runtime = { log: vi.fn(), error: vi.fn(), exit: vi.fn() };
|
|
const monitorPromise = monitor({
|
|
config: cfg,
|
|
runtime,
|
|
abortSignal: abortController.signal,
|
|
});
|
|
|
|
const url = `http://127.0.0.1:${port}${params.path}`;
|
|
await waitUntilServerReady(url);
|
|
|
|
try {
|
|
await run(url);
|
|
} finally {
|
|
abortController.abort();
|
|
await monitorPromise;
|
|
}
|
|
}
|