fix(settings): persist per-model visibility and sibling selector state (#1700)

* fix(settings): persist per-model visibility and sibling selector state

The server-side settings sanitizer only allowlisted favoriteModels and
recentModels, so hiddenModels, collapsedModelProviders, recentAgents, and
recentEfforts were stripped on every write to settings.json — per-model
visibility and collapsed-provider state silently reset on every container
redeploy or settings reload.

Add the four missing fields to sanitizeSettingsUpdate:
- hiddenModels: sanitizeModelRefs(..., 1024) — same shape as favoriteModels;
  1024 covers dense multi-provider setups while bounding persistence/memory.
- collapsedModelProviders: normalizeStringArray with Array.isArray gate
  (matches usageDropdownProviders).
- recentAgents: normalizeStringArray (Array<string> per ui-store).
- recentEfforts: new sanitizeRecentEfforts validating Record<string, string[]>
  (shape confirmed in ui-store + addRecentEffort action); trims/dedupes keys
  and variants, caps at 128 keys x 5 variants/key (5 matches client slice).

No ui-store version bump or migration: zustand's default merge spreads
persisted state over defaults, so missing fields fall back to [] / {} until
the next toggle. favoriteModels and recentModels are untouched.

Tests: 8 new cases in settings-helpers.test.js using the real
sanitizeModelRefs / normalizeStringArray — round-trips, empty-[] parity with
favoriteModels, garbage rejection, and a full-payload regression test.

* fix: sync model selector settings

---------

Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
This commit is contained in:
Szasz Attila
2026-06-23 21:46:23 +03:00
committed by GitHub
co-authored by Bohdan Triapitsyn
parent 307808bec2
commit eae09d4576
6 changed files with 464 additions and 26 deletions
+4
View File
@@ -158,7 +158,11 @@ export type DesktopSettings = {
shortcutOverrides?: Record<string, string>;
favoriteModels?: Array<{ providerID: string; modelID: string }>;
hiddenModels?: Array<{ providerID: string; modelID: string }>;
collapsedModelProviders?: string[];
recentModels?: Array<{ providerID: string; modelID: string }>;
recentAgents?: string[];
recentEfforts?: Record<string, string[]>;
diffLayoutPreference?: 'dynamic' | 'inline' | 'side-by-side';
gitChangesViewMode?: 'flat' | 'tree';
directoryShowHidden?: boolean;