mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 10:10:45 +00:00
fix(plugins): cache web provider runtime loads
This commit is contained in:
@@ -44,9 +44,8 @@ Docs: https://docs.openclaw.ai
|
||||
- Web search/Brave: add `plugins.entries.brave.config.webSearch.baseUrl` for Brave-compatible proxies, including endpoint-aware cache keys for both web and LLM Context modes. Fixes #19075. Thanks @jkoprax and @vishnukool.
|
||||
- Web search/config: validate explicit `tools.web.search.provider` values against bundled and installed plugin manifests, while warning for stale third-party plugin config. Fixes #53092. Thanks @TinyTb.
|
||||
- Web search/SearXNG: retry empty non-general category searches once with the general category, so unsupported category engines do not return empty results when general search has matches. Fixes #73552. Thanks @Loukky.
|
||||
- CLI/message: skip gateway-stop hooks for read-only `message read` and bound
|
||||
stop-hook shutdown for other message actions, so one-shot Discord reads cannot
|
||||
hang behind plugin lifecycle cleanup.
|
||||
- CLI/message: skip gateway-stop hooks for read-only `message read` and bound stop-hook shutdown for other message actions, so one-shot Discord reads cannot hang behind plugin lifecycle cleanup.
|
||||
- Plugins/web-provider: cache repeated bundled web search and web fetch provider registry loads by default while preserving explicit cache opt-outs. Supersedes #75992. Thanks @DmitryPogodaev.
|
||||
- Agents/sandbox: preserve existing workspace file modes when sandbox edits atomically replace files, so 0644 files do not collapse to 0600 after Write/Edit/apply_patch. Fixes #44077. Thanks @patosullivan.
|
||||
- Agents/models: keep legacy CLI runtime model refs such as `claude-cli/*` in the configured allowlist after canonical runtime migration, so cron `payload.model` overrides keep working. Fixes #75753. Thanks @RyanSandoval.
|
||||
- Codex/app-server: restart the shared Codex app-server client once when it closes during startup thread resume, preserving the existing thread binding instead of retrying `thread/start` on a closed client. Thanks @vincentkoc.
|
||||
|
||||
@@ -231,4 +231,132 @@ describe("web-provider-runtime-shared", () => {
|
||||
});
|
||||
expect(mocks.loadOpenClawPlugins).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("caches runtime web provider plugin loads by default", () => {
|
||||
const loadedRegistry = { source: "loaded" };
|
||||
const mapRegistryProviders = vi.fn(() => ["provider"]);
|
||||
mocks.loadOpenClawPlugins.mockReturnValue(loadedRegistry as never);
|
||||
|
||||
const providers = resolvePluginWebProviders(
|
||||
{
|
||||
config: {},
|
||||
onlyPluginIds: ["brave"],
|
||||
},
|
||||
{
|
||||
resolveBundledResolutionConfig: () => ({
|
||||
config: {},
|
||||
activationSourceConfig: {},
|
||||
autoEnabledReasons: {},
|
||||
}),
|
||||
resolveCandidatePluginIds: () => ["brave"],
|
||||
mapRegistryProviders,
|
||||
},
|
||||
);
|
||||
|
||||
expect(providers).toEqual(["provider"]);
|
||||
expect(mocks.resolveCompatibleRuntimePluginRegistry).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
cache: true,
|
||||
onlyPluginIds: ["brave"],
|
||||
}),
|
||||
);
|
||||
expect(mocks.loadOpenClawPlugins).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
cache: true,
|
||||
onlyPluginIds: ["brave"],
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("keeps explicit runtime web provider cache opt-outs", () => {
|
||||
const loadedRegistry = { source: "loaded" };
|
||||
const mapRegistryProviders = vi.fn(() => ["provider"]);
|
||||
mocks.loadOpenClawPlugins.mockReturnValue(loadedRegistry as never);
|
||||
|
||||
resolvePluginWebProviders(
|
||||
{
|
||||
cache: false,
|
||||
config: {},
|
||||
onlyPluginIds: ["brave"],
|
||||
},
|
||||
{
|
||||
resolveBundledResolutionConfig: () => ({
|
||||
config: {},
|
||||
activationSourceConfig: {},
|
||||
autoEnabledReasons: {},
|
||||
}),
|
||||
resolveCandidatePluginIds: () => ["brave"],
|
||||
mapRegistryProviders,
|
||||
},
|
||||
);
|
||||
|
||||
expect(mocks.loadOpenClawPlugins).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
cache: false,
|
||||
onlyPluginIds: ["brave"],
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("caches setup web provider plugin loads by default", () => {
|
||||
const loadedRegistry = { source: "setup" };
|
||||
const mapRegistryProviders = vi.fn(() => ["provider"]);
|
||||
mocks.loadOpenClawPlugins.mockReturnValue(loadedRegistry as never);
|
||||
|
||||
const providers = resolvePluginWebProviders(
|
||||
{
|
||||
config: {},
|
||||
mode: "setup",
|
||||
},
|
||||
{
|
||||
resolveBundledResolutionConfig: () => ({
|
||||
config: {},
|
||||
activationSourceConfig: {},
|
||||
autoEnabledReasons: {},
|
||||
}),
|
||||
resolveCandidatePluginIds: () => ["brave"],
|
||||
mapRegistryProviders,
|
||||
resolveBundledPublicArtifactProviders: () => null,
|
||||
},
|
||||
);
|
||||
|
||||
expect(providers).toEqual(["provider"]);
|
||||
expect(mocks.loadOpenClawPlugins).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
cache: true,
|
||||
onlyPluginIds: ["brave"],
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("keeps explicit setup web provider cache opt-outs", () => {
|
||||
const loadedRegistry = { source: "setup" };
|
||||
const mapRegistryProviders = vi.fn(() => ["provider"]);
|
||||
mocks.loadOpenClawPlugins.mockReturnValue(loadedRegistry as never);
|
||||
|
||||
resolvePluginWebProviders(
|
||||
{
|
||||
cache: false,
|
||||
config: {},
|
||||
mode: "setup",
|
||||
},
|
||||
{
|
||||
resolveBundledResolutionConfig: () => ({
|
||||
config: {},
|
||||
activationSourceConfig: {},
|
||||
autoEnabledReasons: {},
|
||||
}),
|
||||
resolveCandidatePluginIds: () => ["brave"],
|
||||
mapRegistryProviders,
|
||||
resolveBundledPublicArtifactProviders: () => null,
|
||||
},
|
||||
);
|
||||
|
||||
expect(mocks.loadOpenClawPlugins).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
cache: false,
|
||||
onlyPluginIds: ["brave"],
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -112,7 +112,7 @@ function resolveWebProviderLoadOptions(
|
||||
logger: createPluginRuntimeLoaderLogger(),
|
||||
},
|
||||
{
|
||||
cache: params.cache ?? false,
|
||||
cache: params.cache ?? true,
|
||||
activate: params.activate ?? false,
|
||||
...(hasExplicitPluginIdScope(context.onlyPluginIds)
|
||||
? { onlyPluginIds: context.onlyPluginIds }
|
||||
@@ -166,7 +166,7 @@ export function resolvePluginWebProviders<TEntry>(
|
||||
},
|
||||
{
|
||||
onlyPluginIds: pluginIds,
|
||||
cache: params.cache ?? false,
|
||||
cache: params.cache ?? true,
|
||||
activate: params.activate ?? false,
|
||||
},
|
||||
),
|
||||
@@ -186,16 +186,21 @@ export function resolvePluginWebProviders<TEntry>(
|
||||
if (isPluginRegistryLoadInFlight(loadOptions)) {
|
||||
return [];
|
||||
}
|
||||
const scopedPluginIds = context.onlyPluginIds;
|
||||
const hasExplicitEmptyScope = scopedPluginIds !== undefined && scopedPluginIds.length === 0;
|
||||
const activeRegistry = getActivePluginRegistry();
|
||||
if (activeRegistry) {
|
||||
const activeProviders = deps.mapRegistryProviders({
|
||||
registry: activeRegistry,
|
||||
onlyPluginIds: context.onlyPluginIds,
|
||||
});
|
||||
if (activeProviders.length > 0) {
|
||||
if (activeProviders.length > 0 || hasExplicitEmptyScope) {
|
||||
return activeProviders;
|
||||
}
|
||||
}
|
||||
if (hasExplicitEmptyScope) {
|
||||
return [];
|
||||
}
|
||||
return deps.mapRegistryProviders({
|
||||
registry: loadOpenClawPlugins(loadOptions),
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user