mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-08-18 04:54:04 +00:00
fix(python-sdks): migrate agent-framework, cartesia, and pipecat to v4 APIs
Use client.add and search.memories hybrid mode, improve profile memory deduplication for string/pydantic items, and add dedupe unit tests. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
9c3f84b5cb
commit
c449b2fe53
14 changed files with 441 additions and 58 deletions
|
|
@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|||
|
||||
[project]
|
||||
name = "supermemory-agent-framework"
|
||||
version = "1.0.0"
|
||||
version = "1.0.1"
|
||||
description = "Memory tools and middleware for Microsoft Agent Framework with supermemory"
|
||||
readme = "README.md"
|
||||
license = "MIT"
|
||||
|
|
|
|||
|
|
@ -72,19 +72,20 @@ class SupermemoryTools:
|
|||
] = True,
|
||||
limit: Annotated[int, "Maximum number of results to return"] = 10,
|
||||
) -> str:
|
||||
"""Search (recall) memories/details/information about the user or other facts or entities. Run when explicitly asked or when context about user's past choices would be helpful."""
|
||||
"""Search stored memories for facts, preferences, history, and context. Use proactively before answering whenever memory could help — not only when explicitly asked."""
|
||||
try:
|
||||
response = await self._client.search.execute(
|
||||
response = await self._client.search.memories(
|
||||
q=information_to_get,
|
||||
container_tags=[self._connection.container_tag],
|
||||
limit=limit,
|
||||
chunk_threshold=0.6,
|
||||
include_full_docs=include_full_docs,
|
||||
threshold=0.6,
|
||||
search_mode="hybrid",
|
||||
)
|
||||
results = response.results or []
|
||||
result: MemorySearchResult = {
|
||||
"success": True,
|
||||
"results": response.results,
|
||||
"count": len(response.results) if response.results else 0,
|
||||
"results": results,
|
||||
"count": len(results),
|
||||
}
|
||||
return json.dumps(result, default=str)
|
||||
except Exception as error:
|
||||
|
|
@ -152,9 +153,9 @@ class SupermemoryTools:
|
|||
tool(
|
||||
name="search_memories",
|
||||
description=(
|
||||
"Search (recall) memories/details/information about the user or other "
|
||||
"facts or entities. Run when explicitly asked or when context about "
|
||||
"user's past choices would be helpful."
|
||||
"Search (recall) stored memories for facts, preferences, history, and context "
|
||||
"about the user or any topic. Use proactively before answering whenever memory "
|
||||
"could help — do not wait for the user to explicitly ask you to search or recall."
|
||||
),
|
||||
)(self.search_memories),
|
||||
tool(
|
||||
|
|
|
|||
|
|
@ -92,14 +92,19 @@ def deduplicate_memories(
|
|||
def extract_memory_text(item: Any) -> Optional[str]:
|
||||
if item is None:
|
||||
return None
|
||||
if isinstance(item, str):
|
||||
trimmed = item.strip()
|
||||
return trimmed if trimmed else None
|
||||
if isinstance(item, dict):
|
||||
memory = item.get("memory")
|
||||
if isinstance(memory, str):
|
||||
trimmed = memory.strip()
|
||||
return trimmed if trimmed else None
|
||||
return None
|
||||
if isinstance(item, str):
|
||||
trimmed = item.strip()
|
||||
# Stainless SDK returns pydantic models (attribute access, snake_case).
|
||||
memory = getattr(item, "memory", None)
|
||||
if isinstance(memory, str):
|
||||
trimmed = memory.strip()
|
||||
return trimmed if trimmed else None
|
||||
return None
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,20 @@ class TestDeduplicateMemories:
|
|||
)
|
||||
assert result.static == ["valid"]
|
||||
|
||||
def test_pydantic_like_search_results(self) -> None:
|
||||
"""SDK search results are pydantic models, not dicts (#1266)."""
|
||||
from types import SimpleNamespace
|
||||
|
||||
result = deduplicate_memories(
|
||||
static=["User likes Python"],
|
||||
search_results=[
|
||||
SimpleNamespace(memory="User prefers async", updated_at="2026-01-01T00:00:00Z"),
|
||||
SimpleNamespace(memory="User likes Python", updated_at=None),
|
||||
],
|
||||
)
|
||||
assert result.static == ["User likes Python"]
|
||||
assert result.search_results == ["User prefers async"]
|
||||
|
||||
|
||||
class TestConvertProfileToMarkdown:
|
||||
def test_empty_profile(self) -> None:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue