Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions packages/cartesia-sdk-python/src/supermemory_cartesia/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,20 +166,26 @@ async def _retrieve_memories(self, query: str) -> Dict[str, Any]:
timeout=10.0
)

static_count = len(response.profile.static) if response.profile.static else 0
dynamic_count = len(response.profile.dynamic) if response.profile.dynamic else 0
search_count = len(response.search_results.results) if response.search_results and response.search_results.results else 0

logger.info(f"[Supermemory] Retrieved memories - static: {static_count}, dynamic: {dynamic_count}, search: {search_count}")
# A user with no stored memories yet gets a null profile back, which
# is a normal case, not an error. Guard against it so we return an
# empty profile instead of raising AttributeError on response.profile.
profile = getattr(response, "profile", None)
profile_static = profile.static if profile is not None and profile.static else []
profile_dynamic = profile.dynamic if profile is not None and profile.dynamic else []

search_results = []
if response.search_results and response.search_results.results:
search_results = response.search_results.results

logger.info(
f"[Supermemory] Retrieved memories - static: {len(profile_static)}, "
f"dynamic: {len(profile_dynamic)}, search: {len(search_results)}"
)

return {
"profile": {
"static": response.profile.static or [],
"dynamic": response.profile.dynamic or [],
"static": profile_static,
"dynamic": profile_dynamic,
},
"search_results": search_results,
}
Expand Down
Empty file.
77 changes: 77 additions & 0 deletions packages/cartesia-sdk-python/tests/test_empty_profile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
from __future__ import annotations

import sys
import types
import unittest
from types import SimpleNamespace
from unittest.mock import AsyncMock


def _install_test_stubs() -> None:
if "loguru" not in sys.modules:
loguru_module = types.ModuleType("loguru")

class _Logger:
def info(self, *_args, **_kwargs):
return None

def warning(self, *_args, **_kwargs):
return None

def error(self, *_args, **_kwargs):
return None

loguru_module.logger = _Logger()
sys.modules["loguru"] = loguru_module

if "pydantic" not in sys.modules:
pydantic_module = types.ModuleType("pydantic")

class BaseModel:
def __init__(self, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)

def Field(*, default=None, **_kwargs):
return default

pydantic_module.BaseModel = BaseModel
pydantic_module.Field = Field
sys.modules["pydantic"] = pydantic_module


_install_test_stubs()

from supermemory_cartesia.agent import SupermemoryCartesiaAgent


class _MockSupermemoryClient:
def __init__(self, response):
self.profile = AsyncMock(return_value=response)


class TestSupermemoryCartesiaNullProfile(unittest.IsolatedAsyncioTestCase):
async def test_retrieve_memories_handles_null_profile(self) -> None:
agent = SupermemoryCartesiaAgent(
agent=SimpleNamespace(),
api_key="mock_key",
container_tag="user-123",
custom_id="conversation-456",
)

response = SimpleNamespace(profile=None, search_results=None)
agent._supermemory_client = _MockSupermemoryClient(response)

result = await agent._retrieve_memories("Hello world")

self.assertEqual(
result,
{
"profile": {"static": [], "dynamic": []},
"search_results": [],
},
)


if __name__ == "__main__":
unittest.main()