Repository navigation
feat(client): support raw filter strings - #1342
haosenwang1018 wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds support for passing a raw filter string into the Python client Memory.search() and Memory.list() methods to match the TypeScript client / API filtering capabilities (Fixes #1310).
Changes:
- Added a
filter: str | Noneparameter and combined it with built-in andfilter_dictfilters viadict_filters AND (raw_filter). - Added unit tests covering
search(..., filter=...)andlist(..., filter=...)with built-in metadata filters preserved. - Updated tests/documentation comments to use
metadata.-prefixed keys infilter_dictwhere appropriate.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| packages/client/src/memmachine_client/memory.py | Adds filter parameter and AND-combines raw filter strings with dict-based filters for search() and list(). |
| packages/client/client_tests/test_memory.py | Adds unit tests for raw filter strings; updates filter_dict expectations for metadata-prefixed keys. |
| packages/client/client_tests/test_integration_complete.py | Updates integration test to use metadata. prefix for user metadata filter_dict keys. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| def list( | ||
| self, | ||
| memory_type: MemoryType = MemoryType.Episodic, | ||
| page_size: int = 100, | ||
| page_num: int = 0, | ||
| filter_dict: dict[str, str] | None = None, | ||
| filter: str | None = None, | ||
| set_metadata: dict[str, JsonValue] | None = None, | ||
| timeout: int | None = None, | ||
| ) -> ListResult: |
There was a problem hiding this comment.
Adding filter in the middle of the positional parameters for list() is a backward-incompatible API change: any existing callers passing set_metadata positionally will now have that argument interpreted as filter. To preserve backward compatibility, make filter keyword-only (e.g., introduce * before it), or append filter at the end of the parameter list after timeout.
| def test_search_with_filter_string(self, mock_client): | ||
| """Test search with raw filter string.""" | ||
| mock_response = Mock() | ||
| mock_response.status_code = 200 | ||
| mock_response.json.return_value = {"status": 0, "content": {}} | ||
| mock_response.raise_for_status = Mock() | ||
| mock_client.request.return_value = mock_response | ||
|
|
||
| memory = Memory( | ||
| client=mock_client, | ||
| org_id="test_org", | ||
| project_id="test_project", | ||
| metadata={"agent_id": "agent1", "user_id": "user1"}, | ||
| ) | ||
|
|
||
| memory.search("query", filter='metadata.category = "work"') | ||
|
|
||
| call_args = mock_client.request.call_args | ||
| json_data = call_args[1]["json"] | ||
| filter_str = json_data["filter"] | ||
| assert "metadata.user_id='user1'" in filter_str | ||
| assert "metadata.agent_id='agent1'" in filter_str | ||
| assert '(metadata.category = "work")' in filter_str | ||
|
|
||
| def test_list_with_filter_string(self, mock_client): |
There was a problem hiding this comment.
The PR description specifies that when both dict-based filters and a raw filter string are present, the client should combine them as dict_filters AND (raw_filter). Current tests verify that both components appear, but they don’t explicitly assert the AND-combination behavior (including parentheses) for the case where both filter_dict and filter are provided together. Consider adding a unit test for search(..., filter_dict=..., filter=...) and list(..., filter_dict=..., filter=...) that asserts the combined expression contains AND ( and the raw filter is parenthesized.
|
@haosenwang1018 thank you for the pull request submission. Please sign your commits, resolve the unit test failures, and review the CoPilot feedback. You only need to resolve the relevant items. Thanks. |
…ion (#1403) * feat(client+langgraph): raw filter strings and EpisodeType normalization Add three small features to the Python client and its LangGraph wrapper so callers can pass structured filter expressions and either-enum-or-string episode types directly. 1. `Memory.search(filter=...)` and `Memory.list(filter=...)` Accept an optional raw filter string alongside `filter_dict`. When both are provided, the two are combined with `AND`. The raw filter is passed through to the v2 `SearchMemoriesSpec.filter` / `ListMemoriesSpec.filter` fields unchanged. 2. `MemMachineTools.search_memory(filter=...)` Pipes the same raw filter through the LangGraph search-memory tool. 3. `MemMachineTools.add_memory(episode_type=...)` Accept either an `EpisodeType` enum or its string value (e.g. `"message"`), normalizing strings via `EpisodeType(...)` before delegating to `Memory.add`. The factory tool's return-type annotation was widened to match. The `filter` parameter shadows the Python builtin, which is the same trade-off `memmachine_common.api.SearchMemoriesSpec` already made for its `filter:` field — keeping the parameter name aligned with the API field. `# noqa: A002` is applied at the three call sites with a comment pointing at the API spec. This commit consolidates the substantive work from haosenwang1018's 9-commit stack (#1341 → #1349) into a single rebased+linted commit against current `main`. The original stack's prefix-style doc and test changes have been omitted because they have already landed on `main` via #1352 and #1311. The original commits authored by haosenwang1018: - 921b55f feat(client): support raw filter strings - e0849bb feat(langgraph): support raw filter strings - 53b489e fix(langgraph): normalize episode type strings Closes #1341, #1342, #1343, #1344, #1345, #1346, #1347, #1348, #1349 Co-authored-by: Steve Scargall <[email protected]> Signed-off-by: Steve Scargall <[email protected]> * docs(langgraph): document filter and episode type support --------- Signed-off-by: Steve Scargall <[email protected]> Co-authored-by: haosenwang1018 <[email protected]> Co-authored-by: Shu Wang <[email protected]>
|
Closed by #1403 |
Purpose of the change
Add raw filter string support to the Python client so it matches the TypeScript client and underlying API capabilities.
Description
Fixes #1310
This change updates the Python client
Memory.search()andMemory.list()methods to accept an optional rawfilterstring in addition tofilter_dict.Behavior:
filter_dictbehavior remains unchangedfilter="metadata.category = \"work\""filter_dictfilters and a rawfilterstring are both present, they are combined as:dict_filters AND (raw_filter)This preserves backward compatibility while allowing parity with the TypeScript client and direct filter-string usage.
Also added test coverage in
packages/client/client_tests/test_memory.pyfor:search(..., filter=...)list(..., filter=...)Type of change
How Has This Been Tested?
Test command:
cd packages/client && PYTHONPATH=/home/node/.openclaw/workspace/MemMachine/packages/client/src:/home/node/.openclaw/workspace/MemMachine/packages/common/src python -m pytest client_tests/test_memory.py -qChecklist
Maintainer Checklist