From 26ea53cc684e2f9b05b5958cd3f269c18cf2d1c1 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 29 May 2026 16:28:26 -0400 Subject: [PATCH] fix(zai): cap endpoint probe timeouts --- extensions/zai/detect.test.ts | 26 +++++++++++++++++++++++++- extensions/zai/detect.ts | 3 ++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/extensions/zai/detect.test.ts b/extensions/zai/detect.test.ts index b7131889866..386b97b6094 100644 --- a/extensions/zai/detect.test.ts +++ b/extensions/zai/detect.test.ts @@ -1,6 +1,8 @@ -import { describe, expect, it } from "vitest"; +import { afterEach, describe, expect, it, vi } from "vitest"; import { detectZaiEndpoint } from "./detect.js"; +const MAX_TIMER_TIMEOUT_MS = 2_147_000_000; + type FetchResponse = { status: number; body?: unknown }; function makeFetch(map: Record) { @@ -19,6 +21,10 @@ function makeFetch(map: Record) { } describe("detectZaiEndpoint", () => { + afterEach(() => { + vi.restoreAllMocks(); + }); + it("resolves preferred/fallback endpoints and null when probes fail", async () => { const scenarios: Array<{ endpoint?: "global" | "cn" | "coding-global" | "coding-cn"; @@ -114,4 +120,22 @@ describe("detectZaiEndpoint", () => { } } }); + + it("caps oversized probe timeouts before scheduling", async () => { + const timeoutSpy = vi + .spyOn(globalThis, "setTimeout") + .mockImplementation((() => 1) as typeof setTimeout); + vi.spyOn(globalThis, "clearTimeout").mockImplementation(() => undefined); + const fetchFn = makeFetch({ + "https://api.z.ai/api/paas/v4/chat/completions::glm-5.1": { status: 200 }, + }); + + await detectZaiEndpoint({ + apiKey: "sk-test", // pragma: allowlist secret + fetchFn, + timeoutMs: MAX_TIMER_TIMEOUT_MS + 1_000_000, + }); + + expect(timeoutSpy).toHaveBeenCalledWith(expect.any(Function), MAX_TIMER_TIMEOUT_MS); + }); }); diff --git a/extensions/zai/detect.ts b/extensions/zai/detect.ts index 2c87984c172..729a5b6ab62 100644 --- a/extensions/zai/detect.ts +++ b/extensions/zai/detect.ts @@ -1,3 +1,4 @@ +import { resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime"; import { ZAI_CN_BASE_URL, ZAI_CODING_CN_BASE_URL, @@ -113,7 +114,7 @@ export async function detectZaiEndpoint(params: { return null; } - const timeoutMs = params.timeoutMs ?? 5_000; + const timeoutMs = resolveTimerTimeoutMs(params.timeoutMs, 5_000); const probeCandidates = (() => { const general = [ {