mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 11:20:43 +00:00
fix(plugins): reuse gateway-bindable loader cache
This commit is contained in:
@@ -30,6 +30,7 @@ Docs: https://docs.openclaw.ai
|
||||
|
||||
### Fixes
|
||||
|
||||
- Plugins: reuse gateway-bindable plugin loader cache entries for later default-mode loads without serving default-built registries to gateway-bound requests, reducing repeated plugin registration during dispatch. Refs #61756. Thanks @DmitryPogodaev.
|
||||
- Gateway/secrets: include the caught error message in `secrets.reload` and `secrets.resolve` warning logs while keeping RPC errors generic, so operators can diagnose reload and permission failures. Thanks @davidangularme.
|
||||
- fix(infra): block workspace state-directory env override [AI]. (#75940) Thanks @pgondhi987.
|
||||
- MCP/OpenAI: normalize parameter-free tool schemas whose top-level object `properties` is missing, null, or invalid before sending tools to OpenAI, so MCP tools without params stay usable. Fixes #75362. Thanks @tolkonepiu and @SymbolStar.
|
||||
|
||||
@@ -3119,6 +3119,45 @@ module.exports = { id: "throws-after-import", register() {} };`,
|
||||
delete (globalThis as Record<string, unknown>)[marker];
|
||||
});
|
||||
|
||||
it("reuses a gateway-bindable cache entry for later default-mode loads", () => {
|
||||
useNoBundledPlugins();
|
||||
const marker = "__openclawGatewayBindableCacheRegisterCount";
|
||||
const plugin = writePlugin({
|
||||
id: "gateway-bindable-cache",
|
||||
filename: "gateway-bindable-cache.cjs",
|
||||
body: `module.exports = {
|
||||
id: "gateway-bindable-cache",
|
||||
register() {
|
||||
globalThis.${marker} = (globalThis.${marker} || 0) + 1;
|
||||
},
|
||||
};`,
|
||||
});
|
||||
const options = {
|
||||
workspaceDir: plugin.dir,
|
||||
config: {
|
||||
plugins: {
|
||||
load: { paths: [plugin.file] },
|
||||
allow: ["gateway-bindable-cache"],
|
||||
entries: {
|
||||
"gateway-bindable-cache": { enabled: true },
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const gatewayBindable = loadOpenClawPlugins({
|
||||
...options,
|
||||
runtimeOptions: {
|
||||
allowGatewaySubagentBinding: true,
|
||||
},
|
||||
});
|
||||
const defaultMode = loadOpenClawPlugins(options);
|
||||
|
||||
expect(defaultMode).toBe(gatewayBindable);
|
||||
expect((globalThis as Record<string, unknown>)[marker]).toBe(1);
|
||||
delete (globalThis as Record<string, unknown>)[marker];
|
||||
});
|
||||
|
||||
it("re-initializes global hook runner when serving registry from cache", () => {
|
||||
useNoBundledPlugins();
|
||||
const plugin = writePlugin({
|
||||
|
||||
@@ -552,6 +552,50 @@ function setCachedPluginRegistry(
|
||||
getPluginRegistryCache(onlyPluginIds).set(cacheKey, state);
|
||||
}
|
||||
|
||||
function getReusableCachedPluginRegistry(params: {
|
||||
cacheKey: string;
|
||||
onlyPluginIds: string[];
|
||||
runtimeSubagentMode: "default" | "explicit" | "gateway-bindable";
|
||||
options: PluginLoadOptions;
|
||||
}):
|
||||
| {
|
||||
state: CachedPluginState;
|
||||
cacheKey: string;
|
||||
runtimeSubagentMode: "default" | "explicit" | "gateway-bindable";
|
||||
}
|
||||
| undefined {
|
||||
const exact = getCachedPluginRegistry(params.cacheKey, params.onlyPluginIds);
|
||||
if (exact) {
|
||||
return {
|
||||
state: exact,
|
||||
cacheKey: params.cacheKey,
|
||||
runtimeSubagentMode: params.runtimeSubagentMode,
|
||||
};
|
||||
}
|
||||
if (params.runtimeSubagentMode !== "default") {
|
||||
return undefined;
|
||||
}
|
||||
const gatewayBindableContext = resolvePluginLoadCacheContext({
|
||||
...params.options,
|
||||
runtimeOptions: {
|
||||
...params.options.runtimeOptions,
|
||||
allowGatewaySubagentBinding: true,
|
||||
},
|
||||
});
|
||||
const gatewayBindable = getCachedPluginRegistry(
|
||||
gatewayBindableContext.cacheKey,
|
||||
gatewayBindableContext.onlyPluginIds,
|
||||
);
|
||||
if (!gatewayBindable) {
|
||||
return undefined;
|
||||
}
|
||||
return {
|
||||
state: gatewayBindable,
|
||||
cacheKey: gatewayBindableContext.cacheKey,
|
||||
runtimeSubagentMode: gatewayBindableContext.runtimeSubagentMode,
|
||||
};
|
||||
}
|
||||
|
||||
function resolveBundledPackageRootForCache(stockRoot?: string): string | undefined {
|
||||
if (!stockRoot) {
|
||||
return undefined;
|
||||
@@ -1332,31 +1376,38 @@ export function loadOpenClawPlugins(options: PluginLoadOptions = {}): PluginRegi
|
||||
|
||||
const cacheEnabled = options.cache !== false;
|
||||
if (cacheEnabled) {
|
||||
const cached = getCachedPluginRegistry(cacheKey, onlyPluginIds);
|
||||
const cached = getReusableCachedPluginRegistry({
|
||||
cacheKey,
|
||||
onlyPluginIds,
|
||||
runtimeSubagentMode,
|
||||
options,
|
||||
});
|
||||
if (cached) {
|
||||
if (shouldActivate) {
|
||||
restoreRegisteredAgentHarnesses(cached.agentHarnesses);
|
||||
restorePluginCommands(cached.commands ?? []);
|
||||
restoreRegisteredCompactionProviders(cached.compactionProviders);
|
||||
restoreDetachedTaskLifecycleRuntimeRegistration(cached.detachedTaskRuntimeRegistration);
|
||||
restorePluginInteractiveHandlers(cached.interactiveHandlers ?? []);
|
||||
restoreRegisteredMemoryEmbeddingProviders(cached.memoryEmbeddingProviders);
|
||||
restoreRegisteredAgentHarnesses(cached.state.agentHarnesses);
|
||||
restorePluginCommands(cached.state.commands ?? []);
|
||||
restoreRegisteredCompactionProviders(cached.state.compactionProviders);
|
||||
restoreDetachedTaskLifecycleRuntimeRegistration(
|
||||
cached.state.detachedTaskRuntimeRegistration,
|
||||
);
|
||||
restorePluginInteractiveHandlers(cached.state.interactiveHandlers ?? []);
|
||||
restoreRegisteredMemoryEmbeddingProviders(cached.state.memoryEmbeddingProviders);
|
||||
restoreMemoryPluginState({
|
||||
capability: cached.memoryCapability,
|
||||
corpusSupplements: cached.memoryCorpusSupplements,
|
||||
promptBuilder: cached.memoryPromptBuilder,
|
||||
promptSupplements: cached.memoryPromptSupplements,
|
||||
flushPlanResolver: cached.memoryFlushPlanResolver,
|
||||
runtime: cached.memoryRuntime,
|
||||
capability: cached.state.memoryCapability,
|
||||
corpusSupplements: cached.state.memoryCorpusSupplements,
|
||||
promptBuilder: cached.state.memoryPromptBuilder,
|
||||
promptSupplements: cached.state.memoryPromptSupplements,
|
||||
flushPlanResolver: cached.state.memoryFlushPlanResolver,
|
||||
runtime: cached.state.memoryRuntime,
|
||||
});
|
||||
activatePluginRegistry(
|
||||
cached.registry,
|
||||
cacheKey,
|
||||
runtimeSubagentMode,
|
||||
cached.state.registry,
|
||||
cached.cacheKey,
|
||||
cached.runtimeSubagentMode,
|
||||
options.workspaceDir,
|
||||
);
|
||||
}
|
||||
return cached.registry;
|
||||
return cached.state.registry;
|
||||
}
|
||||
}
|
||||
pluginLoaderCacheState.beginLoad(cacheKey);
|
||||
|
||||
Reference in New Issue
Block a user