mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-17 20:32:25 +03:00
Merged in the 2026-09-16 sweep of the maintainer's own open PRs, at the owner's explicit instruction. No push was made to the PR branch: the merge took the head as the owning session left it (verified OPEN, non-draft and MERGEABLE against the release tip immediately before merging).
84 lines
3.5 KiB
TypeScript
84 lines
3.5 KiB
TypeScript
/**
|
|
* Regression for GitHub issue #13232 — "[BUG] Z.ai web error".
|
|
*
|
|
* The Z.ai web transport drives a real headed Chromium browser (via Playwright) to get past
|
|
* Z.ai's CAPTCHA. When the local Playwright Chromium binary is missing,
|
|
* `browserType.launch()` throws "Executable doesn't exist at ...". Before this fix, zai-web.ts
|
|
* had no classification for that failure and surfaced it as a plain 502 with no fallback hint —
|
|
* a status that trips the whole-provider circuit breaker (`AGENTS.md` → "Provider Circuit
|
|
* Breaker") as if the upstream itself were failing, instead of applying the intended
|
|
* host/config connection cooldown. This mirrors the exact failure class already handled for
|
|
* Gemini Web in #3516 (`isMissingBrowserExecutable`, now shared via
|
|
* `open-sse/executors/browserExecutableCheck.ts`).
|
|
*/
|
|
import { describe, it, before, after } from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import fs from "node:fs";
|
|
import os from "node:os";
|
|
import path from "node:path";
|
|
import { Buffer } from "node:buffer";
|
|
|
|
const mod = await import("../../open-sse/executors/zai-web.ts");
|
|
|
|
const TEST_TOKEN = `e30.${Buffer.from(JSON.stringify({ id: "user-123" })).toString("base64url")}.sig`;
|
|
|
|
describe("issue #13232 — Z.ai browser transport classifies a missing Chromium install", () => {
|
|
let emptyBrowsersDir: string;
|
|
let originalBrowsersPath: string | undefined;
|
|
|
|
before(() => {
|
|
emptyBrowsersDir = fs.mkdtempSync(path.join(os.tmpdir(), "playwright-empty-"));
|
|
originalBrowsersPath = process.env.PLAYWRIGHT_BROWSERS_PATH;
|
|
// Force chromium.launch() to genuinely fail with the exact class of error the reporter hit
|
|
// ("Executable doesn't exist at ..."), without touching any real ~/.cache/ms-playwright
|
|
// install.
|
|
process.env.PLAYWRIGHT_BROWSERS_PATH = emptyBrowsersDir;
|
|
});
|
|
|
|
after(() => {
|
|
if (originalBrowsersPath === undefined) {
|
|
delete process.env.PLAYWRIGHT_BROWSERS_PATH;
|
|
} else {
|
|
process.env.PLAYWRIGHT_BROWSERS_PATH = originalBrowsersPath;
|
|
}
|
|
fs.rmSync(emptyBrowsersDir, { recursive: true, force: true });
|
|
});
|
|
|
|
it(
|
|
"returns a classified 503 + X-Omni-Fallback-Hint: connection_cooldown instead of a bare " +
|
|
"502 (contrast: gemini-web.ts isMissingBrowserExecutable, #3516)",
|
|
async () => {
|
|
const executor = new mod.ZaiWebExecutor();
|
|
const body = { model: "glm-5.3-flash", messages: [{ role: "user", content: "hi" }] };
|
|
const result = await executor.execute({
|
|
model: "glm-5.3-flash",
|
|
body,
|
|
stream: false,
|
|
credentials: { apiKey: TEST_TOKEN },
|
|
signal: null,
|
|
});
|
|
|
|
assert.ok("response" in result, "expected an error Response, not a stream result");
|
|
const response = (result as { response: Response }).response;
|
|
const payload = (await response.json()) as { error?: { message?: string } };
|
|
|
|
assert.equal(
|
|
response.status,
|
|
503,
|
|
"zai-web must classify a missing local Chromium install as a host/config error (503), " +
|
|
"not a generic retryable 502 that trips the whole-provider circuit breaker."
|
|
);
|
|
assert.equal(
|
|
response.headers.get("X-Omni-Fallback-Hint"),
|
|
"connection_cooldown",
|
|
"the connection-cooldown hint must be set so accountFallback applies a short cooldown " +
|
|
"instead of tripping the provider circuit breaker."
|
|
);
|
|
assert.match(
|
|
payload.error?.message ?? "",
|
|
/Playwright Chromium browser.*not installed.*npx playwright install chromium/s
|
|
);
|
|
}
|
|
);
|
|
});
|