mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-11 15:30:44 +00:00
187 lines
6.1 KiB
TypeScript
187 lines
6.1 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
import type { InstalledPluginIndex } from "../plugins/installed-plugin-index.js";
|
|
import type { InstalledPluginStartupInfo } from "../plugins/installed-plugin-index.js";
|
|
import type { PluginManifestRegistry } from "../plugins/manifest-registry.js";
|
|
|
|
const readPersistedInstalledPluginIndexMock = vi.fn();
|
|
const loadPluginManifestRegistryForInstalledIndexMock = vi.fn();
|
|
|
|
const startupInfo: InstalledPluginStartupInfo = {
|
|
sidecar: false,
|
|
memory: false,
|
|
deferConfiguredChannelFullLoadUntilAfterListen: false,
|
|
agentHarnesses: [],
|
|
};
|
|
|
|
vi.mock("../plugins/installed-plugin-index-store.js", () => ({
|
|
readPersistedInstalledPluginIndex: (...args: unknown[]) =>
|
|
readPersistedInstalledPluginIndexMock(...args),
|
|
}));
|
|
|
|
vi.mock("../plugins/manifest-registry-installed.js", () => ({
|
|
loadPluginManifestRegistryForInstalledIndex: (...args: unknown[]) =>
|
|
loadPluginManifestRegistryForInstalledIndexMock(...args),
|
|
}));
|
|
|
|
const { listPersistedBundledPluginLocationBridges } = await import("./plugins-location-bridges.js");
|
|
|
|
function makeIndex(record: InstalledPluginIndex["plugins"][number]): InstalledPluginIndex {
|
|
return {
|
|
version: 1,
|
|
hostContractVersion: "2026.5.2",
|
|
compatRegistryVersion: "test",
|
|
migrationVersion: 1,
|
|
policyHash: "test",
|
|
generatedAtMs: 1,
|
|
refreshReason: "manual",
|
|
installRecords: {},
|
|
plugins: [record],
|
|
diagnostics: [],
|
|
};
|
|
}
|
|
|
|
function makeRegistry(pluginId: string): PluginManifestRegistry {
|
|
return {
|
|
plugins: [
|
|
{
|
|
id: pluginId,
|
|
name: pluginId,
|
|
rootDir: `/app/dist/extensions/${pluginId}`,
|
|
source: `/app/dist/extensions/${pluginId}/index.js`,
|
|
origin: "bundled",
|
|
channels: [pluginId],
|
|
providers: [],
|
|
cliBackends: [],
|
|
syntheticAuthRefs: [],
|
|
nonSecretAuthMarkers: [],
|
|
skills: [],
|
|
settingsFiles: [],
|
|
hooks: [],
|
|
configContracts: [],
|
|
activation: {},
|
|
startup: {},
|
|
packageInstall: {
|
|
clawhubSpec: `clawhub:@openclaw/${pluginId}`,
|
|
npmSpec: `@openclaw/${pluginId}`,
|
|
defaultChoice: "clawhub",
|
|
},
|
|
},
|
|
],
|
|
diagnostics: [],
|
|
} as unknown as PluginManifestRegistry;
|
|
}
|
|
|
|
describe("listPersistedBundledPluginLocationBridges", () => {
|
|
beforeEach(() => {
|
|
readPersistedInstalledPluginIndexMock.mockReset();
|
|
loadPluginManifestRegistryForInstalledIndexMock.mockReset();
|
|
});
|
|
|
|
it("keeps persisted bundled relocations npm-first for launch", async () => {
|
|
readPersistedInstalledPluginIndexMock.mockResolvedValue(
|
|
makeIndex({
|
|
pluginId: "diagnostics-otel",
|
|
manifestPath: "/app/dist/extensions/diagnostics-otel/openclaw.plugin.json",
|
|
manifestHash: "hash",
|
|
source: "/app/dist/extensions/diagnostics-otel/index.js",
|
|
rootDir: "/app/dist/extensions/diagnostics-otel",
|
|
origin: "bundled",
|
|
enabled: true,
|
|
startup: startupInfo,
|
|
compat: [],
|
|
packageInstall: {
|
|
defaultChoice: "clawhub",
|
|
clawhub: {
|
|
spec: "clawhub:@openclaw/diagnostics-otel",
|
|
packageName: "@openclaw/diagnostics-otel",
|
|
exactVersion: false,
|
|
},
|
|
npm: {
|
|
spec: "@openclaw/diagnostics-otel",
|
|
packageName: "@openclaw/diagnostics-otel",
|
|
selectorKind: "none",
|
|
exactVersion: false,
|
|
pinState: "floating-without-integrity",
|
|
},
|
|
warnings: [],
|
|
},
|
|
}),
|
|
);
|
|
loadPluginManifestRegistryForInstalledIndexMock.mockReturnValue(
|
|
makeRegistry("diagnostics-otel"),
|
|
);
|
|
|
|
await expect(listPersistedBundledPluginLocationBridges({})).resolves.toEqual([
|
|
{
|
|
bundledPluginId: "diagnostics-otel",
|
|
pluginId: "diagnostics-otel",
|
|
preferredSource: "npm",
|
|
npmSpec: "@openclaw/diagnostics-otel",
|
|
clawhubSpec: "clawhub:@openclaw/diagnostics-otel",
|
|
channelIds: ["diagnostics-otel"],
|
|
},
|
|
]);
|
|
});
|
|
|
|
it("uses official external catalog metadata when the persisted bundled row lacks npm metadata", async () => {
|
|
readPersistedInstalledPluginIndexMock.mockResolvedValue(
|
|
makeIndex({
|
|
pluginId: "diagnostics-otel",
|
|
manifestPath: "/app/dist/extensions/diagnostics-otel/openclaw.plugin.json",
|
|
manifestHash: "hash",
|
|
source: "/app/dist/extensions/diagnostics-otel/index.js",
|
|
rootDir: "/app/dist/extensions/diagnostics-otel",
|
|
origin: "bundled",
|
|
enabled: true,
|
|
startup: startupInfo,
|
|
compat: [],
|
|
packageInstall: {
|
|
defaultChoice: "clawhub",
|
|
clawhub: {
|
|
spec: "clawhub:@openclaw/diagnostics-otel",
|
|
packageName: "@openclaw/diagnostics-otel",
|
|
exactVersion: false,
|
|
},
|
|
warnings: [],
|
|
},
|
|
}),
|
|
);
|
|
loadPluginManifestRegistryForInstalledIndexMock.mockReturnValue(
|
|
makeRegistry("diagnostics-otel"),
|
|
);
|
|
|
|
await expect(listPersistedBundledPluginLocationBridges({})).resolves.toEqual([
|
|
{
|
|
bundledPluginId: "diagnostics-otel",
|
|
pluginId: "diagnostics-otel",
|
|
preferredSource: "npm",
|
|
npmSpec: "@openclaw/diagnostics-otel",
|
|
clawhubSpec: "clawhub:@openclaw/diagnostics-otel",
|
|
channelIds: ["diagnostics-otel"],
|
|
},
|
|
]);
|
|
});
|
|
|
|
it("does not create a relocation bridge without persisted or official install metadata", async () => {
|
|
readPersistedInstalledPluginIndexMock.mockResolvedValue(
|
|
makeIndex({
|
|
pluginId: "local-only",
|
|
manifestPath: "/app/dist/extensions/local-only/openclaw.plugin.json",
|
|
manifestHash: "hash",
|
|
source: "/app/dist/extensions/local-only/index.js",
|
|
rootDir: "/app/dist/extensions/local-only",
|
|
origin: "bundled",
|
|
enabled: true,
|
|
startup: startupInfo,
|
|
compat: [],
|
|
packageInstall: {
|
|
warnings: [],
|
|
},
|
|
}),
|
|
);
|
|
loadPluginManifestRegistryForInstalledIndexMock.mockReturnValue(makeRegistry("local-only"));
|
|
|
|
await expect(listPersistedBundledPluginLocationBridges({})).resolves.toEqual([]);
|
|
});
|
|
});
|