From 5e3d2e4849c0f2512330801d804fb96f4ab72d28 Mon Sep 17 00:00:00 2001 From: Ayobami Adegoke Date: Sat, 25 Jul 2026 16:28:56 +0100 Subject: [PATCH] fix(desktop): surface agent rename relay profile sync failure as a warning toast (#2279) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #1822 ## Problem Renaming an agent via the agent settings dialog performs a local save (always succeeds) and a best-effort relay kind:0 republish (can fail: network blip, auth expiry, relay unreachable). On sync failure the dialog `console.warn`'d the error and closed as a clean success — the user had no signal that the relay still holds the old name, which breaks `@mention` resolution and shows the stale name in other agents' `From:` lines (discovered via #1743). ## Fix Surface `profileSyncError` as a `toast.warning` in `AgentInstanceEditDialog`, matching the treatment the create and persona-save paths already give the same field (`useManagedAgentActions.ts`, `UserProfilePanelPersonaSubmit.ts`). The save is not blocked — the local rename is valid and persists, per the issue's guidance. The toast points at the retry path that actually works: **restarting the agent**. Re-saving the same name does not retry — `update_managed_agent` computes `name_changed` against the already-updated record, so a second identical save skips the sync — but `start_managed_agent` fires `reconcile_agent_profile`, which queries the relay's kind:0 and republishes when the display name diverges. Scope notes: - `EditRespondToDialog` (the third caller of the update mutation) never changes the name, and the Rust side only sets `profile_sync_error` when the name changed — so no change needed there. - The alternative fix in the issue (retry-with-backoff in `sync_managed_agent_profile`) is not taken here; `reconcile_agent_profile` on agent start already provides self-healing, and this change makes that path discoverable at the moment of failure. ## Testing - `just desktop-check` — biome + file-size + px-text + pubkey-truncation guards clean. - `just desktop-test` — 3331 passed, 0 failed. - The handler branch is a straight conditional on the mutation result; the repo's `.test.mjs` convention covers extracted pure logic, and there is no extracted logic here to unit-test (consistent with the equivalent toast branches on the create/persona paths). --------- Signed-off-by: ayobamiseun Signed-off-by: npub1mprnacetjua2xx3p5eddmhxyk6wv929ymm5py8kd2xfxurxahspqqlgyta Co-authored-by: npub1mprnacetjua2xx3p5eddmhxyk6wv929ymm5py8kd2xfxurxahspqqlgyta --- .../features/agents/ui/AgentInstanceEditDialog.tsx | 6 +++--- .../src/features/agents/ui/agentProfileSyncWarning.ts | 11 +++++++++++ 2 files changed, 14 insertions(+), 3 deletions(-) create mode 100644 desktop/src/features/agents/ui/agentProfileSyncWarning.ts diff --git a/desktop/src/features/agents/ui/AgentInstanceEditDialog.tsx b/desktop/src/features/agents/ui/AgentInstanceEditDialog.tsx index 5cd5c7a016..86a70c3db6 100644 --- a/desktop/src/features/agents/ui/AgentInstanceEditDialog.tsx +++ b/desktop/src/features/agents/ui/AgentInstanceEditDialog.tsx @@ -1,7 +1,6 @@ import * as React from "react"; import { ChevronDown } from "lucide-react"; import { AnimatePresence, motion, useReducedMotion } from "motion/react"; - import { toast } from "sonner"; import { @@ -83,6 +82,7 @@ import { AgentDefaultsDialog } from "./AgentDefaultsDialog"; import { useProviderApiKeyFieldState } from "./providerApiKeyFieldState"; import { resolveModelFieldStatusMessage } from "./agentConfigControls"; import { AdvancedRequiredBadge } from "./AdvancedRequiredBadge"; +import { showAgentProfileSyncWarning } from "./agentProfileSyncWarning"; const ADVANCED_FIELDS_MOTION_TRANSITION = { duration: 0.18, @@ -101,8 +101,7 @@ export function AgentInstanceEditDialog({ /** Optional field to scroll/focus when the dialog opens from a card deep-link. */ initialFocus?: EditAgentFocusTarget; open: boolean; - /** Present only when the linked definition is editable (non-built-in, - * resolved). Caller closes this dialog and enters definition-edit. */ + /** Present only when the linked definition is editable (non-built-in, resolved). Caller closes this dialog and enters definition-edit. */ onEditLinkedPersona?: () => void; onOpenChange: (open: boolean) => void; onUpdated?: (agent: ManagedAgent) => void; @@ -706,6 +705,7 @@ export function AgentInstanceEditDialog({ autoRestartOnConfigChange, ); } + showAgentProfileSyncWarning(result.agent.name, result.profileSyncError); handleOpenChange(false); onUpdated?.(result.agent); // The auto-restart policy deliberately never fires for a stopped or diff --git a/desktop/src/features/agents/ui/agentProfileSyncWarning.ts b/desktop/src/features/agents/ui/agentProfileSyncWarning.ts new file mode 100644 index 0000000000..91be216fd6 --- /dev/null +++ b/desktop/src/features/agents/ui/agentProfileSyncWarning.ts @@ -0,0 +1,11 @@ +import { toast } from "sonner"; + +export function showAgentProfileSyncWarning( + agentName: string, + profileSyncError: string | null, +) { + if (!profileSyncError) return; + toast.warning( + `${agentName} was saved, but relay profile sync failed: ${profileSyncError}. The relay may still show the old name — restart the agent to retry the sync.`, + ); +}