






















@@ -4,15 +4,36 @@ import fs from "node:fs/promises";
44import os from "node:os";
55import path from "node:path";
66import { setTimeout as delay } from "node:timers/promises";
7+import { pathToFileURL } from "node:url";
78import { promisify } from "node:util";
8-import { assert, connectGateway, type GatewayRpcClient, waitFor } from "./mcp-channels-harness.ts";
9+import type { GatewayRpcClient } from "./mcp-channels-harness.ts";
9101011const execFileAsync = promisify(execFile);
12+const PROBE_PID_WAIT_MS = readPositiveInt(
13+process.env.OPENCLAW_CRON_MCP_CLEANUP_PID_WAIT_MS,
14+120_000,
15+);
16+type McpChannelsHarness = typeof import("./mcp-channels-harness.ts");
17+let mcpChannelsHarness: McpChannelsHarness | undefined;
11181219type CronJob = { id?: string };
1320type CronRunResult = { ok?: boolean; enqueued?: boolean; runId?: string };
1421type AgentRunResult = { runId?: string; status?: string };
152223+async function loadMcpChannelsHarness(): Promise<McpChannelsHarness> {
24+mcpChannelsHarness ??= await import("./mcp-channels-harness.ts");
25+return mcpChannelsHarness;
26+}
27+28+function readPositiveInt(raw: string | undefined, fallback: number): number {
29+const text = (raw ?? "").trim();
30+if (!/^\d+$/u.test(text)) {
31+return fallback;
32+}
33+const parsed = Number(text);
34+return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback;
35+}
36+1637async function readProbePid(pidPath: string): Promise<number | undefined> {
1738try {
1839const raw = (await fs.readFile(pidPath, "utf-8")).trim();
@@ -52,14 +73,19 @@ async function describeProbePid(pid: number): Promise<string | undefined> {
5273}
5374}
547555-async function waitForProbePid(pidPath: string): Promise<number | undefined> {
76+export async function waitForProbePid(
77+pidPath: string,
78+options: { pollMs?: number; timeoutMs?: number } = {},
79+): Promise<number | undefined> {
80+const timeoutMs = options.timeoutMs ?? PROBE_PID_WAIT_MS;
81+const pollMs = options.pollMs ?? 100;
5682const startedAt = Date.now();
57-while (Date.now() - startedAt < 600_000) {
83+while (Date.now() - startedAt < timeoutMs) {
5884const pid = await readProbePid(pidPath);
5985if (pid) {
6086return pid;
6187}
62-await delay(100);
88+await delay(pollMs);
6389}
6490return undefined;
6591}
@@ -128,6 +154,7 @@ async function runCronCleanupScenario(params: {
128154gateway: GatewayRpcClient;
129155pidPath: string;
130156}): Promise<{ jobId: string; runId?: string; pid: number; status?: unknown }> {
157+const { assert, waitFor } = await loadMcpChannelsHarness();
131158const { gateway, pidPath } = params;
132159const job = await gateway.request<CronJob>("cron.add", {
133160name: "cron mcp cleanup docker e2e",
@@ -171,7 +198,7 @@ async function runCronCleanupScenario(params: {
171198const pid = await waitForProbePid(pidPath);
172199assert(
173200pid,
174-`cron MCP probe did not start; missing pid file at ${pidPath}; events=${JSON.stringify(
201+`cron MCP probe did not start within ${PROBE_PID_WAIT_MS}ms; missing pid file at ${pidPath}; events=${JSON.stringify(
175202 gateway.events.slice(-10),
176203 )}`,
177204);
@@ -209,6 +236,7 @@ async function runSubagentCleanupScenario(params: {
209236pidsPath: string;
210237exitPath: string;
211238}): Promise<{ runId: string; exitedPids: number[]; pids: number[] }> {
239+const { assert } = await loadMcpChannelsHarness();
212240const { gateway, pidPath, pidsPath, exitPath } = params;
213241await resetProbeFiles({ pidPath, pidsPath, exitPath });
214242@@ -258,6 +286,7 @@ async function runSubagentCleanupScenario(params: {
258286}
259287260288async function main() {
289+const { assert, connectGateway } = await loadMcpChannelsHarness();
261290const gatewayUrl = process.env.GW_URL?.trim();
262291const gatewayToken = process.env.GW_TOKEN?.trim();
263292const stateDir = process.env.OPENCLAW_STATE_DIR?.trim() || path.join(os.homedir(), ".openclaw");
@@ -283,4 +312,6 @@ async function main() {
283312}
284313}
285314286-await main();
315+if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
316+await main();
317+}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。