mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-21 10:22:18 +00:00
* fix(desktop): show Hindsight memory provider
* feat(desktop): configure Hindsight memory provider
* fix(desktop): limit Hindsight modes to supported setup
* refactor(desktop): generic memory-provider config surface
Replace the bespoke Hindsight settings surface with a declarative,
schema-driven path so adding a memory provider is pure declaration —
no per-provider page, conditional, or endpoint.
- memory_providers.py: declarative registry. Each provider lists its
fields {key, label, kind, default, options, secret-vs-plain}. Hindsight's
mode is a select(cloud, local_external), so rejecting local_embedded
falls out of generic enum validation instead of a hand-written check.
- One generic endpoint pair GET/PUT /api/memory/providers/{name}/config.
GET returns declared fields + current values (secrets only as is_set,
never read back); PUT validates selects against their options, writes
plain fields to the provider config file, secrets to the env store,
and flips memory.provider.
- ProviderConfigPanel renders straight from the schema, replacing
hindsight-settings.tsx and the memory.provider === 'hindsight'
conditional in config-settings.tsx — same pattern as
toolset-config-panel.tsx off env_vars.
Scoped to memory providers; storage layout is unchanged so the runtime
Hindsight plugin reads the same config.json / HINDSIGHT_API_KEY / provider
keys as before. Tests cover the registry, endpoint behavior (defaults,
write+secret, select rejection, unknown provider, secret-never-returned),
and the generic panel.
46 lines
1.3 KiB
Python
46 lines
1.3 KiB
Python
"""Tests for the declarative memory-provider registry."""
|
|
|
|
from hermes_cli.memory_providers import (
|
|
KIND_SECRET,
|
|
KIND_SELECT,
|
|
get_memory_provider,
|
|
)
|
|
|
|
|
|
def test_hindsight_is_declared():
|
|
provider = get_memory_provider("hindsight")
|
|
|
|
assert provider is not None
|
|
assert provider.label == "Hindsight"
|
|
assert {field.key for field in provider.fields} == {
|
|
"mode",
|
|
"api_key",
|
|
"api_url",
|
|
"bank_id",
|
|
"recall_budget",
|
|
}
|
|
|
|
|
|
def test_hindsight_mode_gating_is_expressed_as_select_options():
|
|
provider = get_memory_provider("hindsight")
|
|
assert provider is not None
|
|
|
|
mode = next(field for field in provider.fields if field.key == "mode")
|
|
assert mode.kind == KIND_SELECT
|
|
assert mode.allowed_values() == {"cloud", "local_external"}
|
|
# local_embedded is intentionally unsupported on desktop.
|
|
assert "local_embedded" not in mode.allowed_values()
|
|
|
|
|
|
def test_api_key_is_a_secret_bound_to_env():
|
|
provider = get_memory_provider("hindsight")
|
|
assert provider is not None
|
|
|
|
api_key = next(field for field in provider.fields if field.key == "api_key")
|
|
assert api_key.kind == KIND_SECRET
|
|
assert api_key.is_secret is True
|
|
assert api_key.env_key == "HINDSIGHT_API_KEY"
|
|
|
|
|
|
def test_unknown_provider_is_none():
|
|
assert get_memory_provider("builtin") is None
|