mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-02 04:04:55 +00:00
130 lines
4.5 KiB
TypeScript
130 lines
4.5 KiB
TypeScript
import { describe, expect, it, vi } from "vitest";
|
|
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
|
import { createPluginRecord } from "./loader-records.js";
|
|
import { createPluginRegistry } from "./registry.js";
|
|
import { getPluginRuntimeGatewayRequestScope } from "./runtime/gateway-request-scope.js";
|
|
import { createPluginRuntime } from "./runtime/index.js";
|
|
import type { PluginRuntime } from "./runtime/types.js";
|
|
|
|
function createTestRegistry(runtime: PluginRuntime) {
|
|
return createPluginRegistry({
|
|
logger: {
|
|
info() {},
|
|
warn() {},
|
|
error() {},
|
|
debug() {},
|
|
},
|
|
runtime,
|
|
activateGlobalSideEffects: false,
|
|
});
|
|
}
|
|
|
|
describe("plugin registry runtime config scope", () => {
|
|
it("adds plugin context to lazy runtime resolution failures", () => {
|
|
const runtime = new Proxy({} as PluginRuntime, {
|
|
get() {
|
|
throw new Error("Unable to resolve plugin runtime module; loader=/tmp/openclaw-loader.js");
|
|
},
|
|
});
|
|
const pluginRegistry = createTestRegistry(runtime);
|
|
const record = createPluginRecord({
|
|
id: "diagnostic-plugin",
|
|
name: "Diagnostic Plugin",
|
|
source: "/plugins/diagnostic-plugin/index.js",
|
|
origin: "global",
|
|
enabled: true,
|
|
configSchema: false,
|
|
});
|
|
const api = pluginRegistry.createApi(record, { config: {} as OpenClawConfig });
|
|
|
|
let thrown: unknown;
|
|
try {
|
|
void api.runtime.version;
|
|
} catch (error) {
|
|
thrown = error;
|
|
}
|
|
|
|
expect(thrown).toBeInstanceOf(Error);
|
|
const message = (thrown as Error).message;
|
|
expect(message).toContain("Unable to resolve plugin runtime module");
|
|
expect(message).toContain("pluginRuntimeContext=pluginId:diagnostic-plugin");
|
|
expect(message).toContain("property:version");
|
|
expect(message).toContain("source:/plugins/diagnostic-plugin/index.js");
|
|
});
|
|
|
|
it("runs config helpers with the owning plugin scope", async () => {
|
|
let currentScope = getPluginRuntimeGatewayRequestScope();
|
|
let mutateScope = getPluginRuntimeGatewayRequestScope();
|
|
let replaceScope = getPluginRuntimeGatewayRequestScope();
|
|
const config = {} as OpenClawConfig;
|
|
const replaceResult = {
|
|
path: "/tmp/openclaw.json",
|
|
previousHash: null,
|
|
persistedHash: "persisted-hash",
|
|
snapshot: { path: "/tmp/openclaw.json" },
|
|
nextConfig: config,
|
|
afterWrite: { mode: "auto" },
|
|
followUp: { mode: "auto", requiresRestart: false },
|
|
} as unknown as Awaited<ReturnType<PluginRuntime["config"]["replaceConfigFile"]>>;
|
|
const mutateConfigFile: PluginRuntime["config"]["mutateConfigFile"] = async () => {
|
|
mutateScope = getPluginRuntimeGatewayRequestScope();
|
|
return {
|
|
...replaceResult,
|
|
result: undefined,
|
|
attempts: 1,
|
|
};
|
|
};
|
|
const replaceConfigFile: PluginRuntime["config"]["replaceConfigFile"] = async () => {
|
|
replaceScope = getPluginRuntimeGatewayRequestScope();
|
|
return replaceResult;
|
|
};
|
|
const loadConfig: PluginRuntime["config"]["loadConfig"] = () => config;
|
|
const writeConfigFile: PluginRuntime["config"]["writeConfigFile"] = async () => {};
|
|
const configRuntime = {
|
|
current: vi.fn(() => {
|
|
currentScope = getPluginRuntimeGatewayRequestScope();
|
|
return config;
|
|
}),
|
|
mutateConfigFile,
|
|
replaceConfigFile,
|
|
loadConfig,
|
|
writeConfigFile,
|
|
} satisfies PluginRuntime["config"];
|
|
const runtime = createPluginRuntime();
|
|
runtime.config = configRuntime;
|
|
const pluginRegistry = createTestRegistry(runtime);
|
|
const record = createPluginRecord({
|
|
id: "legacy-plugin",
|
|
name: "Legacy Plugin",
|
|
source: "/plugins/legacy-plugin/index.js",
|
|
origin: "global",
|
|
enabled: true,
|
|
configSchema: false,
|
|
});
|
|
const api = pluginRegistry.createApi(record, { config });
|
|
|
|
expect(api.runtime.config.current()).toBe(config);
|
|
await api.runtime.config.mutateConfigFile({
|
|
afterWrite: { mode: "none", reason: "test" },
|
|
mutate: () => undefined,
|
|
});
|
|
await api.runtime.config.replaceConfigFile({
|
|
nextConfig: config,
|
|
afterWrite: { mode: "none", reason: "test" },
|
|
});
|
|
|
|
expect(currentScope).toMatchObject({
|
|
pluginId: "legacy-plugin",
|
|
pluginSource: "/plugins/legacy-plugin/index.js",
|
|
});
|
|
expect(mutateScope).toMatchObject({
|
|
pluginId: "legacy-plugin",
|
|
pluginSource: "/plugins/legacy-plugin/index.js",
|
|
});
|
|
expect(replaceScope).toMatchObject({
|
|
pluginId: "legacy-plugin",
|
|
pluginSource: "/plugins/legacy-plugin/index.js",
|
|
});
|
|
});
|
|
});
|