mirror of
https://github.com/nesquena/hermes-webui.git
synced 2026-07-16 12:40:18 +00:00
stage #4516: apply config defaults to non-default profile reads (#4465 / #4513) + v0.51.532 CHANGELOG
This commit is contained in:
@@ -3,6 +3,12 @@
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [v0.51.532] — 2026-06-20 — Release SQ (built-in personalities on non-default profiles)
|
||||
|
||||
### Fixed
|
||||
|
||||
- **Non-default profiles now see the built-in personalities too (follow-up to #4465, closes the #4513 gap).** v0.51.525 hydrated the 14 built-in personalities for the default profile, but `get_config_for_profile_home()` — used by the streaming worker to resolve a non-default profile's config — was a pure file read with no defaults applied, so a fresh non-default profile still resolved `personalities: []`. It now applies the documented config defaults (including the built-ins) to the per-profile read, matching the ambient `get_config()` shape, without mutating any global cache. A non-existent profile home returns an empty dict. Thanks @franksong2702.
|
||||
|
||||
## [v0.51.531] — 2026-06-20 — Release SP (plugins panel: correct active-provider badge)
|
||||
|
||||
### Fixed
|
||||
|
||||
+8
-1
@@ -510,6 +510,8 @@ def get_config_for_profile_home(profile_home: "Path | str | None") -> dict:
|
||||
target = Path(profile_home).expanduser()
|
||||
except Exception:
|
||||
return get_config()
|
||||
if not target.exists():
|
||||
return {}
|
||||
# If the ambient resolver already points at this profile home, defer to
|
||||
# get_config() so in-memory overrides (monkeypatched cfg) are honored.
|
||||
try:
|
||||
@@ -517,7 +519,12 @@ def get_config_for_profile_home(profile_home: "Path | str | None") -> dict:
|
||||
return get_config()
|
||||
except Exception:
|
||||
pass
|
||||
return _load_yaml_config_file(target / "config.yaml")
|
||||
# Read the profile file directly and apply documented defaults locally so the
|
||||
# returned dict matches ambient get_config() shape (including built-in
|
||||
# personalities) without mutating any global cache state.
|
||||
profile_cfg = _load_yaml_config_file(target / "config.yaml")
|
||||
_apply_config_defaults(profile_cfg)
|
||||
return profile_cfg
|
||||
|
||||
|
||||
def _config_for_yaml_save(config_data: dict) -> dict:
|
||||
|
||||
@@ -69,6 +69,42 @@ def test_config_defaults_replace_non_dict_personality_section_with_builtins():
|
||||
assert set(cfg["agent"]["personalities"]) == BUILTIN_NAMES
|
||||
|
||||
|
||||
def test_profile_home_config_read_hydrates_builtin_personalities_without_writing(tmp_path):
|
||||
profile_home = tmp_path / "profiles" / "research"
|
||||
profile_home.mkdir(parents=True)
|
||||
|
||||
cfg = config.get_config_for_profile_home(profile_home)
|
||||
|
||||
personalities = cfg["agent"]["personalities"]
|
||||
assert set(personalities) == BUILTIN_NAMES
|
||||
assert personalities["helpful"] == "You are a helpful, friendly AI assistant."
|
||||
assert not (profile_home / "config.yaml").exists()
|
||||
|
||||
|
||||
def test_profile_home_config_read_merges_custom_personalities(tmp_path):
|
||||
profile_home = tmp_path / "profiles" / "research"
|
||||
profile_home.mkdir(parents=True)
|
||||
(profile_home / "config.yaml").write_text(
|
||||
"\n".join(
|
||||
[
|
||||
"agent:",
|
||||
" personalities:",
|
||||
" helpful: Custom helpful prompt.",
|
||||
" analyst:",
|
||||
" system_prompt: Use careful evidence.",
|
||||
]
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
cfg = config.get_config_for_profile_home(profile_home)
|
||||
|
||||
personalities = cfg["agent"]["personalities"]
|
||||
assert set(BUILTIN_NAMES).issubset(personalities)
|
||||
assert personalities["helpful"] == "Custom helpful prompt."
|
||||
assert personalities["analyst"]["system_prompt"] == "Use careful evidence."
|
||||
|
||||
|
||||
def test_config_save_strips_generated_builtin_personalities(tmp_path):
|
||||
cfg = {}
|
||||
config._apply_config_defaults(cfg)
|
||||
|
||||
Reference in New Issue
Block a user