















@@ -54,7 +54,7 @@ function resolveOpenClawRunner() {
5454return { pnpm: true, baseArgs: ["openclaw"], label: "pnpm openclaw" };
5555}
565657-function makeEnv() {
57+export function makeEnv() {
5858const root = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-kitchen-sink-rpc-"));
5959const home = path.join(root, "home");
6060const stateDir = path.join(home, ".openclaw");
@@ -75,6 +75,31 @@ function makeEnv() {
7575};
7676}
777778+export async function cleanupKitchenSinkEnv(root, options = {}) {
79+if (root) {
80+const attempts = Math.max(1, options.attempts ?? 5);
81+const delayMs = Math.max(0, options.delayMs ?? 250);
82+let lastError;
83+for (let attempt = 1; attempt <= attempts; attempt += 1) {
84+try {
85+fs.rmSync(root, { recursive: true, force: true });
86+return true;
87+} catch (error) {
88+lastError = error;
89+if (attempt < attempts) {
90+await delay(delayMs);
91+}
92+}
93+}
94+if (options.warn !== false) {
95+const message = lastError instanceof Error ? lastError.message : String(lastError);
96+console.error(`Kitchen Sink RPC temp root cleanup failed; preserved ${root}: ${message}`);
97+}
98+return false;
99+}
100+return true;
101+}
102+78103function writeJson(file, value) {
79104fs.mkdirSync(path.dirname(file), { recursive: true });
80105fs.writeFileSync(file, `${JSON.stringify(value, null, 2)}\n`);
@@ -841,53 +866,57 @@ export async function main() {
841866const port = readPositiveInt(process.env.OPENCLAW_KITCHEN_SINK_RPC_PORT, DEFAULT_PORT);
842867const { root, env } = makeEnv();
843868const logPath = path.join(root, "gateway.log");
869+const keepTmp = process.env.OPENCLAW_KITCHEN_SINK_KEEP_TMP === "1";
870+let failed = false;
871+let child;
844872845-console.log(`Kitchen Sink RPC walk using ${PLUGIN_SPEC} via ${runner.label}`);
846-await runOpenClaw(runner, ["plugins", "install", PLUGIN_SPEC], env, {
847-timeoutMs: INSTALL_TIMEOUT_MS,
848-});
849-runner = resolveOpenClawRunner();
850-console.log(`Kitchen Sink RPC runtime runner: ${runner.label}`);
851-configureKitchenSink(env, port);
852-await runOpenClaw(runner, ["plugins", "enable", PLUGIN_ID], env, { timeoutMs: 60000 });
853-const inspect = parseJsonOutput(
854-(await runOpenClaw(runner, ["plugins", "inspect", PLUGIN_ID, "--runtime", "--json"], env))
855-.stdout,
856-);
857-if (inspect?.plugin?.status !== "loaded") {
858-throw new Error(`Kitchen Sink plugin did not inspect as loaded: ${JSON.stringify(inspect)}`);
859-}
860-const inspectPlugin = inspect.plugin ?? {};
861-const inspectProviders = [
862- ...(Array.isArray(inspectPlugin.providerIds) ? inspectPlugin.providerIds : []),
863- ...(Array.isArray(inspectPlugin.providers) ? inspectPlugin.providers : []),
864-];
865-assertIncludesAny(inspectProviders, EXPECTED_PROVIDERS, "plugins inspect providers");
866-867-const child = await startGateway(runner, port, env, logPath);
868873const processSamples = [];
869-const sampleGateway = async () => {
870-const windowsSampleOptions = runner.pnpm
871- ? { windowsCommandLineNeedles: ["gateway", "--port", String(port)] }
872- : {};
873-let sample = await sampleProcess(child.pid, windowsSampleOptions);
874-if (!sample && process.platform === "win32") {
875-sample = await sampleWindowsProcessByPort(port);
876-}
877-if (sample) {
878-processSamples.push(sample);
879-}
880-return sample;
881-};
882874let sampleInFlight = null;
883-const collectTimedSample = () => {
884-sampleInFlight ??= sampleGateway().finally(() => {
885-sampleInFlight = null;
886-});
887-return sampleInFlight;
888-};
889875let sampleTimer;
890876try {
877+console.log(`Kitchen Sink RPC walk using ${PLUGIN_SPEC} via ${runner.label}`);
878+await runOpenClaw(runner, ["plugins", "install", PLUGIN_SPEC], env, {
879+timeoutMs: INSTALL_TIMEOUT_MS,
880+});
881+runner = resolveOpenClawRunner();
882+console.log(`Kitchen Sink RPC runtime runner: ${runner.label}`);
883+configureKitchenSink(env, port);
884+await runOpenClaw(runner, ["plugins", "enable", PLUGIN_ID], env, { timeoutMs: 60000 });
885+const inspect = parseJsonOutput(
886+(await runOpenClaw(runner, ["plugins", "inspect", PLUGIN_ID, "--runtime", "--json"], env))
887+.stdout,
888+);
889+if (inspect?.plugin?.status !== "loaded") {
890+throw new Error(`Kitchen Sink plugin did not inspect as loaded: ${JSON.stringify(inspect)}`);
891+}
892+const inspectPlugin = inspect.plugin ?? {};
893+const inspectProviders = [
894+ ...(Array.isArray(inspectPlugin.providerIds) ? inspectPlugin.providerIds : []),
895+ ...(Array.isArray(inspectPlugin.providers) ? inspectPlugin.providers : []),
896+];
897+assertIncludesAny(inspectProviders, EXPECTED_PROVIDERS, "plugins inspect providers");
898+899+child = await startGateway(runner, port, env, logPath);
900+const sampleGateway = async () => {
901+const windowsSampleOptions = runner.pnpm
902+ ? { windowsCommandLineNeedles: ["gateway", "--port", String(port)] }
903+ : {};
904+let sample = await sampleProcess(child.pid, windowsSampleOptions);
905+if (!sample && process.platform === "win32") {
906+sample = await sampleWindowsProcessByPort(port);
907+}
908+if (sample) {
909+processSamples.push(sample);
910+}
911+return sample;
912+};
913+const collectTimedSample = () => {
914+sampleInFlight ??= sampleGateway().finally(() => {
915+sampleInFlight = null;
916+});
917+return sampleInFlight;
918+};
919+891920await waitForGatewayReady(child, port, logPath);
892921const initialSample = await sampleGateway();
893922sampleTimer = setInterval(() => {
@@ -996,13 +1025,19 @@ export async function main() {
9961025);
9971026console.log("Kitchen Sink RPC walk passed");
9981027} catch (error) {
1028+failed = true;
9991029console.error(tailFile(logPath));
10001030throw error;
10011031} finally {
10021032if (sampleTimer) {
10031033clearInterval(sampleTimer);
10041034}
10051035await stopGateway(child);
1036+if (!failed && !keepTmp) {
1037+await cleanupKitchenSinkEnv(root);
1038+} else if (failed || keepTmp) {
1039+console.error(`Kitchen Sink RPC temp root preserved: ${root}`);
1040+}
10061041}
10071042}
10081043此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。