mirror of
https://github.com/OpenHands/OpenHands.git
synced 2026-10-07 12:58:49 +08:00
* fix(skills): save disabled_skills when settings has no prior disabled_skills field
The hydration effect in SkillsSettingsScreen only set hasHydratedInitialSettings=true
when settings?.disabled_skills was truthy. When no skills had ever been disabled,
the server omits the field entirely (undefined), so the condition was always false:
if (settings?.disabled_skills) { ... } // skipped when field is absent
Because settings?.disabled_skills is undefined both before *and* after settings
load, the dependency array [settings?.disabled_skills] never changed value on
load either, so the effect never ran a second time. hasHydratedInitialSettings
stayed false, and the save effect's early-return guard blocked every toggle.
Fix by gating on settingsLoading instead and defaulting the missing field with
?? []. Also add a localStorage stub for Node.js 25+ which ships a built-in
localStorage that is non-functional without --localstorage-file, breaking the
zustand persist middleware in the test environment.
Co-authored-by: openhands <openhands@all-hands.dev>
* fix(tests): use mockResolvedValue(true) for saveSettings spy
saveSettings returns Promise<boolean>, not Promise<void>, so
mockResolvedValue(undefined) caused TS2345 type errors in CI.
Co-authored-by: openhands <openhands@all-hands.dev>
* fix(skills): persist disabled_skills to localStorage for local backend
The local agent-server has no concept of disabled_skills and its
PATCH /api/settings strips the field before sending. As a result,
toggling a skill off appeared to work in the UI but was never
persisted -- the value was silently discarded on every save and
page refresh reverted the toggle.
Fix by mirroring the existing app-preferences pattern:
- saveSettings (local path): call writeStoredDisabledSkills before
stripping the field from the PATCH payload.
- transformApiResponse: call readStoredDisabledSkills and overlay it
onto the partial Settings returned from the API, so every getSettings
call (cached or fresh) surfaces the stored value.
Export DISABLED_SKILLS_STORAGE_KEY so tests can reference the key
without duplicating the string literal.
Co-authored-by: openhands <openhands@all-hands.dev>
* fix: truncate long conversation title on mobile to keep tab toggle visible
When a conversation title was long enough it would overflow and hide the
RightPanelToggle button (the tab toggle) in the top-right of the mobile
header. Fixed by:
- Adding `min-w-0` to the left-side flex container in
ConversationNameWithStatus so it can shrink and the toggle stays in view
- Adding `shrink-0` to the status dot wrapper so it never collapses
- Adding `min-w-0` to ConversationName's root div (flex item) to allow
it to shrink within the parent
- Removing `w-fit max-w-fit` from the title div (both prevented
`truncate` from ever activating) so the title now properly truncates
with an ellipsis when too long
- Adding `shrink-0` to the ellipsis-button wrapper so it is always
accessible regardless of title length
Fixes #848
Co-authored-by: openhands <openhands@all-hands.dev>
---------
Co-authored-by: openhands <openhands@all-hands.dev>