diff --git a/ui/src/ui/storage.ts b/ui/src/ui/storage.ts index 0b23b3436a4..fcd9c4469c8 100644 --- a/ui/src/ui/storage.ts +++ b/ui/src/ui/storage.ts @@ -1,8 +1,12 @@ -const KEY = "openclaw.control.settings.v1"; +const SETTINGS_KEY_PREFIX = "openclaw.control.settings.v1:"; const LEGACY_TOKEN_SESSION_KEY = "openclaw.control.token.v1"; const TOKEN_SESSION_KEY_PREFIX = "openclaw.control.token.v1:"; const MAX_SCOPED_SESSION_ENTRIES = 10; +function settingsKeyForGateway(gatewayUrl: string): string { + return `${SETTINGS_KEY_PREFIX}${normalizeGatewayTokenScope(gatewayUrl)}`; +} + type ScopedSessionSelection = { sessionKey: string; lastActiveSessionKey: string; @@ -188,7 +192,9 @@ export function loadSettings(): UiSettings { }; try { - const raw = storage?.getItem(KEY); + // First check for legacy key (no scope), then check for scoped key + const scopedKey = settingsKeyForGateway(defaults.gatewayUrl); + const raw = storage?.getItem(scopedKey) ?? storage?.getItem(SETTINGS_KEY_PREFIX + "default") ?? storage?.getItem("openclaw.control.settings.v1"); if (!raw) { return defaults; } @@ -256,9 +262,11 @@ function persistSettings(next: UiSettings) { persistSessionToken(next.gatewayUrl, next.token); const storage = getSafeLocalStorage(); const scope = normalizeGatewayTokenScope(next.gatewayUrl); + const scopedKey = settingsKeyForGateway(next.gatewayUrl); let existingSessionsByGateway: Record = {}; try { - const raw = storage?.getItem(KEY); + // Try to migrate from legacy key or other scopes + const raw = storage?.getItem(scopedKey) ?? storage?.getItem(SETTINGS_KEY_PREFIX + "default") ?? storage?.getItem("openclaw.control.settings.v1"); if (raw) { const parsed = JSON.parse(raw) as PersistedUiSettings; if (parsed.sessionsByGateway && typeof parsed.sessionsByGateway === "object") { @@ -294,5 +302,5 @@ function persistSettings(next: UiSettings) { sessionsByGateway, ...(next.locale ? { locale: next.locale } : {}), }; - storage?.setItem(KEY, JSON.stringify(persisted)); + storage?.setItem(scopedKey, JSON.stringify(persisted)); }