From 2e2fff08697417876d54363ca9155d4503509636 Mon Sep 17 00:00:00 2001 From: ciregenz Date: Sat, 20 Jun 2026 03:22:03 -0700 Subject: [PATCH] [eric] settings: broadcast settings:changed on agent write so the UI reflects it instantly (no focus wait) --- backend/main.py | 8 ++++++++ frontend/src/shared/ws/WebSocketManager.ts | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/backend/main.py b/backend/main.py index f3f123b7..93d905e4 100644 --- a/backend/main.py +++ b/backend/main.py @@ -840,6 +840,14 @@ async def settings_meta(action: str, request: Request): for f in staged: outcomes[f] = {"status": "error", "reason": f"write failed: {e}"} + if any(o.get("status") == "applied" for o in outcomes.values()): + # An agent wrote settings (not the user via the modal), so nudge every + # open window to refetch instead of waiting for the next window-focus. + # Pure signal: the renderer refetches the authoritative state, so nothing + # (least of all a secret) needs to ride the broadcast. + from backend.apps.agents.core.ws_manager import ws_manager as _wsm + await _wsm.broadcast_global("settings:changed", {}) + return JSONResponse({"outcomes": outcomes}) return JSONResponse({"error": f"unknown action: {action}"}, status_code=400) diff --git a/frontend/src/shared/ws/WebSocketManager.ts b/frontend/src/shared/ws/WebSocketManager.ts index 7d3d6f8e..e1cae746 100644 --- a/frontend/src/shared/ws/WebSocketManager.ts +++ b/frontend/src/shared/ws/WebSocketManager.ts @@ -26,6 +26,7 @@ import { import { streamStart, streamDelta, streamEnd, clearStreamingForSession } from '../state/streamingSlice'; import { addBrowserCardFromBackend, markBrowserCardEnding, keepBrowserCardOpen, placeInParentColumn, setBrowserCardPosition, setGlowingBrowserCards } from '../state/dashboardLayoutSlice'; import { upsertOutput } from '../state/outputsSlice'; +import { fetchSettings } from '../state/settingsSlice'; import { displaySessionName } from '../state/sessionDisplay'; import { getAuthToken } from '../config'; import { notifyAgentCompletion } from '../notifications'; @@ -822,6 +823,13 @@ class WebSocketManager { } } break; + + case 'settings:changed': + // An agent wrote settings under us (not the user via the modal), so refetch + // now instead of waiting for the next window-focus. The slice's latestWriteId + // guard drops this if a newer user save is already in flight. + store.dispatch(fetchSettings()); + break; } // Notify any custom listeners