fix(check): repair plugin runtime type drift batch

This commit is contained in:
Peter Steinberger
2026-04-06 15:52:44 +01:00
parent 8fe7b3730f
commit d12029a15a
5 changed files with 90 additions and 80 deletions

View File

@@ -1,26 +1,27 @@
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
const resolveRuntimePluginRegistryMock = vi.fn((_options: unknown): unknown => undefined);
const applyPluginAutoEnableMock = vi.fn<(params: { config: unknown; env?: unknown }) => unknown>();
const getMemoryRuntimeMock = vi.fn();
const resolveAgentWorkspaceDirMock = vi.fn(
(_config: unknown, _agentId: unknown): unknown => undefined,
);
const resolveDefaultAgentIdMock = vi.fn((_config: unknown) => "default");
const resolveRuntimePluginRegistryMock =
vi.fn<typeof import("./loader.js").resolveRuntimePluginRegistry>();
const applyPluginAutoEnableMock =
vi.fn<typeof import("../config/plugin-auto-enable.js").applyPluginAutoEnable>();
const getMemoryRuntimeMock = vi.fn<typeof import("./memory-state.js").getMemoryRuntime>();
const resolveAgentWorkspaceDirMock =
vi.fn<typeof import("../agents/agent-scope.js").resolveAgentWorkspaceDir>();
const resolveDefaultAgentIdMock = vi.fn<
typeof import("../agents/agent-scope.js").resolveDefaultAgentId
>(() => "default");
vi.mock("../config/plugin-auto-enable.js", () => ({
applyPluginAutoEnable: (params: { config: unknown; env?: unknown }) =>
applyPluginAutoEnableMock(params),
applyPluginAutoEnable: applyPluginAutoEnableMock,
}));
vi.mock("../agents/agent-scope.js", () => ({
resolveAgentWorkspaceDir: (config: unknown, agentId: unknown) =>
resolveAgentWorkspaceDirMock(config, agentId),
resolveDefaultAgentId: (config: unknown) => resolveDefaultAgentIdMock(config),
resolveAgentWorkspaceDir: resolveAgentWorkspaceDirMock,
resolveDefaultAgentId: resolveDefaultAgentIdMock,
}));
vi.mock("./loader.js", () => ({
resolveRuntimePluginRegistry: (options: unknown) => resolveRuntimePluginRegistryMock(options),
resolveRuntimePluginRegistry: resolveRuntimePluginRegistryMock,
}));
vi.mock("./memory-state.js", () => ({
@@ -129,12 +130,12 @@ describe("memory runtime auto-enable loading", () => {
getMemoryRuntimeMock.mockReset();
resolveAgentWorkspaceDirMock.mockReset();
resolveDefaultAgentIdMock.mockClear();
applyPluginAutoEnableMock.mockImplementation((params: { config: unknown }) => ({
config: params.config,
applyPluginAutoEnableMock.mockImplementation((params) => ({
config: params.config ?? {},
changes: [],
autoEnabledReasons: {},
}));
resolveAgentWorkspaceDirMock.mockReturnValue(undefined);
resolveAgentWorkspaceDirMock.mockReturnValue("/resolved-workspace");
});
it.each([
@@ -177,6 +178,8 @@ describe("memory runtime auto-enable loading", () => {
config: {},
setup: () => {
const runtime = {
getMemorySearchManager: vi.fn(async () => ({ manager: null, error: "no index" })),
resolveMemoryBackendConfig: vi.fn(() => ({ backend: "builtin" as const })),
closeAllMemorySearchManagers: vi.fn(async () => {}),
};
getMemoryRuntimeMock.mockReturnValue(runtime);

View File

@@ -1,28 +1,29 @@
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
const loadConfigMock = vi.fn();
const applyPluginAutoEnableMock = vi.fn<(params: { config: unknown; env?: unknown }) => unknown>();
const resolveAgentWorkspaceDirMock = vi.fn(
(_config: unknown, _agentId: unknown): string => "/resolved-workspace",
);
const resolveDefaultAgentIdMock = vi.fn((_config: unknown): string => "default");
const loadConfigMock = vi.fn<typeof import("../../config/config.js").loadConfig>();
const applyPluginAutoEnableMock =
vi.fn<typeof import("../../config/plugin-auto-enable.js").applyPluginAutoEnable>();
const resolveAgentWorkspaceDirMock = vi.fn<
typeof import("../../agents/agent-scope.js").resolveAgentWorkspaceDir
>(() => "/resolved-workspace");
const resolveDefaultAgentIdMock = vi.fn<
typeof import("../../agents/agent-scope.js").resolveDefaultAgentId
>(() => "default");
let resolvePluginRuntimeLoadContext: typeof import("./load-context.js").resolvePluginRuntimeLoadContext;
let buildPluginRuntimeLoadOptions: typeof import("./load-context.js").buildPluginRuntimeLoadOptions;
vi.mock("../../config/config.js", () => ({
loadConfig: () => loadConfigMock(),
loadConfig: loadConfigMock,
}));
vi.mock("../../config/plugin-auto-enable.js", () => ({
applyPluginAutoEnable: (params: { config: unknown; env?: unknown }) =>
applyPluginAutoEnableMock(params),
applyPluginAutoEnable: applyPluginAutoEnableMock,
}));
vi.mock("../../agents/agent-scope.js", () => ({
resolveAgentWorkspaceDir: (config: unknown, agentId: unknown) =>
resolveAgentWorkspaceDirMock(config, agentId),
resolveDefaultAgentId: (config: unknown) => resolveDefaultAgentIdMock(config),
resolveAgentWorkspaceDir: resolveAgentWorkspaceDirMock,
resolveDefaultAgentId: resolveDefaultAgentIdMock,
}));
describe("resolvePluginRuntimeLoadContext", () => {
@@ -38,8 +39,8 @@ describe("resolvePluginRuntimeLoadContext", () => {
resolveDefaultAgentIdMock.mockClear();
loadConfigMock.mockReturnValue({ plugins: {} });
applyPluginAutoEnableMock.mockImplementation((params: { config: unknown }) => ({
config: params.config,
applyPluginAutoEnableMock.mockImplementation((params) => ({
config: params.config ?? {},
changes: [],
autoEnabledReasons: {},
}));

View File

@@ -1,43 +1,54 @@
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import { createEmptyPluginRegistry } from "../registry.js";
const loadOpenClawPluginsMock = vi.fn((_options: unknown): unknown => undefined);
const getActivePluginRegistryMock = vi.fn<() => unknown>(() => undefined);
const resolveConfiguredChannelPluginIdsMock = vi.fn(
(_options: unknown): string[] | undefined => undefined,
);
const resolveChannelPluginIdsMock = vi.fn((_options: unknown): string[] | undefined => undefined);
const applyPluginAutoEnableMock = vi.fn<(params: { config: unknown; env?: unknown }) => unknown>();
const resolveAgentWorkspaceDirMock = vi.fn(
(_config: unknown, _agentId: unknown): string => "/resolved-workspace",
);
const resolveDefaultAgentIdMock = vi.fn((_config: unknown): string => "default");
const mocks = vi.hoisted(() => ({
loadOpenClawPlugins: vi.fn<typeof import("../loader.js").loadOpenClawPlugins>(),
getActivePluginRegistry: vi.fn<typeof import("../runtime.js").getActivePluginRegistry>(),
resolveConfiguredChannelPluginIds:
vi.fn<typeof import("../channel-plugin-ids.js").resolveConfiguredChannelPluginIds>(),
resolveChannelPluginIds:
vi.fn<typeof import("../channel-plugin-ids.js").resolveChannelPluginIds>(),
applyPluginAutoEnable:
vi.fn<typeof import("../../config/plugin-auto-enable.js").applyPluginAutoEnable>(),
resolveAgentWorkspaceDir: vi.fn<
typeof import("../../agents/agent-scope.js").resolveAgentWorkspaceDir
>(() => "/resolved-workspace"),
resolveDefaultAgentId: vi.fn<typeof import("../../agents/agent-scope.js").resolveDefaultAgentId>(
() => "default",
),
}));
let ensurePluginRegistryLoaded: typeof import("./runtime-registry-loader.js").ensurePluginRegistryLoaded;
let resetPluginRegistryLoadedForTests: typeof import("./runtime-registry-loader.js").__testing.resetPluginRegistryLoadedForTests;
vi.mock("../loader.js", () => ({
loadOpenClawPlugins: (options: unknown) => loadOpenClawPluginsMock(options),
loadOpenClawPlugins: (...args: Parameters<typeof mocks.loadOpenClawPlugins>) =>
mocks.loadOpenClawPlugins(...args),
}));
vi.mock("../runtime.js", () => ({
getActivePluginRegistry: () => getActivePluginRegistryMock(),
getActivePluginRegistry: (...args: Parameters<typeof mocks.getActivePluginRegistry>) =>
mocks.getActivePluginRegistry(...args),
}));
vi.mock("../channel-plugin-ids.js", () => ({
resolveConfiguredChannelPluginIds: (options: unknown) =>
resolveConfiguredChannelPluginIdsMock(options),
resolveChannelPluginIds: (options: unknown) => resolveChannelPluginIdsMock(options),
resolveConfiguredChannelPluginIds: (
...args: Parameters<typeof mocks.resolveConfiguredChannelPluginIds>
) => mocks.resolveConfiguredChannelPluginIds(...args),
resolveChannelPluginIds: (...args: Parameters<typeof mocks.resolveChannelPluginIds>) =>
mocks.resolveChannelPluginIds(...args),
}));
vi.mock("../../config/plugin-auto-enable.js", () => ({
applyPluginAutoEnable: (params: { config: unknown; env?: unknown }) =>
applyPluginAutoEnableMock(params),
applyPluginAutoEnable: (...args: Parameters<typeof mocks.applyPluginAutoEnable>) =>
mocks.applyPluginAutoEnable(...args),
}));
vi.mock("../../agents/agent-scope.js", () => ({
resolveAgentWorkspaceDir: (config: unknown, agentId: unknown) =>
resolveAgentWorkspaceDirMock(config, agentId),
resolveDefaultAgentId: (config: unknown) => resolveDefaultAgentIdMock(config),
resolveAgentWorkspaceDir: (...args: Parameters<typeof mocks.resolveAgentWorkspaceDir>) =>
mocks.resolveAgentWorkspaceDir(...args),
resolveDefaultAgentId: (...args: Parameters<typeof mocks.resolveDefaultAgentId>) =>
mocks.resolveDefaultAgentId(...args),
}));
describe("ensurePluginRegistryLoaded", () => {
@@ -48,21 +59,17 @@ describe("ensurePluginRegistryLoaded", () => {
});
beforeEach(() => {
loadOpenClawPluginsMock.mockReset();
getActivePluginRegistryMock.mockReset();
resolveConfiguredChannelPluginIdsMock.mockReset();
resolveChannelPluginIdsMock.mockReset();
applyPluginAutoEnableMock.mockReset();
resolveAgentWorkspaceDirMock.mockClear();
resolveDefaultAgentIdMock.mockClear();
mocks.loadOpenClawPlugins.mockReset();
mocks.getActivePluginRegistry.mockReset();
mocks.resolveConfiguredChannelPluginIds.mockReset();
mocks.resolveChannelPluginIds.mockReset();
mocks.applyPluginAutoEnable.mockReset();
mocks.resolveAgentWorkspaceDir.mockClear();
mocks.resolveDefaultAgentId.mockClear();
resetPluginRegistryLoadedForTests();
getActivePluginRegistryMock.mockReturnValue({
plugins: [],
channels: [],
tools: [],
});
applyPluginAutoEnableMock.mockImplementation((params: { config: unknown }) => ({
mocks.getActivePluginRegistry.mockReturnValue(createEmptyPluginRegistry());
mocks.applyPluginAutoEnable.mockImplementation((params) => ({
config:
params.config && typeof params.config === "object"
? {
@@ -73,7 +80,7 @@ describe("ensurePluginRegistryLoaded", () => {
},
},
}
: params.config,
: {},
changes: [],
autoEnabledReasons: {
demo: ["demo configured"],
@@ -93,7 +100,7 @@ describe("ensurePluginRegistryLoaded", () => {
};
const env = { HOME: "/tmp/openclaw-home" } as NodeJS.ProcessEnv;
resolveConfiguredChannelPluginIdsMock.mockReturnValue(["demo-channel"]);
mocks.resolveConfiguredChannelPluginIds.mockReturnValue(["demo-channel"]);
ensurePluginRegistryLoaded({
scope: "configured-channels",
config: rawConfig as never,
@@ -101,18 +108,18 @@ describe("ensurePluginRegistryLoaded", () => {
activationSourceConfig: { plugins: { allow: ["demo-channel"] } } as never,
});
expect(resolveConfiguredChannelPluginIdsMock).toHaveBeenCalledWith(
expect(mocks.resolveConfiguredChannelPluginIds).toHaveBeenCalledWith(
expect.objectContaining({
config: resolvedConfig,
env,
workspaceDir: "/resolved-workspace",
}),
);
expect(applyPluginAutoEnableMock).toHaveBeenCalledWith({
expect(mocks.applyPluginAutoEnable).toHaveBeenCalledWith({
config: rawConfig,
env,
});
expect(loadOpenClawPluginsMock).toHaveBeenCalledWith(
expect(mocks.loadOpenClawPlugins).toHaveBeenCalledWith(
expect.objectContaining({
config: resolvedConfig,
activationSourceConfig: { plugins: { allow: ["demo-channel"] } },
@@ -138,12 +145,12 @@ describe("ensurePluginRegistryLoaded", () => {
onlyPluginIds: ["demo-b"],
});
expect(loadOpenClawPluginsMock).toHaveBeenCalledTimes(2);
expect(loadOpenClawPluginsMock).toHaveBeenNthCalledWith(
expect(mocks.loadOpenClawPlugins).toHaveBeenCalledTimes(2);
expect(mocks.loadOpenClawPlugins).toHaveBeenNthCalledWith(
1,
expect.objectContaining({ onlyPluginIds: ["demo-a"] }),
);
expect(loadOpenClawPluginsMock).toHaveBeenNthCalledWith(
expect(mocks.loadOpenClawPlugins).toHaveBeenNthCalledWith(
2,
expect.objectContaining({ onlyPluginIds: ["demo-b"] }),
);

View File

@@ -154,7 +154,7 @@ export function buildWebProviderSnapshotCacheKey(params: {
bundledAllowlistCompat?: boolean;
onlyPluginIds?: readonly string[];
origin?: PluginManifestRecord["origin"];
envKey: string;
envKey: Record<string, string>;
}): string {
return JSON.stringify({
workspaceDir: params.workspaceDir ?? "",
@@ -163,7 +163,7 @@ export function buildWebProviderSnapshotCacheKey(params: {
onlyPluginIds: [...new Set(params.onlyPluginIds ?? [])].toSorted((left, right) =>
left.localeCompare(right),
),
env: params.envKey,
env: Object.entries(params.envKey).toSorted(([left], [right]) => left.localeCompare(right)),
});
}

View File

@@ -9,8 +9,7 @@ import type {
import { pushInactiveSurfaceWarning, pushWarning } from "./runtime-shared.js";
import type { RuntimeWebDiagnostic, RuntimeWebDiagnosticCode } from "./runtime-web-tools.types.js";
type RuntimeWebWarningDiagnosticCode = Extract<RuntimeWebDiagnosticCode, SecretResolverWarningCode>;
type RuntimeWebWarningCode = Extract<RuntimeWebDiagnosticCode, SecretResolverWarningCode>;
export type SecretResolutionResult<TSource extends string> = {
value?: string;
source: TSource;
@@ -49,9 +48,9 @@ export type RuntimeWebProviderSelectionParams<
context: ResolverContext;
defaults: SecretDefaults | undefined;
deferKeylessFallback: boolean;
fallbackUsedCode: RuntimeWebWarningDiagnosticCode;
noFallbackCode: RuntimeWebWarningDiagnosticCode;
autoDetectSelectedCode: RuntimeWebDiagnosticCode;
fallbackUsedCode: RuntimeWebWarningCode;
noFallbackCode: RuntimeWebWarningCode;
autoDetectSelectedCode: RuntimeWebWarningCode;
readConfiguredCredential: (params: {
provider: TProvider;
config: OpenClawConfig;
@@ -140,7 +139,7 @@ export type ResolveRuntimeWebProviderSurfaceParams<
toolConfig: TToolConfig;
diagnostics: RuntimeWebDiagnostic[];
metadataDiagnostics: RuntimeWebDiagnostic[];
invalidAutoDetectCode: RuntimeWebWarningDiagnosticCode;
invalidAutoDetectCode: RuntimeWebWarningCode;
sourceConfig: OpenClawConfig;
context: ResolverContext;
resolveProviders: (params: { configuredBundledPluginId?: string }) => TProvider[];