mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-14 09:47:17 +00:00
fix(plugins): guard host cleanup extension metadata
This commit is contained in:
@@ -57,4 +57,53 @@ describe("plugin host cleanup config fallback", () => {
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("continues cleanup after unreadable session extension metadata", async () => {
|
||||
const registry = createEmptyPluginRegistry();
|
||||
const runtimeCleanup = vi.fn();
|
||||
const brokenExtension = {
|
||||
pluginId: "broken-extension",
|
||||
pluginName: "Broken Extension",
|
||||
source: "test",
|
||||
} as NonNullable<typeof registry.sessionExtensions>[number];
|
||||
Object.defineProperty(brokenExtension, "extension", {
|
||||
get() {
|
||||
throw new Error("session extension getter exploded");
|
||||
},
|
||||
});
|
||||
registry.sessionExtensions = [brokenExtension];
|
||||
registry.runtimeLifecycles ??= [];
|
||||
registry.runtimeLifecycles.push({
|
||||
pluginId: "healthy-runtime",
|
||||
pluginName: "Healthy Runtime",
|
||||
source: "test",
|
||||
lifecycle: {
|
||||
id: "healthy-cleanup",
|
||||
cleanup: runtimeCleanup,
|
||||
},
|
||||
});
|
||||
|
||||
const result = await runPluginHostCleanup({
|
||||
cfg: {},
|
||||
registry,
|
||||
reason: "disable",
|
||||
});
|
||||
|
||||
expect(runtimeCleanup.mock.calls).toEqual([
|
||||
[
|
||||
{
|
||||
runId: undefined,
|
||||
reason: "disable",
|
||||
sessionKey: undefined,
|
||||
},
|
||||
],
|
||||
]);
|
||||
expect(result.cleanupCount).toBe(1);
|
||||
expect(result.failures).toHaveLength(1);
|
||||
expect(result.failures[0]).toMatchObject({
|
||||
pluginId: "broken-extension",
|
||||
hookId: "session:unknown",
|
||||
});
|
||||
expect(result.failures[0]?.error).toBeInstanceOf(Error);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -324,17 +324,21 @@ function collectSessionEntrySlotKeys(
|
||||
): Set<string> {
|
||||
const slotKeys = new Set<string>();
|
||||
for (const registration of registry?.sessionExtensions ?? []) {
|
||||
if (!shouldCleanPlugin(registration.pluginId, pluginId)) {
|
||||
try {
|
||||
if (!shouldCleanPlugin(registration.pluginId, pluginId)) {
|
||||
continue;
|
||||
}
|
||||
const slotKey = registration.extension.sessionEntrySlotKey;
|
||||
if (slotKey === undefined) {
|
||||
continue;
|
||||
}
|
||||
const normalized = normalizeSessionEntrySlotKey(slotKey);
|
||||
if (normalized.ok) {
|
||||
slotKeys.add(normalized.key);
|
||||
}
|
||||
} catch {
|
||||
continue;
|
||||
}
|
||||
const slotKey = registration.extension.sessionEntrySlotKey;
|
||||
if (slotKey === undefined) {
|
||||
continue;
|
||||
}
|
||||
const normalized = normalizeSessionEntrySlotKey(slotKey);
|
||||
if (normalized.ok) {
|
||||
slotKeys.add(normalized.key);
|
||||
}
|
||||
}
|
||||
return slotKeys;
|
||||
}
|
||||
@@ -400,14 +404,35 @@ export async function runPluginHostCleanup(params: {
|
||||
if (!shouldCleanup()) {
|
||||
return { cleanupCount, failures };
|
||||
}
|
||||
if (!shouldCleanPlugin(registration.pluginId, params.pluginId)) {
|
||||
let pluginId: string;
|
||||
let hookId: string;
|
||||
let cleanup:
|
||||
| ((params: {
|
||||
reason: PluginHostCleanupReason;
|
||||
sessionKey?: string;
|
||||
}) => void | Promise<void>)
|
||||
| undefined;
|
||||
let failurePluginId = params.pluginId ?? "plugin-host";
|
||||
try {
|
||||
pluginId = registration.pluginId;
|
||||
failurePluginId = pluginId;
|
||||
if (!shouldCleanPlugin(pluginId, params.pluginId)) {
|
||||
continue;
|
||||
}
|
||||
const extension = registration.extension;
|
||||
cleanup = extension.cleanup;
|
||||
hookId = `session:${extension.namespace}`;
|
||||
} catch (error) {
|
||||
failures.push({
|
||||
pluginId: failurePluginId,
|
||||
hookId: "session:unknown",
|
||||
error,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
const cleanup = registration.extension.cleanup;
|
||||
if (!cleanup) {
|
||||
continue;
|
||||
}
|
||||
const hookId = `session:${registration.extension.namespace}`;
|
||||
try {
|
||||
await withPluginHostCleanupTimeout(hookId, () =>
|
||||
cleanup({
|
||||
@@ -418,7 +443,7 @@ export async function runPluginHostCleanup(params: {
|
||||
cleanupCount += 1;
|
||||
} catch (error) {
|
||||
failures.push({
|
||||
pluginId: registration.pluginId,
|
||||
pluginId,
|
||||
hookId,
|
||||
error,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user