mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 16:20:43 +00:00
perf: speed up security audit test imports
This commit is contained in:
@@ -18,9 +18,13 @@ type BundledChannelEntryRuntimeContract = {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
features?: {
|
||||
accountInspect?: boolean;
|
||||
};
|
||||
register: (api: unknown) => void;
|
||||
loadChannelPlugin: () => ChannelPlugin;
|
||||
loadChannelSecrets?: () => ChannelPlugin["secrets"] | undefined;
|
||||
loadChannelAccountInspector?: () => NonNullable<ChannelPlugin["config"]["inspectAccount"]>;
|
||||
setChannelRuntime?: (runtime: PluginRuntime) => void;
|
||||
};
|
||||
|
||||
@@ -49,6 +53,10 @@ type BundledChannelCacheContext = {
|
||||
lazySetupPluginsById: Map<ChannelId, ChannelPlugin>;
|
||||
lazySecretsById: Map<ChannelId, ChannelPlugin["secrets"] | null>;
|
||||
lazySetupSecretsById: Map<ChannelId, ChannelPlugin["secrets"] | null>;
|
||||
lazyAccountInspectorsById: Map<
|
||||
ChannelId,
|
||||
NonNullable<ChannelPlugin["config"]["inspectAccount"]> | null
|
||||
>;
|
||||
};
|
||||
|
||||
const log = createSubsystemLogger("channels");
|
||||
@@ -100,6 +108,13 @@ function hasSetupEntryFeature(
|
||||
return entry?.features?.[feature] === true;
|
||||
}
|
||||
|
||||
function hasChannelEntryFeature(
|
||||
entry: BundledChannelEntryRuntimeContract | undefined,
|
||||
feature: keyof NonNullable<BundledChannelEntryRuntimeContract["features"]>,
|
||||
): boolean {
|
||||
return entry?.features?.[feature] === true;
|
||||
}
|
||||
|
||||
function resolveBundledChannelBoundaryRoot(params: {
|
||||
packageRoot: string;
|
||||
pluginsDir?: string;
|
||||
@@ -222,6 +237,7 @@ function createBundledChannelCacheContext(): BundledChannelCacheContext {
|
||||
lazySetupPluginsById: new Map(),
|
||||
lazySecretsById: new Map(),
|
||||
lazySetupSecretsById: new Map(),
|
||||
lazyAccountInspectorsById: new Map(),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -368,6 +384,24 @@ function getBundledChannelSecretsForRoot(
|
||||
return secrets;
|
||||
}
|
||||
|
||||
function getBundledChannelAccountInspectorForRoot(
|
||||
id: ChannelId,
|
||||
rootScope: BundledChannelRootScope,
|
||||
cacheContext: BundledChannelCacheContext,
|
||||
): NonNullable<ChannelPlugin["config"]["inspectAccount"]> | undefined {
|
||||
if (cacheContext.lazyAccountInspectorsById.has(id)) {
|
||||
return cacheContext.lazyAccountInspectorsById.get(id) ?? undefined;
|
||||
}
|
||||
const entry = getLazyGeneratedBundledChannelEntryForRoot(id, rootScope, cacheContext)?.entry;
|
||||
if (!entry?.loadChannelAccountInspector) {
|
||||
cacheContext.lazyAccountInspectorsById.set(id, null);
|
||||
return undefined;
|
||||
}
|
||||
const inspector = entry.loadChannelAccountInspector();
|
||||
cacheContext.lazyAccountInspectorsById.set(id, inspector);
|
||||
return inspector;
|
||||
}
|
||||
|
||||
function getBundledChannelSetupPluginForRoot(
|
||||
id: ChannelId,
|
||||
rootScope: BundledChannelRootScope,
|
||||
@@ -449,6 +483,22 @@ export function listBundledChannelSetupPluginsByFeature(
|
||||
});
|
||||
}
|
||||
|
||||
export function hasBundledChannelEntryFeature(
|
||||
id: ChannelId,
|
||||
feature: keyof NonNullable<BundledChannelEntryRuntimeContract["features"]>,
|
||||
): boolean {
|
||||
const { rootScope, cacheContext } = resolveActiveBundledChannelCacheScope();
|
||||
const entry = getLazyGeneratedBundledChannelEntryForRoot(id, rootScope, cacheContext)?.entry;
|
||||
return hasChannelEntryFeature(entry, feature);
|
||||
}
|
||||
|
||||
export function getBundledChannelAccountInspector(
|
||||
id: ChannelId,
|
||||
): NonNullable<ChannelPlugin["config"]["inspectAccount"]> | undefined {
|
||||
const { rootScope, cacheContext } = resolveActiveBundledChannelCacheScope();
|
||||
return getBundledChannelAccountInspectorForRoot(id, rootScope, cacheContext);
|
||||
}
|
||||
|
||||
export function getBundledChannelPlugin(id: ChannelId): ChannelPlugin | undefined {
|
||||
const { rootScope, cacheContext } = resolveActiveBundledChannelCacheScope();
|
||||
return getBundledChannelPluginForRoot(id, rootScope, cacheContext);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import { getChannelPlugin } from "./plugins/registry.js";
|
||||
import { getBundledChannelAccountInspector } from "./plugins/bundled.js";
|
||||
import { getLoadedChannelPlugin } from "./plugins/registry.js";
|
||||
import type { ChannelId } from "./plugins/types.public.js";
|
||||
|
||||
export type ReadOnlyInspectedAccount = Record<string, unknown>;
|
||||
@@ -9,7 +10,9 @@ export async function inspectReadOnlyChannelAccount(params: {
|
||||
cfg: OpenClawConfig;
|
||||
accountId?: string | null;
|
||||
}): Promise<ReadOnlyInspectedAccount | null> {
|
||||
const inspectAccount = getChannelPlugin(params.channelId)?.config.inspectAccount;
|
||||
const inspectAccount =
|
||||
getLoadedChannelPlugin(params.channelId)?.config.inspectAccount ??
|
||||
getBundledChannelAccountInspector(params.channelId);
|
||||
if (!inspectAccount) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -36,6 +36,8 @@ type DefineBundledChannelEntryOptions<TPlugin = ChannelPlugin> = {
|
||||
secrets?: BundledEntryModuleRef;
|
||||
configSchema?: ChannelEntryConfigSchema<TPlugin> | (() => ChannelEntryConfigSchema<TPlugin>);
|
||||
runtime?: BundledEntryModuleRef;
|
||||
accountInspect?: BundledEntryModuleRef;
|
||||
features?: BundledChannelEntryFeatures;
|
||||
registerCliMetadata?: (api: OpenClawPluginApi) => void;
|
||||
registerFull?: (api: OpenClawPluginApi) => void;
|
||||
};
|
||||
@@ -53,15 +55,21 @@ export type BundledChannelSetupEntryFeatures = {
|
||||
legacySessionSurfaces?: boolean;
|
||||
};
|
||||
|
||||
export type BundledChannelEntryFeatures = {
|
||||
accountInspect?: boolean;
|
||||
};
|
||||
|
||||
export type BundledChannelEntryContract<TPlugin = ChannelPlugin> = {
|
||||
kind: "bundled-channel-entry";
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
configSchema: ChannelEntryConfigSchema<TPlugin>;
|
||||
features?: BundledChannelEntryFeatures;
|
||||
register: (api: OpenClawPluginApi) => void;
|
||||
loadChannelPlugin: () => TPlugin;
|
||||
loadChannelSecrets?: () => ChannelPlugin["secrets"] | undefined;
|
||||
loadChannelAccountInspector?: () => NonNullable<ChannelPlugin["config"]["inspectAccount"]>;
|
||||
setChannelRuntime?: (runtime: PluginRuntime) => void;
|
||||
};
|
||||
|
||||
@@ -332,6 +340,8 @@ export function defineBundledChannelEntry<TPlugin = ChannelPlugin>({
|
||||
secrets,
|
||||
configSchema,
|
||||
runtime,
|
||||
accountInspect,
|
||||
features,
|
||||
registerCliMetadata,
|
||||
registerFull,
|
||||
}: DefineBundledChannelEntryOptions<TPlugin>): BundledChannelEntryContract<TPlugin> {
|
||||
@@ -343,6 +353,13 @@ export function defineBundledChannelEntry<TPlugin = ChannelPlugin>({
|
||||
const loadChannelSecrets = secrets
|
||||
? () => loadBundledEntryExportSync<ChannelPlugin["secrets"] | undefined>(importMetaUrl, secrets)
|
||||
: undefined;
|
||||
const loadChannelAccountInspector = accountInspect
|
||||
? () =>
|
||||
loadBundledEntryExportSync<NonNullable<ChannelPlugin["config"]["inspectAccount"]>>(
|
||||
importMetaUrl,
|
||||
accountInspect,
|
||||
)
|
||||
: undefined;
|
||||
const setChannelRuntime = runtime
|
||||
? (pluginRuntime: PluginRuntime) => {
|
||||
const setter = loadBundledEntryExportSync<(runtime: PluginRuntime) => void>(
|
||||
@@ -359,6 +376,9 @@ export function defineBundledChannelEntry<TPlugin = ChannelPlugin>({
|
||||
name,
|
||||
description,
|
||||
configSchema: resolvedConfigSchema,
|
||||
...(features || accountInspect
|
||||
? { features: { ...features, ...(accountInspect ? { accountInspect: true } : {}) } }
|
||||
: {}),
|
||||
register(api: OpenClawPluginApi) {
|
||||
if (api.registrationMode === "cli-metadata") {
|
||||
registerCliMetadata?.(api);
|
||||
@@ -374,6 +394,7 @@ export function defineBundledChannelEntry<TPlugin = ChannelPlugin>({
|
||||
},
|
||||
loadChannelPlugin,
|
||||
...(loadChannelSecrets ? { loadChannelSecrets } : {}),
|
||||
...(loadChannelAccountInspector ? { loadChannelAccountInspector } : {}),
|
||||
...(setChannelRuntime ? { setChannelRuntime } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import fs from "node:fs";
|
||||
import { createRequire } from "node:module";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { fileURLToPath, pathToFileURL } from "node:url";
|
||||
import { openBoundaryFileSync } from "../infra/boundary-file-read.js";
|
||||
import { resolveBundledPluginsDir } from "../plugins/bundled-dir.js";
|
||||
import {
|
||||
@@ -275,6 +275,54 @@ export function loadBundledPluginPublicSurfaceModuleSync<T extends object>(param
|
||||
});
|
||||
}
|
||||
|
||||
export async function loadBundledPluginPublicSurfaceModule<T extends object>(params: {
|
||||
dirName: string;
|
||||
artifactBasename: string;
|
||||
trackedPluginId?: string | (() => string);
|
||||
env?: NodeJS.ProcessEnv;
|
||||
}): Promise<T> {
|
||||
const location = resolveFacadeModuleLocation(params);
|
||||
if (!location) {
|
||||
throw new Error(
|
||||
`Unable to resolve bundled plugin public surface ${params.dirName}/${params.artifactBasename}`,
|
||||
);
|
||||
}
|
||||
const cached = loadedFacadeModules.get(location.modulePath);
|
||||
if (cached) {
|
||||
return cached as T;
|
||||
}
|
||||
|
||||
const opened = openBoundaryFileSync({
|
||||
absolutePath: location.modulePath,
|
||||
rootPath: location.boundaryRoot,
|
||||
boundaryLabel:
|
||||
location.boundaryRoot === getOpenClawPackageRoot() ? "OpenClaw package root" : "plugin root",
|
||||
rejectHardlinks: false,
|
||||
});
|
||||
if (!opened.ok) {
|
||||
throw new Error(`Unable to open bundled plugin public surface ${location.modulePath}`, {
|
||||
cause: opened.error,
|
||||
});
|
||||
}
|
||||
fs.closeSync(opened.fd);
|
||||
|
||||
try {
|
||||
const loaded = (await import(pathToFileURL(location.modulePath).href)) as T;
|
||||
loadedFacadeModules.set(location.modulePath, loaded);
|
||||
loadedFacadePluginIds.add(
|
||||
typeof params.trackedPluginId === "function"
|
||||
? params.trackedPluginId()
|
||||
: (params.trackedPluginId ?? params.dirName),
|
||||
);
|
||||
return loaded;
|
||||
} catch {
|
||||
return loadFacadeModuleAtLocationSync({
|
||||
location,
|
||||
trackedPluginId: params.trackedPluginId ?? params.dirName,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function listImportedBundledPluginFacadeIds(): string[] {
|
||||
return [...loadedFacadePluginIds].toSorted((left, right) => left.localeCompare(right));
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ type FacadeModule = typeof import("@openclaw/telegram/contract-api.js");
|
||||
type SecurityAuditFacadeModule = typeof import("@openclaw/telegram/security-audit-contract-api.js");
|
||||
import {
|
||||
createLazyFacadeArrayValue,
|
||||
loadBundledPluginPublicSurfaceModule,
|
||||
loadBundledPluginPublicSurfaceModuleSync,
|
||||
} from "./facade-loader.js";
|
||||
|
||||
@@ -13,8 +14,8 @@ function loadFacadeModule(): FacadeModule {
|
||||
});
|
||||
}
|
||||
|
||||
function loadSecurityAuditFacadeModule(): SecurityAuditFacadeModule {
|
||||
return loadBundledPluginPublicSurfaceModuleSync<SecurityAuditFacadeModule>({
|
||||
async function loadSecurityAuditFacadeModule(): Promise<SecurityAuditFacadeModule> {
|
||||
return await loadBundledPluginPublicSurfaceModule<SecurityAuditFacadeModule>({
|
||||
dirName: "telegram",
|
||||
artifactBasename: "security-audit-contract-api.js",
|
||||
});
|
||||
@@ -31,8 +32,8 @@ export const singleAccountKeysToMove: FacadeModule["singleAccountKeysToMove"] =
|
||||
createLazyFacadeArrayValue(() => loadFacadeModule().singleAccountKeysToMove);
|
||||
|
||||
export const collectTelegramSecurityAuditFindings: FacadeModule["collectTelegramSecurityAuditFindings"] =
|
||||
((...args) =>
|
||||
loadSecurityAuditFacadeModule().collectTelegramSecurityAuditFindings(
|
||||
(async (...args) =>
|
||||
(await loadSecurityAuditFacadeModule()).collectTelegramSecurityAuditFindings(
|
||||
...args,
|
||||
)) as FacadeModule["collectTelegramSecurityAuditFindings"];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user