diff --git a/apps/desktop/src/components/layout/UpdateDialog.spec.ts b/apps/desktop/src/components/layout/UpdateDialog.spec.ts index 1363259bf1..79b060b0c2 100644 --- a/apps/desktop/src/components/layout/UpdateDialog.spec.ts +++ b/apps/desktop/src/components/layout/UpdateDialog.spec.ts @@ -512,4 +512,31 @@ describe("UpdateDialog aggregate update center", () => { expect(installComponentUpdates).toHaveBeenCalledWith("drivers"); }); + + it("marks only a plugin whose update source changed as needing confirmation in the Plugin Center", async () => { + const listing = (id: string, provenance: Record) => ({ + key: `official:${id}`, + status: "update", + artifact: { target: "universal", url: "https://example.com/plugin.dbxp", sha256: "hash", signingKeyId: "key-a" }, + repository: { id: "official" }, + plugin: { id, latestVersion: "1.1.0", publisher: "DBX" }, + installed: { manifest: { id, version: "1.0.0" }, provenance }, + name: `${id} plugin`, + }); + await mountDialog(0, {}, undefined, { + updateInfo: null, + pluginUpdates: [listing("same", { repositoryId: "official" }), listing("moved", { repositoryId: "other-repo" })], + }); + + const pluginsTab = document.body.querySelector('[data-update-tab="plugins"]'); + pluginsTab?.click(); + await flushDialog(); + + // "Update all" skips the changed-source plugin, so the dialog has to explain why it stays. + const hint = "Confirm the change in the Plugin Center first"; + const rows = [...document.body.querySelectorAll(".rounded-md.border.p-3")]; + const rowFor = (name: string) => rows.find((row) => row.textContent?.includes(name)); + expect(rowFor("moved plugin")?.textContent).toContain(hint); + expect(rowFor("same plugin")?.textContent).not.toContain(hint); + }); }); diff --git a/apps/desktop/src/components/layout/UpdateDialog.vue b/apps/desktop/src/components/layout/UpdateDialog.vue index a98ce5a2fe..346c175e00 100644 --- a/apps/desktop/src/components/layout/UpdateDialog.vue +++ b/apps/desktop/src/components/layout/UpdateDialog.vue @@ -8,7 +8,7 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@ import type { UpdateInfo } from "@/lib/backend/api"; import type { AgentDriverInfo, McpServerStatus, UpdateDownloadSource } from "@/lib/backend/tauri"; import type { JdbcPluginStatus } from "@/types/database"; -import type { MarketplacePluginListing } from "@/lib/plugins/pluginMarketplace"; +import { pluginSourceChange, type MarketplacePluginListing } from "@/lib/plugins/pluginMarketplace"; import { mcpUpdateAvailability } from "@/lib/mcp/mcpUpdateStatus"; import { isTauriRuntime } from "@/lib/backend/tauriRuntime"; import { isUpdatePreviewMockEnabled } from "@/lib/updates/updatePreviewMock"; @@ -302,6 +302,9 @@ watch(
{{ plugin.name }}
{{ plugin.installed?.manifest.version || t("updates.notInstalled") }} → {{ plugin.plugin.latestVersion }}
+ +
{{ t("pluginPlatform.updateSourceChangeRequired") }}
{{ t("settings.updateAvailable") }} diff --git a/apps/desktop/src/components/plugins/PluginContributionsPanel.vue b/apps/desktop/src/components/plugins/PluginContributionsPanel.vue index 18160342b6..07d45f67d2 100644 --- a/apps/desktop/src/components/plugins/PluginContributionsPanel.vue +++ b/apps/desktop/src/components/plugins/PluginContributionsPanel.vue @@ -1,6 +1,6 @@