Files
openclaw/src/plugins/discovery-threading.test.ts
Dallin Romney 88d8d6af93 perf(plugins): extend discovery threading to loader, manifest registry, installed-index, and config contracts (#84283)
* perf(plugins): extend discovery threading to loader, manifest registry, installed-index, and config contracts

Follow-up to #75451. Threads optional discovery?: PluginDiscoveryResult
through the remaining helpers that still call discoverOpenClawPlugins
internally during startup:

- loadOpenClawPlugins / loadOpenClawPluginCliRegistry (src/plugins/loader.ts):
  add discovery? to PluginLoadOptions and consult it before falling back to
  an internal scan at both call sites.

- loadPluginManifestRegistry (src/plugins/manifest-registry.ts): accept
  discovery? as a more ergonomic alternative to the existing candidates? /
  diagnostics? pair; candidates? still wins when both are supplied.

- resolveInstalledPluginIndexRegistry (src/plugins/installed-plugin-index-registry.ts):
  add discovery? to LoadInstalledPluginIndexParams and use it when
  candidates aren't supplied.

- resolvePluginConfigContractsById (src/plugins/config-contracts.ts): add
  discovery? and thread it into the bundled-fallback discovery call.

Add discovery-threading.test.ts asserting each entry point skips its
internal discoverOpenClawPlugins call when discovery is supplied, calls it
when nothing is supplied, and prefers explicit candidates over discovery
when both are present (6 tests, all pass).

discoverOpenClawPlugins remains stateless; sharing is function-scoped per
src/plugins/CLAUDE.md guidance. Backward compatible: every change is
additive (new optional param).

* perf(plugins): drop verbose JSDoc from discovery? params
2026-05-19 16:22:30 -07:00

64 lines
2.4 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from "vitest";
import type { PluginDiscoveryResult } from "./discovery.js";
const discoverOpenClawPluginsMock = vi.fn();
vi.mock("./discovery.js", async (importOriginal) => {
const actual = await importOriginal<typeof import("./discovery.js")>();
return {
...actual,
discoverOpenClawPlugins: (...args: unknown[]) => discoverOpenClawPluginsMock(...args),
};
});
const { loadPluginManifestRegistry } = await import("./manifest-registry.js");
const { resolveInstalledPluginIndexRegistry } =
await import("./installed-plugin-index-registry.js");
const emptyDiscovery: PluginDiscoveryResult = { candidates: [], diagnostics: [] };
describe("discovery threading", () => {
beforeEach(() => {
discoverOpenClawPluginsMock.mockReset();
discoverOpenClawPluginsMock.mockReturnValue(emptyDiscovery);
});
describe("loadPluginManifestRegistry", () => {
it("skips internal discoverOpenClawPlugins when discovery is supplied", () => {
loadPluginManifestRegistry({ discovery: emptyDiscovery });
expect(discoverOpenClawPluginsMock).not.toHaveBeenCalled();
});
it("calls discoverOpenClawPlugins when neither discovery nor candidates supplied", () => {
loadPluginManifestRegistry({});
expect(discoverOpenClawPluginsMock).toHaveBeenCalledTimes(1);
});
it("prefers explicit candidates over discovery when both are supplied", () => {
loadPluginManifestRegistry({ candidates: [], diagnostics: [], discovery: emptyDiscovery });
expect(discoverOpenClawPluginsMock).not.toHaveBeenCalled();
});
});
describe("resolveInstalledPluginIndexRegistry", () => {
it("skips internal discoverOpenClawPlugins when discovery is supplied", () => {
resolveInstalledPluginIndexRegistry({ discovery: emptyDiscovery, installRecords: {} });
expect(discoverOpenClawPluginsMock).not.toHaveBeenCalled();
});
it("calls discoverOpenClawPlugins when neither discovery nor candidates supplied", () => {
resolveInstalledPluginIndexRegistry({ installRecords: {} });
expect(discoverOpenClawPluginsMock).toHaveBeenCalledTimes(1);
});
it("prefers explicit candidates over discovery when both are supplied", () => {
resolveInstalledPluginIndexRegistry({
candidates: [],
discovery: emptyDiscovery,
installRecords: {},
});
expect(discoverOpenClawPluginsMock).not.toHaveBeenCalled();
});
});
});