mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 14:20:44 +00:00
perf(tests): trim plugin and gateway hot paths
This commit is contained in:
@@ -2,7 +2,7 @@ import * as fs from "node:fs/promises";
|
||||
import type { IncomingMessage, ServerResponse } from "node:http";
|
||||
import * as os from "node:os";
|
||||
import * as path from "node:path";
|
||||
import { beforeEach, describe, expect, it, test, vi } from "vitest";
|
||||
import { beforeAll, beforeEach, describe, expect, it, test, vi } from "vitest";
|
||||
import { defaultVoiceWakeTriggers } from "../infra/voicewake.js";
|
||||
import { handleControlUiHttpRequest } from "./control-ui.js";
|
||||
import {
|
||||
@@ -46,28 +46,15 @@ vi.mock("ws", () => ({
|
||||
|
||||
let GatewayClient: typeof import("./client.js").GatewayClient;
|
||||
|
||||
async function loadFreshGatewayClientModuleForTest() {
|
||||
vi.resetModules();
|
||||
vi.doMock("ws", () => ({
|
||||
WebSocket: class MockWebSocket {
|
||||
on = vi.fn();
|
||||
close = vi.fn();
|
||||
send = vi.fn();
|
||||
|
||||
constructor(url: unknown, opts: unknown) {
|
||||
wsMockState.last = { url, opts };
|
||||
}
|
||||
},
|
||||
}));
|
||||
({ GatewayClient } = await import("./client.js"));
|
||||
}
|
||||
|
||||
beforeEach(async () => {
|
||||
wsMockState.last = null;
|
||||
await loadFreshGatewayClientModuleForTest();
|
||||
});
|
||||
|
||||
describe("GatewayClient", () => {
|
||||
beforeAll(async () => {
|
||||
({ GatewayClient } = await import("./client.js"));
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
wsMockState.last = null;
|
||||
});
|
||||
|
||||
async function withControlUiRoot(
|
||||
params: { faviconSvg?: string; indexHtml?: string },
|
||||
run: (tmp: string) => Promise<void>,
|
||||
|
||||
@@ -47,6 +47,11 @@ export type BundledPluginCompatibleActivationInputs = PluginActivationInputs & {
|
||||
compatPluginIds: string[];
|
||||
};
|
||||
|
||||
export type BundledPluginCompatibleLoadValues = Pick<
|
||||
BundledPluginCompatibleActivationInputs,
|
||||
"rawConfig" | "config" | "activationSourceConfig" | "autoEnabledReasons" | "compatPluginIds"
|
||||
>;
|
||||
|
||||
export function withActivatedPluginIds(params: {
|
||||
config?: OpenClawConfig;
|
||||
pluginIds: readonly string[];
|
||||
@@ -235,3 +240,70 @@ export function resolveBundledPluginCompatibleActivationInputs(params: {
|
||||
compatPluginIds,
|
||||
};
|
||||
}
|
||||
|
||||
export function resolveBundledPluginCompatibleLoadValues(params: {
|
||||
rawConfig?: OpenClawConfig;
|
||||
resolvedConfig?: OpenClawConfig;
|
||||
autoEnabledReasons?: Record<string, string[]>;
|
||||
env?: NodeJS.ProcessEnv;
|
||||
workspaceDir?: string;
|
||||
onlyPluginIds?: readonly string[];
|
||||
applyAutoEnable?: boolean;
|
||||
compatMode: PluginActivationBundledCompatMode;
|
||||
resolveCompatPluginIds: (params: {
|
||||
config?: OpenClawConfig;
|
||||
workspaceDir?: string;
|
||||
env?: NodeJS.ProcessEnv;
|
||||
onlyPluginIds?: readonly string[];
|
||||
}) => string[];
|
||||
}): BundledPluginCompatibleLoadValues {
|
||||
const env = params.env ?? process.env;
|
||||
const rawConfig = params.rawConfig ?? params.resolvedConfig;
|
||||
let resolvedConfig = params.resolvedConfig ?? params.rawConfig;
|
||||
let autoEnabledReasons = params.autoEnabledReasons ?? {};
|
||||
|
||||
if (params.applyAutoEnable && rawConfig !== undefined) {
|
||||
const autoEnabled = applyPluginAutoEnable({
|
||||
config: rawConfig,
|
||||
env,
|
||||
});
|
||||
resolvedConfig = autoEnabled.config;
|
||||
autoEnabledReasons = autoEnabled.autoEnabledReasons;
|
||||
}
|
||||
|
||||
const allowlistCompatEnabled = params.compatMode.allowlist === true;
|
||||
const shouldResolveCompatPluginIds =
|
||||
allowlistCompatEnabled ||
|
||||
params.compatMode.enablement === "always" ||
|
||||
(params.compatMode.enablement === "allowlist" && allowlistCompatEnabled) ||
|
||||
params.compatMode.vitest === true;
|
||||
const compatPluginIds = shouldResolveCompatPluginIds
|
||||
? params.resolveCompatPluginIds({
|
||||
config: resolvedConfig,
|
||||
workspaceDir: params.workspaceDir,
|
||||
env,
|
||||
onlyPluginIds: params.onlyPluginIds,
|
||||
})
|
||||
: [];
|
||||
const config = applyPluginCompatibilityOverrides({
|
||||
config: resolvedConfig,
|
||||
compat: {
|
||||
allowlistPluginIds: allowlistCompatEnabled ? compatPluginIds : undefined,
|
||||
enablementPluginIds:
|
||||
params.compatMode.enablement === "always" ||
|
||||
(params.compatMode.enablement === "allowlist" && allowlistCompatEnabled)
|
||||
? compatPluginIds
|
||||
: undefined,
|
||||
vitestPluginIds: params.compatMode.vitest ? compatPluginIds : undefined,
|
||||
},
|
||||
env,
|
||||
});
|
||||
|
||||
return {
|
||||
rawConfig,
|
||||
config,
|
||||
activationSourceConfig: rawConfig,
|
||||
autoEnabledReasons,
|
||||
compatPluginIds,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1679,8 +1679,6 @@ module.exports = { id: "throws-after-import", register() {} };`,
|
||||
});
|
||||
|
||||
it("can scope bundled provider loads to deepseek without hanging", () => {
|
||||
resetPluginLoaderTestStateForTest();
|
||||
|
||||
const scoped = loadOpenClawPlugins({
|
||||
cache: false,
|
||||
activate: false,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { type NormalizedPluginsConfig } from "./config-state.js";
|
||||
import type { PluginLoadOptions } from "./loader.js";
|
||||
import type { PluginWebFetchProviderEntry } from "./types.js";
|
||||
import {
|
||||
@@ -26,7 +25,6 @@ export function resolveBundledWebFetchResolutionConfig(params: {
|
||||
bundledAllowlistCompat?: boolean;
|
||||
}): {
|
||||
config: PluginLoadOptions["config"];
|
||||
normalized: NormalizedPluginsConfig;
|
||||
activationSourceConfig?: PluginLoadOptions["config"];
|
||||
autoEnabledReasons: Record<string, string[]>;
|
||||
} {
|
||||
|
||||
@@ -2,13 +2,11 @@ import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const mocks = vi.hoisted(() => ({
|
||||
loadPluginManifestRegistry: vi.fn(),
|
||||
resolveManifestContractPluginIds: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("./manifest-registry.js", () => ({
|
||||
loadPluginManifestRegistry: (...args: unknown[]) => mocks.loadPluginManifestRegistry(...args),
|
||||
resolveManifestContractPluginIds: (...args: unknown[]) =>
|
||||
mocks.resolveManifestContractPluginIds(...args),
|
||||
resolveManifestContractPluginIds: vi.fn(),
|
||||
}));
|
||||
|
||||
let resolveManifestDeclaredWebProviderCandidatePluginIds: typeof import("./web-provider-resolution-shared.js").resolveManifestDeclaredWebProviderCandidatePluginIds;
|
||||
@@ -20,8 +18,6 @@ describe("resolveManifestDeclaredWebProviderCandidatePluginIds", () => {
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
mocks.resolveManifestContractPluginIds.mockReset();
|
||||
mocks.resolveManifestContractPluginIds.mockReturnValue(["alpha"]);
|
||||
mocks.loadPluginManifestRegistry.mockReset();
|
||||
mocks.loadPluginManifestRegistry.mockReturnValue({
|
||||
plugins: [
|
||||
@@ -65,4 +61,14 @@ describe("resolveManifestDeclaredWebProviderCandidatePluginIds", () => {
|
||||
}),
|
||||
).toBeUndefined();
|
||||
});
|
||||
|
||||
it("derives provider candidates from a single manifest-registry read", () => {
|
||||
expect(
|
||||
resolveManifestDeclaredWebProviderCandidatePluginIds({
|
||||
contract: "webSearchProviders",
|
||||
configKey: "webSearch",
|
||||
}),
|
||||
).toEqual(["alpha", "beta"]);
|
||||
expect(mocks.loadPluginManifestRegistry).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { resolveBundledPluginCompatibleActivationInputs } from "./activation-context.js";
|
||||
import type { NormalizedPluginsConfig } from "./config-state.js";
|
||||
import { resolveBundledPluginCompatibleLoadValues } from "./activation-context.js";
|
||||
import type { PluginLoadOptions } from "./loader.js";
|
||||
import {
|
||||
loadPluginManifestRegistry,
|
||||
@@ -72,16 +71,6 @@ export function resolveManifestDeclaredWebProviderCandidatePluginIds(params: {
|
||||
onlyPluginIds?: readonly string[];
|
||||
origin?: PluginManifestRecord["origin"];
|
||||
}): string[] | undefined {
|
||||
const contractIds = new Set(
|
||||
resolveManifestContractPluginIds({
|
||||
contract: params.contract,
|
||||
origin: params.origin,
|
||||
config: params.config,
|
||||
workspaceDir: params.workspaceDir,
|
||||
env: params.env,
|
||||
onlyPluginIds: params.onlyPluginIds,
|
||||
}),
|
||||
);
|
||||
const scopedPluginIds = normalizePluginIdScope(params.onlyPluginIds);
|
||||
const onlyPluginIdSet = createPluginIdScopeSet(scopedPluginIds);
|
||||
const ids = loadPluginManifestRegistry({
|
||||
@@ -93,8 +82,7 @@ export function resolveManifestDeclaredWebProviderCandidatePluginIds(params: {
|
||||
(plugin) =>
|
||||
(!params.origin || plugin.origin === params.origin) &&
|
||||
(!onlyPluginIdSet || onlyPluginIdSet.has(plugin.id)) &&
|
||||
(contractIds.has(plugin.id) ||
|
||||
pluginManifestDeclaresProviderConfig(plugin, params.configKey, params.contract)),
|
||||
pluginManifestDeclaresProviderConfig(plugin, params.configKey, params.contract),
|
||||
)
|
||||
.map((plugin) => plugin.id)
|
||||
.toSorted((left, right) => left.localeCompare(right));
|
||||
@@ -127,11 +115,10 @@ export function resolveBundledWebProviderResolutionConfig(params: {
|
||||
bundledAllowlistCompat?: boolean;
|
||||
}): {
|
||||
config: PluginLoadOptions["config"];
|
||||
normalized: NormalizedPluginsConfig;
|
||||
activationSourceConfig?: PluginLoadOptions["config"];
|
||||
autoEnabledReasons: Record<string, string[]>;
|
||||
} {
|
||||
const activation = resolveBundledPluginCompatibleActivationInputs({
|
||||
const activation = resolveBundledPluginCompatibleLoadValues({
|
||||
rawConfig: params.config,
|
||||
env: params.env,
|
||||
workspaceDir: params.workspaceDir,
|
||||
@@ -150,7 +137,6 @@ export function resolveBundledWebProviderResolutionConfig(params: {
|
||||
|
||||
return {
|
||||
config: activation.config,
|
||||
normalized: activation.normalized,
|
||||
activationSourceConfig: activation.activationSourceConfig,
|
||||
autoEnabledReasons: activation.autoEnabledReasons,
|
||||
};
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { type NormalizedPluginsConfig } from "./config-state.js";
|
||||
import type { PluginLoadOptions } from "./loader.js";
|
||||
import type { PluginWebSearchProviderEntry } from "./types.js";
|
||||
import {
|
||||
@@ -26,7 +25,6 @@ export function resolveBundledWebSearchResolutionConfig(params: {
|
||||
bundledAllowlistCompat?: boolean;
|
||||
}): {
|
||||
config: PluginLoadOptions["config"];
|
||||
normalized: NormalizedPluginsConfig;
|
||||
activationSourceConfig?: PluginLoadOptions["config"];
|
||||
autoEnabledReasons: Record<string, string[]>;
|
||||
} {
|
||||
|
||||
Reference in New Issue
Block a user