Bug Description
hermes setup can overwrite configuration changes made by the shared model/provider picker before the setup wizard exits.
This affects auxiliary task model choices made during setup. For example, if the picker writes an auxiliary override such as:
auxiliary:
compression:
provider: gemini
model: gemini-2.5-flash
the setup wizard can later save its stale in-memory config snapshot and reset that choice back to auto.
This is the same stale-config class as the custom-provider overwrite issue, but the current resync only preserves selected top-level keys (model, custom_providers). Any other section written by the shared picker can still be lost.
Steps to Reproduce
- Start with default config where
auxiliary.compression.provider is auto.
- Run the setup model flow and choose an auxiliary model/provider override from the delegated picker path.
- Allow setup to complete so the outer wizard performs its final
save_config(config).
- Inspect
~/.hermes/config.yaml.
Minimal regression shape:
- Load setup's in-memory config.
- Simulate
select_provider_and_model() writing auxiliary.compression.provider = gemini and model = gemini-2.5-flash to disk.
- Return to
setup_model_provider().
- Call
save_config(config) as the setup wizard does on exit.
Expected Behavior
Any config changes written by the shared model/provider picker should survive the setup wizard's final save, including auxiliary task choices and future picker-owned sections.
Actual Behavior
The final setup save can write the older in-memory config object back to disk, reverting picker-written values. Current code only resyncs a small whitelist (model, custom_providers), so auxiliary choices can still be lost.
Affected Component
- Setup / Installation
- Configuration (config.yaml, .env, hermes setup)
Messaging Platform (if gateway-related)
N/A (CLI only)
Debug Report
Not attached. This is a local code-path regression with a focused unit test reproduction; no credentials or runtime logs are needed to reproduce it.
Operating System
Ubuntu 24.04
Python Version
Python 3.11.15
Hermes Version
Hermes Agent v0.13.0 (2026.5.7), observed against commit 242da9db9.
Additional Logs / Traceback (optional)
No traceback; this is silent config loss.
Root Cause Analysis (optional)
setup_model_provider(config) delegates to select_provider_and_model(). That picker and its subflows perform their own load_config() / save_config() cycle and write to config.yaml directly.
The outer setup wizard still holds the earlier config dict loaded at wizard startup. When setup later calls save_config(config), that stale object can overwrite what the picker wrote.
The current code partially mitigates this by copying back model and custom_providers after the picker returns, but the same root cause applies to any picker-written section, including auxiliary.
Proposed Fix (optional)
After the shared picker returns, reload config.yaml and refresh the caller's dict in place:
_refreshed = load_config()
config.clear()
config.update(_refreshed)
This preserves object identity for the rest of setup while ensuring the final wizard save uses the latest on-disk config.
Are you willing to submit a PR for this?
Yes. PR incoming.
Bug Description
hermes setupcan overwrite configuration changes made by the shared model/provider picker before the setup wizard exits.This affects auxiliary task model choices made during setup. For example, if the picker writes an auxiliary override such as:
the setup wizard can later save its stale in-memory config snapshot and reset that choice back to
auto.This is the same stale-config class as the custom-provider overwrite issue, but the current resync only preserves selected top-level keys (
model,custom_providers). Any other section written by the shared picker can still be lost.Steps to Reproduce
auxiliary.compression.providerisauto.save_config(config).~/.hermes/config.yaml.Minimal regression shape:
select_provider_and_model()writingauxiliary.compression.provider = geminiandmodel = gemini-2.5-flashto disk.setup_model_provider().save_config(config)as the setup wizard does on exit.Expected Behavior
Any config changes written by the shared model/provider picker should survive the setup wizard's final save, including auxiliary task choices and future picker-owned sections.
Actual Behavior
The final setup save can write the older in-memory config object back to disk, reverting picker-written values. Current code only resyncs a small whitelist (
model,custom_providers), so auxiliary choices can still be lost.Affected Component
Messaging Platform (if gateway-related)
N/A (CLI only)
Debug Report
Not attached. This is a local code-path regression with a focused unit test reproduction; no credentials or runtime logs are needed to reproduce it.
Operating System
Ubuntu 24.04
Python Version
Python 3.11.15
Hermes Version
Hermes Agent v0.13.0 (2026.5.7), observed against commit
242da9db9.Additional Logs / Traceback (optional)
No traceback; this is silent config loss.
Root Cause Analysis (optional)
setup_model_provider(config)delegates toselect_provider_and_model(). That picker and its subflows perform their ownload_config()/save_config()cycle and write toconfig.yamldirectly.The outer setup wizard still holds the earlier
configdict loaded at wizard startup. When setup later callssave_config(config), that stale object can overwrite what the picker wrote.The current code partially mitigates this by copying back
modelandcustom_providersafter the picker returns, but the same root cause applies to any picker-written section, includingauxiliary.Proposed Fix (optional)
After the shared picker returns, reload
config.yamland refresh the caller's dict in place:This preserves object identity for the rest of setup while ensuring the final wizard save uses the latest on-disk config.
Are you willing to submit a PR for this?
Yes. PR incoming.