From 94523764fca8b94c4c4f32abc514c0fd5cce1764 Mon Sep 17 00:00:00 2001 From: Hao Zhe Date: Tue, 26 May 2026 12:37:28 +0800 Subject: [PATCH] fix(memory): choose OpenViking key type before prompting --- plugins/memory/openviking/__init__.py | 68 ++++++++++++------- .../memory/test_openviking_provider.py | 31 ++++++--- 2 files changed, 66 insertions(+), 33 deletions(-) diff --git a/plugins/memory/openviking/__init__.py b/plugins/memory/openviking/__init__.py index c5bda3e5d0d..29b3e5ad7c4 100644 --- a/plugins/memory/openviking/__init__.py +++ b/plugins/memory/openviking/__init__.py @@ -595,26 +595,35 @@ def _prompt_manual_connection_values(prompt, select, cancelled): prompt("OpenViking server URL", default=_DEFAULT_ENDPOINT) ) or _DEFAULT_ENDPOINT is_local = _is_local_openviking_url(endpoint) - api_key_label = ( - "OpenViking API key (optional for local)" - if is_local - else "OpenViking API key" - ) - api_key = _clean_config_value(prompt(api_key_label, secret=True)) - if not api_key and not is_local: - print("\n Remote OpenViking servers require an API key.") - print(" No changes saved.\n") - return None values = { "endpoint": endpoint, - "api_key": api_key, + "api_key": "", "account": "", "user": "", "agent": "", } - if api_key: - key_type = select( + if is_local: + credential_choice = select( + " OpenViking credential", + [ + ("No API key", "local dev mode"), + ("User API key", "server derives account/user automatically"), + ("Root API key", "requires account and user IDs"), + ], + default=0, + cancel_returns=cancelled, + ) + if credential_choice == cancelled: + return _SETUP_CANCELLED + if credential_choice == 0: + values["agent"] = _clean_config_value( + prompt("OpenViking agent", default=_DEFAULT_AGENT) + ) or _DEFAULT_AGENT + return values + api_key_type = "root" if credential_choice == 2 else "user" + else: + credential_choice = select( " OpenViking API key type", [ ("User API key", "server derives account/user automatically"), @@ -623,18 +632,29 @@ def _prompt_manual_connection_values(prompt, select, cancelled): default=0, cancel_returns=cancelled, ) - if key_type == cancelled: + if credential_choice == cancelled: return _SETUP_CANCELLED - if key_type == 1: - values["api_key_type"] = "root" - values["account"] = _clean_config_value(prompt("OpenViking account")) - values["user"] = _clean_config_value(prompt("OpenViking user")) - if not values["account"] or not values["user"]: - print("\n Root API keys require both OpenViking account and user.") - print(" No changes saved.\n") - return None - else: - values["api_key_type"] = "user" + api_key_type = "root" if credential_choice == 1 else "user" + + values["api_key_type"] = api_key_type + api_key_label = ( + "OpenViking root API key" + if api_key_type == "root" + else "OpenViking user API key" + ) + values["api_key"] = _clean_config_value(prompt(api_key_label, secret=True)) + if not values["api_key"]: + print(f"\n {api_key_label} is required.") + print(" No changes saved.\n") + return None + + if api_key_type == "root": + values["account"] = _clean_config_value(prompt("OpenViking account")) + values["user"] = _clean_config_value(prompt("OpenViking user")) + if not values["account"] or not values["user"]: + print("\n Root API keys require both OpenViking account and user.") + print(" No changes saved.\n") + return None values["agent"] = _clean_config_value( prompt("OpenViking agent", default=_DEFAULT_AGENT) diff --git a/tests/plugins/memory/test_openviking_provider.py b/tests/plugins/memory/test_openviking_provider.py index b4e42093e00..2ca648d3228 100644 --- a/tests/plugins/memory/test_openviking_provider.py +++ b/tests/plugins/memory/test_openviking_provider.py @@ -223,7 +223,7 @@ def test_post_setup_manual_remote_root_writes_ovcli_and_links(tmp_path, monkeypa "_prompt", _prompt_from_values({ "OpenViking server URL": "https://openviking.example", - "OpenViking API key": "root-secret", + "OpenViking root API key": "root-secret", "OpenViking account": "acct", "OpenViking user": "alice", "OpenViking agent": "agent", @@ -272,10 +272,14 @@ def test_post_setup_manual_remote_user_keeps_only_hermes_env(tmp_path, monkeypat _prompt_from_values( { "OpenViking server URL": "https://openviking.example", - "OpenViking API key": "user-secret", + "OpenViking user API key": "user-secret", "OpenViking agent": "agent", }, - forbidden={"OpenViking account", "OpenViking user"}, + forbidden={ + "OpenViking account", + "OpenViking root API key", + "OpenViking user", + }, ), ) config = {"memory": {}} @@ -308,13 +312,18 @@ def test_post_setup_manual_remote_requires_api_key(tmp_path, monkeypatch): save_config = MagicMock() monkeypatch.setattr(hermes_config, "save_config", save_config) - monkeypatch.setattr(memory_setup, "_curses_select", lambda *args, **kwargs: 2) + choices = iter([2, 0]) + monkeypatch.setattr( + memory_setup, + "_curses_select", + lambda *args, **kwargs: next(choices), + ) monkeypatch.setattr( memory_setup, "_prompt", _prompt_from_values({ "OpenViking server URL": "https://openviking.example", - "OpenViking API key": "", + "OpenViking user API key": "", }), ) config = {"memory": {"provider": "builtin"}} @@ -353,7 +362,7 @@ def test_post_setup_manual_root_requires_account_and_user(tmp_path, monkeypatch) "_prompt", _prompt_from_values({ "OpenViking server URL": "https://openviking.example", - "OpenViking API key": "root-secret", + "OpenViking root API key": "root-secret", "OpenViking account": "", "OpenViking user": "alice", }), @@ -380,7 +389,7 @@ def test_post_setup_manual_local_allows_blank_api_key(tmp_path, monkeypatch): from hermes_cli import memory_setup - choices = iter([2, 1]) + choices = iter([2, 0, 1]) monkeypatch.setattr( memory_setup, "_curses_select", @@ -392,10 +401,14 @@ def test_post_setup_manual_local_allows_blank_api_key(tmp_path, monkeypatch): _prompt_from_values( { "OpenViking server URL": "http://localhost:1933", - "OpenViking API key": "", "OpenViking agent": "agent", }, - forbidden={"OpenViking account", "OpenViking user"}, + forbidden={ + "OpenViking account", + "OpenViking root API key", + "OpenViking user", + "OpenViking user API key", + }, ), ) config = {"memory": {}}