





























@@ -5,6 +5,7 @@ const mocks = vi.hoisted(() => ({
55installPluginFromNpmSpec: vi.fn(),
66listChannelPluginCatalogEntries: vi.fn(),
77listOfficialExternalPluginCatalogEntries: vi.fn(),
8+loadInstalledPluginIndex: vi.fn(),
89loadInstalledPluginIndexInstallRecords: vi.fn(),
910loadPluginMetadataSnapshot: vi.fn(),
1011getOfficialExternalPluginCatalogManifest: vi.fn(
@@ -33,6 +34,11 @@ vi.mock("../../../plugins/installed-plugin-index-records.js", () => ({
3334mocks.writePersistedInstalledPluginIndexInstallRecords,
3435}));
353637+vi.mock("../../../plugins/installed-plugin-index.js", async (importOriginal) => ({
38+ ...(await importOriginal<typeof import("../../../plugins/installed-plugin-index.js")>()),
39+loadInstalledPluginIndex: mocks.loadInstalledPluginIndex,
40+}));
41+3642vi.mock("../../../plugins/install-paths.js", () => ({
3743resolveDefaultPluginExtensionsDir: mocks.resolveDefaultPluginExtensionsDir,
3844}));
@@ -76,6 +82,11 @@ describe("repairMissingConfiguredPluginInstalls", () => {
7682plugins: [],
7783diagnostics: [],
7884});
85+mocks.loadInstalledPluginIndex.mockReturnValue({
86+plugins: [],
87+diagnostics: [],
88+installRecords: {},
89+});
7990mocks.loadInstalledPluginIndexInstallRecords.mockResolvedValue({});
8091mocks.listChannelPluginCatalogEntries.mockReturnValue([]);
8192mocks.listOfficialExternalPluginCatalogEntries.mockReturnValue([]);
@@ -663,6 +674,75 @@ describe("repairMissingConfiguredPluginInstalls", () => {
663674});
664675});
665676677+it("uses current bundled discovery to remove records before stale snapshots can reinstall official plugins", async () => {
678+const records = {
679+"google-meet": {
680+source: "npm",
681+spec: "@openclaw/google-meet",
682+resolvedName: "@openclaw/google-meet",
683+installPath: "/missing/google-meet",
684+},
685+};
686+mocks.loadInstalledPluginIndexInstallRecords.mockResolvedValue(records);
687+mocks.loadPluginMetadataSnapshot.mockReturnValue({
688+plugins: [
689+{
690+id: "google-meet",
691+origin: "npm",
692+packageName: "@openclaw/google-meet",
693+},
694+],
695+diagnostics: [],
696+});
697+mocks.loadInstalledPluginIndex.mockReturnValue({
698+plugins: [
699+{
700+pluginId: "google-meet",
701+origin: "bundled",
702+packageName: "@openclaw/google-meet",
703+},
704+],
705+diagnostics: [],
706+installRecords: {},
707+});
708+mocks.listOfficialExternalPluginCatalogEntries.mockReturnValue([
709+{
710+id: "google-meet",
711+label: "Google Meet",
712+install: { npmSpec: "@openclaw/google-meet" },
713+openclaw: {
714+id: "google-meet",
715+install: { npmSpec: "@openclaw/google-meet" },
716+},
717+},
718+]);
719+720+const { repairMissingConfiguredPluginInstalls } =
721+await import("./missing-configured-plugin-install.js");
722+const result = await repairMissingConfiguredPluginInstalls({
723+cfg: {
724+plugins: {
725+entries: {
726+"google-meet": { enabled: true },
727+},
728+},
729+},
730+env: {},
731+});
732+733+expect(mocks.installPluginFromNpmSpec).not.toHaveBeenCalled();
734+expect(mocks.writePersistedInstalledPluginIndexInstallRecords).toHaveBeenCalledWith(
735+{},
736+{
737+env: {},
738+},
739+);
740+expect(result).toEqual({
741+changes: ['Removed stale managed install record for bundled plugin "google-meet".'],
742+warnings: [],
743+});
744+});
745+666746it.each([
667747[
668748"npm",
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。