mirror of https://github.com/openclaw/openclaw.git
fix: add facade recursion regression coverage (#57508) (thanks @openperf)
This commit is contained in:
parent
9a03fe8181
commit
0b632dde8c
|
|
@ -96,6 +96,7 @@ Docs: https://docs.openclaw.ai
|
|||
- Agents/Anthropic failover: treat Anthropic `api_error` payloads with `An unexpected error occurred while processing the response` as transient so retry/fallback can engage instead of surfacing a terminal failure. (#57441) Thanks @zijiess and @vincentkoc.
|
||||
- Agents/compaction: keep late compaction-retry rejections handled after the aggregate timeout path wins without swallowing real pre-timeout wait failures, so timed-out retries no longer surface an unhandled rejection on later unsubscribe. (#57451) Thanks @mpz4life and @vincentkoc.
|
||||
- Matrix/delivery recovery: treat Synapse `User not in room` replay failures as permanent during startup recovery so poisoned queued messages move to `failed/` instead of crash-looping Matrix after restart. (#57426) thanks @dlardo.
|
||||
- Plugins/facades: guard bundled plugin facade loads with a cache-first sentinel so circular re-entry stops crashing `xai`, `sglang`, and `vllm` during gateway plugin startup. (#57508) Thanks @openperf.
|
||||
|
||||
## 2026.3.28
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,36 @@ function createThrowingPluginDir(prefix: string): string {
|
|||
return rootDir;
|
||||
}
|
||||
|
||||
function createCircularPluginDir(prefix: string): string {
|
||||
const rootDir = fs.mkdtempSync(path.join(os.tmpdir(), prefix));
|
||||
tempDirs.push(rootDir);
|
||||
fs.mkdirSync(path.join(rootDir, "demo"), { recursive: true });
|
||||
fs.writeFileSync(
|
||||
path.join(rootDir, "facade.mjs"),
|
||||
[
|
||||
`import { loadBundledPluginPublicSurfaceModuleSync } from ${JSON.stringify(
|
||||
new URL("./facade-runtime.js", import.meta.url).href,
|
||||
)};`,
|
||||
`export const marker = loadBundledPluginPublicSurfaceModuleSync({ dirName: "demo", artifactBasename: "api.js" }).marker;`,
|
||||
"",
|
||||
].join("\n"),
|
||||
"utf8",
|
||||
);
|
||||
fs.writeFileSync(
|
||||
path.join(rootDir, "demo", "helper.js"),
|
||||
['import { marker } from "../facade.mjs";', "export const circularMarker = marker;", ""].join(
|
||||
"\n",
|
||||
),
|
||||
"utf8",
|
||||
);
|
||||
fs.writeFileSync(
|
||||
path.join(rootDir, "demo", "api.js"),
|
||||
['import "./helper.js";', 'export const marker = "circular-ok";', ""].join("\n"),
|
||||
"utf8",
|
||||
);
|
||||
return rootDir;
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
if (originalBundledPluginsDir === undefined) {
|
||||
|
|
@ -79,6 +109,18 @@ describe("plugin-sdk facade runtime", () => {
|
|||
expect(first.marker).toBe("identity-check");
|
||||
});
|
||||
|
||||
it("breaks circular facade re-entry during module evaluation", () => {
|
||||
const dir = createCircularPluginDir("openclaw-facade-circular-");
|
||||
process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = dir;
|
||||
|
||||
const loaded = loadBundledPluginPublicSurfaceModuleSync<{ marker: string }>({
|
||||
dirName: "demo",
|
||||
artifactBasename: "api.js",
|
||||
});
|
||||
|
||||
expect(loaded.marker).toBe("circular-ok");
|
||||
});
|
||||
|
||||
it("clears the cache on load failure so retries re-execute", () => {
|
||||
const dir = createThrowingPluginDir("openclaw-facade-throw-");
|
||||
process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = dir;
|
||||
|
|
|
|||
Loading…
Reference in New Issue