mirror of
https://github.com/OpenHands/OpenHands.git
synced 2026-10-07 14:17:58 +08:00
* settings: persist app preferences and disabled_skills on the agent-server The local agent-server now exposes app_preferences on the persisted settings (OpenHands/software-agent-sdk#3539): language, sound notifications, analytics consent, git identity, and disabled_skills are returned on GET /api/settings under app_preferences and updated via a new app_preferences_diff field on PATCH /api/settings. This brings the local agent-server to parity with the cloud, which has always accepted the same keys at the top level. Drops the localStorage workaround that mirrored these fields in two keys (openhands-agent-server-app-preferences and openhands-agent-server-disabled-skills), along with the app-preferences-store.ts module and the DISABLED_SKILLS_STORAGE_KEY helpers it depended on. - SettingsService.transformApiResponse reads app_preferences from the server response and hoists each field onto the flat Settings shape so consumers (settings.language, settings.disabled_skills, …) keep working unchanged. - SettingsService.saveSettings routes the same set of fields through the new app_preferences_diff for local backends and through the existing app_preferences flat-spread path for cloud backends. - New legacy-app-preferences-migration.ts runs once on first getSettings() after upgrade: when the server reports an app_preferences block AND legacy localStorage values are still present, it pushes them up via app_preferences_diff and clears the legacy keys. Pre-1.27 servers (which omit app_preferences entirely) cause the migration to no-op so existing data isn't dropped before the server can accept it. - Updated MSW handlers to round-trip app_preferences and app_preferences_diff so the mock backend matches production. - Test coverage: 5 new tests in __tests__/api/settings-service.test.ts for the local round-trip, the mixed diff routing, the legacy migration, and the pre-1.27 skip path. Closes the localStorage workaround called out in the recent audit of agent-canvas localStorage usage (items 3 and 4: disabled_skills and app-preferences fields). Depends on agent-server 1.27 / SDK PR #3539. Co-authored-by: openhands <openhands@all-hands.dev> * settings: read/write app preferences via misc_settings container Follow-up to the localStorage cleanup in this PR + SDK refactor in openhands/software-agent-sdk#3543. The agent-server now exposes frontend-owned settings under a generic misc_settings container instead of a top-level app_preferences field. Wire shape changes: Before: After: GET /api/settings GET /api/settings -> { app_preferences: {...} } -> { misc_settings: { app_preferences: {...} } } PATCH /api/settings PATCH /api/settings body.app_preferences_diff (shallow body.misc_settings_diff (deep-merged, overlay, replaces named fields) same semantics as agent_settings_diff) Why the rename to misc_settings: the previous name pinned the API to a single 'frontend-owned' namespace. Adding a future category like ui_preferences (sidebar layout / view modes) would have required either yet another top-level field or shoehorning unrelated UI state into AppPreferences. With misc_settings as a container, new categories drop in as nested fields without churning the top-level shape. Changes: - settings-service.api.ts * SettingsApiResponse.app_preferences -> .misc_settings (typed) * SettingsUpdateRequest.app_preferences_diff -> .misc_settings_diff * Add MiscSettings interface * transformApiResponse reads response.misc_settings?.app_preferences * saveSettings emits { misc_settings_diff: { app_preferences } } * Local 'has any diffs' check tracks misc_settings_diff * Doc comments updated; semantics noted as deep-merge - legacy-app-preferences-migration.ts * Gate on serverResponse.misc_settings, not .app_preferences * pushDiff callback now wraps the diff in { app_preferences: ... } - src/mocks/settings-handlers.ts * GET handler returns misc_settings.app_preferences * PATCH handler accepts misc_settings_diff; deep-merges nested app_preferences into the persisted block * Internal mock state stores under misc_settings to match wire shape - __tests__/api/settings-service.test.ts * Four tests updated to assert the new wire shape (local PATCH body, GET round-trip, mixed-diff routing, legacy localStorage migration) * Pre-1.27 detection test now keys off missing misc_settings - AGENTS.md * App-preferences note rewritten for the misc_settings container, explains deep-merge semantics, and documents the in-flight rename (flat shape introduced in #3539 never shipped to users) Cloud path is unchanged: cloud /api/v1/settings still accepts the fields as flat top-level keys, mirrored by saveCloudSettings. Verification: $ npm run typecheck exit 0 $ npm test -- __tests__/api/settings-service.test.ts \ __tests__/api/mock-settings-handlers.test.ts 23 tests passed $ npm test 3009 passed | 12 skipped | 9 todo $ npm run lint All matched files use Prettier code style! $ npm run build built in 1.50s Co-authored-by: openhands <openhands@all-hands.dev> * Bump agent-server default to 1.27.0 Co-authored-by: openhands <openhands@all-hands.dev> --------- Co-authored-by: openhands <openhands@all-hands.dev>