From 183e9fba9375fb1d7681f4aaddd0c06a084f5edc Mon Sep 17 00:00:00 2001 From: ved015 <122012786+ved015@users.noreply.github.com> Date: Fri, 21 Aug 2026 21:24:38 +0530 Subject: [PATCH] fix(openai-sdk-python): harden v4 migration --- packages/openai-sdk-python/README.md | 7 ++-- packages/openai-sdk-python/pyproject.toml | 5 ++- .../src/supermemory_openai/middleware.py | 16 ++++----- .../src/supermemory_openai/tools.py | 33 ++++++++++--------- .../openai-sdk-python/tests/test_tools.py | 19 ++++++++--- packages/openai-sdk-python/uv.lock | 8 ++--- 6 files changed, 52 insertions(+), 36 deletions(-) diff --git a/packages/openai-sdk-python/README.md b/packages/openai-sdk-python/README.md index f9d96510..b030a9fa 100644 --- a/packages/openai-sdk-python/README.md +++ b/packages/openai-sdk-python/README.md @@ -245,8 +245,7 @@ tools = SupermemoryTools( # Search memories result = await tools.search_memories( information_to_get="user preferences", - limit=10, - include_full_docs=True + limit=10 ) # Add memory @@ -260,6 +259,10 @@ result = await tools.fetch_memory( ) ``` +`include_full_docs` is retained as a deprecated Python argument for compatibility, +but v4 search returns relevant memories and chunks instead of full source documents. +It is no longer exposed in the OpenAI tool schema. + ### Individual Tools ```python diff --git a/packages/openai-sdk-python/pyproject.toml b/packages/openai-sdk-python/pyproject.toml index 9e991881..210b2ae8 100644 --- a/packages/openai-sdk-python/pyproject.toml +++ b/packages/openai-sdk-python/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "supermemory-openai-sdk" -version = "1.0.5" +version = "1.0.6" description = "Memory tools for OpenAI function calling with supermemory" readme = "README.md" license = "MIT" @@ -15,7 +15,6 @@ classifiers = [ "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", @@ -62,7 +61,7 @@ multi_line_output = 3 line_length = 88 [tool.mypy] -python_version = "3.8" +python_version = "3.9" warn_return_any = true warn_unused_configs = true disallow_untyped_defs = true diff --git a/packages/openai-sdk-python/src/supermemory_openai/middleware.py b/packages/openai-sdk-python/src/supermemory_openai/middleware.py index 1a079fa2..9cbad1b0 100644 --- a/packages/openai-sdk-python/src/supermemory_openai/middleware.py +++ b/packages/openai-sdk-python/src/supermemory_openai/middleware.py @@ -222,15 +222,15 @@ async def add_memory_tool( ) -> None: """Add a new memory to the SuperMemory system.""" try: - add_params = { - "content": content, - "container_tag": container_tag, - } - if custom_id is not None: - add_params["custom_id"] = custom_id - # Handle both sync and async supermemory clients - result = client.add(**add_params) + if custom_id is None: + result = client.add(content=content, container_tag=container_tag) + else: + result = client.add( + content=content, + container_tag=container_tag, + custom_id=custom_id, + ) if inspect.isawaitable(result): response = await result else: diff --git a/packages/openai-sdk-python/src/supermemory_openai/tools.py b/packages/openai-sdk-python/src/supermemory_openai/tools.py index 60274615..d294bf58 100644 --- a/packages/openai-sdk-python/src/supermemory_openai/tools.py +++ b/packages/openai-sdk-python/src/supermemory_openai/tools.py @@ -1,7 +1,8 @@ """Supermemory tools for OpenAI function calling.""" import json -from typing import Dict, List, Optional, TypedDict, Union +import warnings +from typing import Dict, List, Optional, TypedDict import supermemory from openai.types.chat import ( @@ -10,7 +11,6 @@ from openai.types.chat import ( ChatCompletionToolMessageParam, ) from supermemory.types import AddResponse, SearchMemoriesResponse -from supermemory.types.search_memories_response import Result from .exceptions import ( SupermemoryConfigurationError, @@ -23,6 +23,8 @@ class SupermemoryToolsConfig(TypedDict, total=False): """Configuration for Supermemory tools. Only one of `project_id` or `container_tags` can be provided. + The first container tag is the primary v4 search scope; all configured tags + are applied when adding a memory. """ base_url: Optional[str] @@ -38,7 +40,7 @@ class MemorySearchResult(TypedDict, total=False): """Result type for memory search operations.""" success: bool - results: Optional[List[Result]] + results: Optional[List[Dict[str, object]]] count: Optional[int] error: Optional[str] @@ -65,14 +67,6 @@ MEMORY_TOOL_SCHEMAS: Dict[str, ChatCompletionFunctionToolParam] = { "type": "string", "description": "Terms to search for in the user's memories", }, - "include_full_docs": { - "type": "boolean", - "description": ( - "Whether to include the full document content in the response. " - "Defaults to true for better AI context." - ), - "default": True, - }, "limit": { "type": "number", "description": "Maximum number of results to return", @@ -169,23 +163,32 @@ class SupermemoryTools: async def search_memories( self, information_to_get: str, - include_full_docs: bool = True, + include_full_docs: Optional[bool] = None, limit: int = 10, ) -> MemorySearchResult: """Search memories. Args: information_to_get: Terms to search for - include_full_docs: Whether to include full document content + include_full_docs: Deprecated compatibility argument. V4 search + returns relevant memories and chunks, not full source documents. limit: Maximum number of results Returns: MemorySearchResult """ + if include_full_docs is not None: + warnings.warn( + "include_full_docs is deprecated and ignored because v4 search " + "does not return full source documents", + DeprecationWarning, + stacklevel=2, + ) + try: response: SearchMemoriesResponse = await self.client.search.memories( q=information_to_get, - container_tags=self.container_tags, + container_tag=self.container_tags[0], limit=limit, threshold=0.6, search_mode="hybrid", @@ -317,7 +320,7 @@ class SearchMemoriesTool: async def execute( self, information_to_get: str, - include_full_docs: bool = True, + include_full_docs: Optional[bool] = None, limit: int = 10, ) -> MemorySearchResult: """Execute search memories.""" diff --git a/packages/openai-sdk-python/tests/test_tools.py b/packages/openai-sdk-python/tests/test_tools.py index 5bc95920..029c4610 100644 --- a/packages/openai-sdk-python/tests/test_tools.py +++ b/packages/openai-sdk-python/tests/test_tools.py @@ -159,6 +159,10 @@ class TestToolDefinitions: assert search_tool is not None assert search_tool["type"] == "function" assert "information_to_get" in search_tool["function"]["parameters"]["required"] + assert ( + "include_full_docs" + not in search_tool["function"]["parameters"]["properties"] + ) # Check addMemory add_tool = next( @@ -206,25 +210,32 @@ class TestMemoryOperationsUnit: @pytest.mark.asyncio async def test_search_memories_uses_search_memories_hybrid(self): - """search_memories must call client.search.memories with hybrid mode.""" + """V4 search must use the primary singular tag and hybrid mode.""" from types import SimpleNamespace from unittest.mock import AsyncMock - tools = SupermemoryTools("test-key", {"container_tags": ["unit-tag"]}) + tools = SupermemoryTools( + "test-key", {"container_tags": ["primary-tag", "secondary-tag"]} + ) tools.client.search.memories = AsyncMock( return_value=SimpleNamespace( results=[SimpleNamespace(model_dump=lambda: {"memory": "likes tea"})] ) ) - result = await tools.search_memories("tea", limit=3) + with pytest.warns(DeprecationWarning, match="include_full_docs"): + result = await tools.search_memories( + "tea", include_full_docs=False, limit=3 + ) assert result["success"] is True assert result["count"] == 1 tools.client.search.memories.assert_awaited_once() kwargs = tools.client.search.memories.await_args.kwargs assert kwargs["q"] == "tea" - assert kwargs["container_tags"] == ["unit-tag"] + assert kwargs["container_tag"] == "primary-tag" + assert "container_tags" not in kwargs + assert "include_full_docs" not in kwargs assert kwargs["limit"] == 3 assert kwargs["search_mode"] == "hybrid" diff --git a/packages/openai-sdk-python/uv.lock b/packages/openai-sdk-python/uv.lock index 6c457622..b4e297e5 100644 --- a/packages/openai-sdk-python/uv.lock +++ b/packages/openai-sdk-python/uv.lock @@ -377,7 +377,7 @@ resolution-markers = [ "python_full_version < '3.10'", ] dependencies = [ - { name = "colorama", marker = "python_full_version < '3.10' and sys_platform == 'win32'" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593, upload-time = "2024-12-21T18:38:44.339Z" } wheels = [ @@ -392,7 +392,7 @@ resolution-markers = [ "python_full_version >= '3.10'", ] dependencies = [ - { name = "colorama", marker = "python_full_version >= '3.10' and sys_platform == 'win32'" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/60/6c/8ca2efa64cf75a977a0d7fac081354553ebe483345c734fb6b6515d96bbc/click-8.2.1.tar.gz", hash = "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202", size = 286342, upload-time = "2025-05-20T23:19:49.832Z" } wheels = [ @@ -422,7 +422,7 @@ name = "exceptiongroup" version = "1.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.13'" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749, upload-time = "2025-05-10T17:42:51.123Z" } wheels = [ @@ -1372,7 +1372,7 @@ wheels = [ [[package]] name = "supermemory-openai-sdk" -version = "1.0.4" +version = "1.0.6" source = { editable = "." } dependencies = [ { name = "openai" },