diff --git a/plugins/memory/openviking/__init__.py b/plugins/memory/openviking/__init__.py index c9cbfcad4b5..62078000866 100644 --- a/plugins/memory/openviking/__init__.py +++ b/plugins/memory/openviking/__init__.py @@ -100,18 +100,19 @@ class _VikingClient: raise ImportError("httpx is required for OpenViking: pip install httpx") def _headers(self) -> dict: - # Only send tenant headers when the user actually configured them. - # Legacy installs had account/user defaulted to the literal string - # "default" — treat that as unset so authenticated remote servers - # that derive tenancy from the Bearer key aren't overridden by a - # bogus tenant value. + # Always send tenant headers when account/user are configured. + # OpenViking 0.3.x requires X-OpenViking-Account and X-OpenViking-User + # for ROOT API key requests to tenant-scoped APIs — omitting them + # causes INVALID_ARGUMENT errors even when account="default". + # User-level keys can omit them (server derives tenancy from the key), + # but ROOT keys must always include them explicitly. h = { "Content-Type": "application/json", "X-OpenViking-Agent": self._agent, } - if self._account and self._account != "default": + if self._account: h["X-OpenViking-Account"] = self._account - if self._user and self._user != "default": + if self._user: h["X-OpenViking-User"] = self._user if self._api_key: h["X-API-Key"] = self._api_key diff --git a/tests/plugins/memory/test_openviking_provider.py b/tests/plugins/memory/test_openviking_provider.py index 76d69224e35..127528205b2 100644 --- a/tests/plugins/memory/test_openviking_provider.py +++ b/tests/plugins/memory/test_openviking_provider.py @@ -314,10 +314,11 @@ def test_viking_client_headers_include_bearer_when_api_key_set(): assert headers["Authorization"] == "Bearer test-key" -def test_viking_client_headers_omit_tenant_when_legacy_default(): - # Existing installs have account/user set to the literal string "default". - # Those should NOT be sent as headers — the server would interpret that - # as a real tenant override and reject/misroute requests. +def test_viking_client_headers_send_tenant_when_default(): + # account/user set to the literal string "default". OpenViking 0.3.x + # requires X-OpenViking-Account and X-OpenViking-User for ROOT API key + # requests to tenant-scoped APIs — omitting them causes + # INVALID_ARGUMENT errors even when account="default". client = _VikingClient( "https://example.com", api_key="test-key", @@ -326,13 +327,15 @@ def test_viking_client_headers_omit_tenant_when_legacy_default(): agent="hermes", ) headers = client._headers() - assert "X-OpenViking-Account" not in headers - assert "X-OpenViking-User" not in headers + assert headers["X-OpenViking-Account"] == "default" + assert headers["X-OpenViking-User"] == "default" assert headers["X-OpenViking-Agent"] == "hermes" assert headers["Authorization"] == "Bearer test-key" -def test_viking_client_headers_omit_tenant_when_empty(): +def test_viking_client_headers_send_tenant_when_empty_falls_back_to_default(): + # Empty account/user strings fall back to "default" via the constructor. + # Headers are sent even for the default value — ROOT API keys need them. client = _VikingClient( "https://example.com", api_key="", @@ -341,8 +344,8 @@ def test_viking_client_headers_omit_tenant_when_empty(): agent="hermes", ) headers = client._headers() - assert "X-OpenViking-Account" not in headers - assert "X-OpenViking-User" not in headers + assert headers["X-OpenViking-Account"] == "default" + assert headers["X-OpenViking-User"] == "default" assert "Authorization" not in headers assert "X-API-Key" not in headers