|
34 | 34 | HealthCheckResponse,
|
35 | 35 | MemoryRecord,
|
36 | 36 | MemoryRecordResults,
|
| 37 | + MemoryTypeEnum, |
37 | 38 | ModelNameLiteral,
|
38 | 39 | SessionListResponse,
|
39 | 40 | WorkingMemory,
|
@@ -442,7 +443,7 @@ async def add_memories_to_working_memory(
|
442 | 443 | # Auto-generate IDs for memories that don't have them
|
443 | 444 | for memory in final_memories:
|
444 | 445 | if not memory.id:
|
445 |
| - memory.id = str(ulid.new()) |
| 446 | + memory.id = str(ulid.ULID()) |
446 | 447 |
|
447 | 448 | # Create new working memory with the memories
|
448 | 449 | working_memory = WorkingMemory(
|
@@ -617,136 +618,10 @@ async def search_long_term_memory(
|
617 | 618 | exclude_none=True, mode="json"
|
618 | 619 | )
|
619 | 620 | if user_id:
|
620 |
| - payload["user_id"] = user_id.model_dump(exclude_none=True) |
621 |
| - if memory_type: |
622 |
| - payload["memory_type"] = memory_type.model_dump(exclude_none=True) |
623 |
| - if distance_threshold is not None: |
624 |
| - payload["distance_threshold"] = distance_threshold |
625 |
| - |
626 |
| - try: |
627 |
| - response = await self._client.post( |
628 |
| - "/v1/long-term-memory/search", |
629 |
| - json=payload, |
630 |
| - ) |
631 |
| - response.raise_for_status() |
632 |
| - return MemoryRecordResults(**response.json()) |
633 |
| - except httpx.HTTPStatusError as e: |
634 |
| - self._handle_http_error(e.response) |
635 |
| - raise |
636 |
| - |
637 |
| - async def search_memories( |
638 |
| - self, |
639 |
| - text: str, |
640 |
| - session_id: SessionId | dict[str, Any] | None = None, |
641 |
| - namespace: Namespace | dict[str, Any] | None = None, |
642 |
| - topics: Topics | dict[str, Any] | None = None, |
643 |
| - entities: Entities | dict[str, Any] | None = None, |
644 |
| - created_at: CreatedAt | dict[str, Any] | None = None, |
645 |
| - last_accessed: LastAccessed | dict[str, Any] | None = None, |
646 |
| - user_id: UserId | dict[str, Any] | None = None, |
647 |
| - distance_threshold: float | None = None, |
648 |
| - memory_type: MemoryType | dict[str, Any] | None = None, |
649 |
| - limit: int = 10, |
650 |
| - offset: int = 0, |
651 |
| - ) -> MemoryRecordResults: |
652 |
| - """ |
653 |
| - Search across all memory types (working memory and long-term memory). |
654 |
| -
|
655 |
| - This method searches both working memory (ephemeral, session-scoped) and |
656 |
| - long-term memory (persistent, indexed) to provide comprehensive results. |
657 |
| -
|
658 |
| - For working memory: |
659 |
| - - Uses simple text matching |
660 |
| - - Searches across all sessions (unless session_id filter is provided) |
661 |
| - - Returns memories that haven't been promoted to long-term storage |
662 |
| -
|
663 |
| - For long-term memory: |
664 |
| - - Uses semantic vector search |
665 |
| - - Includes promoted memories from working memory |
666 |
| - - Supports advanced filtering by topics, entities, etc. |
667 |
| -
|
668 |
| - Args: |
669 |
| - text: Search query text for semantic similarity |
670 |
| - session_id: Optional session ID filter |
671 |
| - namespace: Optional namespace filter |
672 |
| - topics: Optional topics filter |
673 |
| - entities: Optional entities filter |
674 |
| - created_at: Optional creation date filter |
675 |
| - last_accessed: Optional last accessed date filter |
676 |
| - user_id: Optional user ID filter |
677 |
| - distance_threshold: Optional distance threshold for search results |
678 |
| - memory_type: Optional memory type filter |
679 |
| - limit: Maximum number of results to return (default: 10) |
680 |
| - offset: Offset for pagination (default: 0) |
681 |
| -
|
682 |
| - Returns: |
683 |
| - MemoryRecordResults with matching memories from both memory types |
684 |
| -
|
685 |
| - Raises: |
686 |
| - MemoryServerError: If the request fails |
687 |
| -
|
688 |
| - Example: |
689 |
| - ```python |
690 |
| - # Search for user preferences with topic filtering |
691 |
| - from .filters import Topics |
692 |
| -
|
693 |
| - results = await client.search_memories( |
694 |
| - text="user prefers dark mode", |
695 |
| - topics=Topics(any=["preferences", "ui"]), |
696 |
| - limit=5 |
697 |
| - ) |
698 |
| -
|
699 |
| - for memory in results.memories: |
700 |
| - print(f"Found: {memory.text}") |
701 |
| - ``` |
702 |
| - """ |
703 |
| - # Convert dictionary filters to their proper filter objects if needed |
704 |
| - if isinstance(session_id, dict): |
705 |
| - session_id = SessionId(**session_id) |
706 |
| - if isinstance(namespace, dict): |
707 |
| - namespace = Namespace(**namespace) |
708 |
| - if isinstance(topics, dict): |
709 |
| - topics = Topics(**topics) |
710 |
| - if isinstance(entities, dict): |
711 |
| - entities = Entities(**entities) |
712 |
| - if isinstance(created_at, dict): |
713 |
| - created_at = CreatedAt(**created_at) |
714 |
| - if isinstance(last_accessed, dict): |
715 |
| - last_accessed = LastAccessed(**last_accessed) |
716 |
| - if isinstance(user_id, dict): |
717 |
| - user_id = UserId(**user_id) |
718 |
| - if isinstance(memory_type, dict): |
719 |
| - memory_type = MemoryType(**memory_type) |
720 |
| - |
721 |
| - # Apply default namespace if needed and no namespace filter specified |
722 |
| - if namespace is None and self.config.default_namespace is not None: |
723 |
| - namespace = Namespace(eq=self.config.default_namespace) |
724 |
| - |
725 |
| - payload = { |
726 |
| - "text": text, |
727 |
| - "limit": limit, |
728 |
| - "offset": offset, |
729 |
| - } |
730 |
| - |
731 |
| - # Add filters if provided |
732 |
| - if session_id: |
733 |
| - payload["session_id"] = session_id.model_dump(exclude_none=True) |
734 |
| - if namespace: |
735 |
| - payload["namespace"] = namespace.model_dump(exclude_none=True) |
736 |
| - if topics: |
737 |
| - payload["topics"] = topics.model_dump(exclude_none=True) |
738 |
| - if entities: |
739 |
| - payload["entities"] = entities.model_dump(exclude_none=True) |
740 |
| - if created_at: |
741 |
| - payload["created_at"] = created_at.model_dump( |
742 |
| - exclude_none=True, mode="json" |
743 |
| - ) |
744 |
| - if last_accessed: |
745 |
| - payload["last_accessed"] = last_accessed.model_dump( |
746 |
| - exclude_none=True, mode="json" |
747 |
| - ) |
748 |
| - if user_id: |
749 |
| - payload["user_id"] = user_id.model_dump(exclude_none=True) |
| 621 | + if isinstance(user_id, dict): |
| 622 | + payload["user_id"] = user_id |
| 623 | + else: |
| 624 | + payload["user_id"] = user_id.model_dump(exclude_none=True) |
750 | 625 | if memory_type:
|
751 | 626 | payload["memory_type"] = memory_type.model_dump(exclude_none=True)
|
752 | 627 | if distance_threshold is not None:
|
@@ -1076,7 +951,7 @@ async def add_memory_tool(
|
1076 | 951 | # Create memory record
|
1077 | 952 | memory = ClientMemoryRecord(
|
1078 | 953 | text=text,
|
1079 |
| - memory_type=memory_type, |
| 954 | + memory_type=MemoryTypeEnum(memory_type), |
1080 | 955 | topics=topics,
|
1081 | 956 | entities=entities,
|
1082 | 957 | namespace=namespace or self.config.default_namespace,
|
@@ -1111,7 +986,7 @@ async def update_memory_data_tool(
|
1111 | 986 | self,
|
1112 | 987 | session_id: str,
|
1113 | 988 | data: dict[str, Any],
|
1114 |
| - merge_strategy: str = "merge", |
| 989 | + merge_strategy: Literal["replace", "merge", "deep_merge"] = "merge", |
1115 | 990 | namespace: str | None = None,
|
1116 | 991 | user_id: str | None = None,
|
1117 | 992 | ) -> dict[str, Any]:
|
@@ -1997,70 +1872,6 @@ async def search_all_long_term_memories(
|
1997 | 1872 |
|
1998 | 1873 | offset += batch_size
|
1999 | 1874 |
|
2000 |
| - async def search_all_memories( |
2001 |
| - self, |
2002 |
| - text: str, |
2003 |
| - session_id: SessionId | dict[str, Any] | None = None, |
2004 |
| - namespace: Namespace | dict[str, Any] | None = None, |
2005 |
| - topics: Topics | dict[str, Any] | None = None, |
2006 |
| - entities: Entities | dict[str, Any] | None = None, |
2007 |
| - created_at: CreatedAt | dict[str, Any] | None = None, |
2008 |
| - last_accessed: LastAccessed | dict[str, Any] | None = None, |
2009 |
| - user_id: UserId | dict[str, Any] | None = None, |
2010 |
| - distance_threshold: float | None = None, |
2011 |
| - memory_type: MemoryType | dict[str, Any] | None = None, |
2012 |
| - batch_size: int = 50, |
2013 |
| - ) -> AsyncIterator[MemoryRecord]: |
2014 |
| - """ |
2015 |
| - Auto-paginating version of unified memory search. |
2016 |
| -
|
2017 |
| - Searches both working memory and long-term memory with automatic pagination. |
2018 |
| -
|
2019 |
| - Args: |
2020 |
| - text: Search query text |
2021 |
| - session_id: Optional session ID filter |
2022 |
| - namespace: Optional namespace filter |
2023 |
| - topics: Optional topics filter |
2024 |
| - entities: Optional entities filter |
2025 |
| - created_at: Optional creation date filter |
2026 |
| - last_accessed: Optional last accessed date filter |
2027 |
| - user_id: Optional user ID filter |
2028 |
| - distance_threshold: Optional distance threshold |
2029 |
| - memory_type: Optional memory type filter |
2030 |
| - batch_size: Number of results to fetch per API call |
2031 |
| -
|
2032 |
| - Yields: |
2033 |
| - Individual memory records from all result pages |
2034 |
| - """ |
2035 |
| - offset = 0 |
2036 |
| - while True: |
2037 |
| - results = await self.search_memories( |
2038 |
| - text=text, |
2039 |
| - session_id=session_id, |
2040 |
| - namespace=namespace, |
2041 |
| - topics=topics, |
2042 |
| - entities=entities, |
2043 |
| - created_at=created_at, |
2044 |
| - last_accessed=last_accessed, |
2045 |
| - user_id=user_id, |
2046 |
| - distance_threshold=distance_threshold, |
2047 |
| - memory_type=memory_type, |
2048 |
| - limit=batch_size, |
2049 |
| - offset=offset, |
2050 |
| - ) |
2051 |
| - |
2052 |
| - if not results.memories: |
2053 |
| - break |
2054 |
| - |
2055 |
| - for memory in results.memories: |
2056 |
| - yield memory |
2057 |
| - |
2058 |
| - # If we got fewer results than batch_size, we've reached the end |
2059 |
| - if len(results.memories) < batch_size: |
2060 |
| - break |
2061 |
| - |
2062 |
| - offset += batch_size |
2063 |
| - |
2064 | 1875 | def validate_memory_record(self, memory: ClientMemoryRecord | MemoryRecord) -> None:
|
2065 | 1876 | """
|
2066 | 1877 | Validate memory record before sending to server.
|
@@ -2237,7 +2048,7 @@ async def append_messages_to_working_memory(
|
2237 | 2048 | converted_existing_messages.append(msg)
|
2238 | 2049 | else:
|
2239 | 2050 | # Fallback for any other message type - convert to string content
|
2240 |
| - converted_existing_messages.append( |
| 2051 | + converted_existing_messages.append( # type: ignore |
2241 | 2052 | {"role": "user", "content": str(msg)}
|
2242 | 2053 | )
|
2243 | 2054 |
|
|
0 commit comments