fix(memory): read non-secret provider config from config.yaml for OpenViking and RetainDB (#68209) - #68228
Conversation
trac3r00
left a comment
There was a problem hiding this comment.
Checked out pr-68228 locally (Python 3.11) and verified the claims end-to-end:
Test evidence
- On the PR head:
tests/plugins/memory/test_openviking_provider.py+tests/plugins/memory/test_retaindb_provider.py→ 144 passed (matches the PR description). - Cherry-picking only the new tests onto
main(no source changes) → 5 failed, 139 passed, and the failures are exactly the regressions this PR claims to fix:test_resolve_connection_settings_reads_config_yaml_non_secret_fields— OpenViking never foldsmemory.openviking.*non-secret fields into resolution.test_is_available_true_for_config_yaml_endpoint— a config.yaml-only endpoint reportsneeds_configon main.- The three RetainDB
initialize()tests fail on main (_load_retaindb_configdoesn't exist there), confirmingbase_url/projectwere env-only.
So the tests are genuine failing-then-green regression tests, not change detectors.
Code review
- Resolution order (env → ovcli → config.yaml → default for OpenViking; env → config.yaml → default for RetainDB) matches the documented intent, and secrets (
api_key) stay env-only in both providers — good scoping. - Both call sites of
_resolve_connection_settings()(lines ~1956 and ~2156) already pass_load_hermes_openviking_config(), so the newprovider_configfallback is reachable from both paths. _load_retaindb_config()swallowing all exceptions and returning{}mirrors the existing_load_hermes_openviking_config()pattern, so behavior is consistent across the two providers.
One minor behavioral note (not blocking)
In RetainDB, os.environ.get("RETAINDB_BASE_URL") or _config_str(...) means an env var explicitly set to the empty string now falls through to config.yaml/default, whereas main would have used the empty string verbatim (producing a broken "" base URL). I'd call that an improvement, but it's technically a behavior change worth being aware of.
LGTM — focused fix, real regression coverage, consistent with the surrounding config-reading patterns.
[bob]
teknium1
left a comment
There was a problem hiding this comment.
Thanks for the focused fix. The reported behavior is still present on current main: OpenViking ignores memory.openviking.endpoint in plugins/memory/openviking/__init__.py:920-939 and :1927-1938; RetainDB reads URL/project only from environment variables at plugins/memory/retaindb/__init__.py:490-502.
Problems
- The added tests stub the new config-loading boundary or pass an in-memory config directly, so they do not verify the Dashboard's persisted
config.yamlpath. The real write path persists non-secret fields undermemory.<provider>athermes_cli/web_server.py:6436-6467. - The proposed RetainDB helper uses
load_config()atplugins/memory/retaindb/__init__.py:54even though it is read-only. OpenViking deliberately usesload_config_readonly()atplugins/memory/openviking/__init__.py:897-905; its test enforces that attests/plugins/memory/test_openviking_provider.py:86-116.
Suggested changes
- Switch RetainDB to
load_config_readonly(). - Add temp-
HERMES_HOMEfile-backed regression coverage for both providers, including env-over-config precedence.
This is an automated hermes-sweeper review.
| unset. The secret ``api_key`` continues to come from the environment. | ||
| """ | ||
| try: | ||
| from hermes_cli.config import load_config |
There was a problem hiding this comment.
This helper only reads configuration, so use load_config_readonly() here. That matches OpenViking's runtime reader (plugins/memory/openviking/__init__.py:897-905) and avoids the defensive deepcopy performed by load_config().
3b723f3 to
dca5791
Compare
…nViking and RetainDB OpenViking is_available() only consulted env vars and use_ovcli_config, so an endpoint saved to config.yaml (e.g. by the Dashboard) reported needs_config; _resolve_connection_settings() likewise never folded config.yaml's non-secret fields into its chain. RetainDB initialize() read base_url/project from the environment only, ignoring the values the Dashboard writes to config.yaml. Both now resolve non-secret fields as env -> (ovcli ->) config.yaml -> default; secrets still come from the environment. Adds regression tests for both. Fixes NousResearch#68209
dca5791 to
521de8c
Compare
|
Merged via #77747 — your commits cherry-picked with authorship preserved (rebase merge). This PR consolidated your config.yaml readback fix for OpenViking and RetainDB together with 5 other OpenViking fixes into one coherent integration so the complete runtime behavior could be validated as a unit. Thanks for the contribution! |
What does this PR do?
Two in-tree memory providers ignore the non-secret configuration the Dashboard writes to
config.yaml, so they can't be enabled through the UI. The root cause is on the reading side — secrets already reach the runtime viasave_env_value()'sos.environsync; the non-secret fields (endpoint, base_url, project) are saved toconfig.yamlbut never read back.is_available()only checkedOPENVIKING_ENDPOINTanduse_ovcli_config, so anendpointsaved tomemory.openviking.endpointreportedneeds_config._resolve_connection_settings()likewise never foldedconfig.yaml's non-secret fields into its resolution chain, so even past an availability check the runtime would fall back to the default endpoint.initialize()readbase_url/projectfromos.environonly, ignoring the values the Dashboard persists tomemory.retaindb.*.Both now resolve non-secret fields as env → (ovcli →) config.yaml → default; secrets continue to come from the environment only. Scoped deliberately to these two reading bugs — the issue's broader "shared config interface for all 8 providers" refactor is intentionally left out.
Related Issue
Fixes #68209
Type of Change
Changes Made
plugins/memory/openviking/__init__.pyis_available()now returnsTruewhen a non-secretendpointis present inconfig.yaml(not just env/ovcli)._resolve_connection_settings()foldsconfig.yaml's non-secret fields (endpoint,account,user,agent) into the chain before the built-in default; the secretapi_keyis unchanged (env-sourced).plugins/memory/retaindb/__init__.py_load_retaindb_config()(reads thememory.retaindbblock, empty on error) and a small_config_str()helper.initialize()falls back toconfig.yamlforbase_urlandprojectwhen the env var is unset.tests/plugins/memory/test_openviking_provider.py,tests/plugins/memory/test_retaindb_provider.pyHow to Test
Result:
144 tests passed, 0 failed. The new tests fail againstupstream/main(OpenVikingis_available()returnsFalsefor a config.yaml-only endpoint; RetainDB'sinitialize()never consultsconfig.yaml) and pass with this change.Manual: set
memory.openviking.endpoint(ormemory.retaindb.base_url/project) inconfig.yamlwith no matching env var — OpenViking now reports available, and RetainDB connects to the configured base URL/project instead of the defaults.Checklist
Code
fix(scope):,feat(scope):, etc.)Documentation & Housekeeping
docs/, docstrings) — or N/A (docstrings updated inline; behavior documented in code comments)cli-config.yaml.exampleif I added/changed config keys — N/A (no new keys; reads existingmemory.<provider>.*)CONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — N/A