fix(cli): parse JSON object values in config set - #40546
Conversation
|
In One other thing I noticed -- the prefix/suffix check uses Not a blocker, just something to be aware of if edge cases around extremely nested config values come up. |
alpindiay
left a comment
There was a problem hiding this comment.
Review: PR #40546 -- fix(cli): parse JSON object values in config set
Summary: Adds structured value parsing to "hermes config set" so JSON objects and arrays passed as CLI values are properly deserialized into YAML mappings/lists rather than stored as raw strings. Includes tests.
What works well:
- The _coerce_cli_value helper is well-designed: it preserves the existing bool/int/float coercion first, then attempts JSON parsing only for {...} and [...] strings.
- Uses json.loads (safe) -- not eval.
- Graceful fallback: if JSON parsing fails, the raw string is returned unchanged. No crashes on invalid input.
- Tests are included covering three scenarios: valid nested object, provider block object, and invalid JSON fallback. All tests properly verify type (isinstance) as well as value.
- The docstring clearly explains the coercion order and fallback behavior.
Considerations:
- Nested function definition: _coerce_cli_value is defined inside set_config_value, meaning it is recreated on every call. A module-level function would be more efficient, but this is a negligible concern for a CLI command that runs once per invocation.
- Float detection fragility (pre-existing): The raw.replace(".", "", 1).isdigit() check can incorrectly classify strings like "1.2.3" or "..." as floats. This is existing code, not introduced here, but worth noting that json.loads would handle numeric parsing correctly if the coercion order were reconsidered in the future.
Verdict: Solid fix with good test coverage. Approve.
|
Thanks for the focused fix. The underlying bug is still present in the inspected checkout: Problems
Suggested changes
Automated hermes-sweeper review. |
1c0fddf to
129e616
Compare
|
Addressed in 129e616. Integrated structured JSON coercion with the newer string-typed leaf guard: settings declared as str in DEFAULT_CONFIG now preserve their raw value, including JSON-shaped strings, while non-string and dynamic settings retain scalar coercion and can parse JSON objects or arrays. Malformed object-like input still falls back to the original string. |
|
Thanks for working on this, @izumi0uu — this bug has been silently corrupting our config for weeks and we only traced it back to Affected version: Hermes Agent v0.19.0 (2026.7.20, Config keys we've seen corrupted by this:
The Workaround we built (for anyone else hitting this): A small Python script that detects quoted JSON strings in Really hoping this lands soon — it's a silent data-corruption bug that's hard to diagnose unless you know what to look for. Thanks again for the fix. |
What does this PR do?
Fixes
hermes config setso JSON object/array CLI values are persisted as structured YAML mappings/lists instead of quoted strings.This addresses a real configuration workflow where provider blocks such as
providers.deepseekwere being written with the wrong type, even though the CLI printed a success message.Related Issue
Fixes #40545
Type of Change
Changes Made
json-based structured value coercion inhermes_cli/config.py{...}) or arrays ([...])foo.bar '{"x":1}')providers.deepseek '{...}')How to Test
Reproduce the original bug on main:
Before this fix,
providers.deepseekis written as a quoted JSON string.Run the regression test file:
Verify the fixed behavior:
After this fix,
providers.deepseekis a YAML mapping withbase_url,key_env, andapi_modefields.Checklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests passDocumentation & Housekeeping
docs/, docstrings) — or N/Acli-config.yaml.exampleif I added/changed config keys — or N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — or N/AScreenshots / Logs
Relevant local verification: