aboutsummaryrefslogtreecommitdiff
path: root/packages/openai-sdk-python/tests
diff options
context:
space:
mode:
authorCodeWithShreyans <[email protected]>2025-08-27 23:34:49 +0000
committerCodeWithShreyans <[email protected]>2025-08-27 23:34:49 +0000
commit3a0e264b7eb18fe3b6d2de25e79879ada7c9f3ec (patch)
tree4f2be5731860abece575bf4946ef881972502d73 /packages/openai-sdk-python/tests
parentfeat: support project-specific installation commands (#390) (diff)
downloadsupermemory-3a0e264b7eb18fe3b6d2de25e79879ada7c9f3ec.tar.xz
supermemory-3a0e264b7eb18fe3b6d2de25e79879ada7c9f3ec.zip
feat: openai js and python sdk utilities (#389)shreyans/08-27-feat_openai_js_and_python_sdk_utilities
needs testing
Diffstat (limited to 'packages/openai-sdk-python/tests')
-rw-r--r--packages/openai-sdk-python/tests/__init__.py1
-rw-r--r--packages/openai-sdk-python/tests/test_infinite_chat.py387
-rw-r--r--packages/openai-sdk-python/tests/test_tools.py350
3 files changed, 738 insertions, 0 deletions
diff --git a/packages/openai-sdk-python/tests/__init__.py b/packages/openai-sdk-python/tests/__init__.py
new file mode 100644
index 00000000..66173aec
--- /dev/null
+++ b/packages/openai-sdk-python/tests/__init__.py
@@ -0,0 +1 @@
+# Test package
diff --git a/packages/openai-sdk-python/tests/test_infinite_chat.py b/packages/openai-sdk-python/tests/test_infinite_chat.py
new file mode 100644
index 00000000..9fdf52c5
--- /dev/null
+++ b/packages/openai-sdk-python/tests/test_infinite_chat.py
@@ -0,0 +1,387 @@
+"""Tests for infinite_chat module."""
+
+import os
+import pytest
+from typing import List
+
+from openai.types.chat import ChatCompletionMessageParam
+from ..src import (
+ SupermemoryOpenAI,
+ SupermemoryInfiniteChatConfigWithProviderName,
+ SupermemoryInfiniteChatConfigWithProviderUrl,
+ ProviderName,
+)
+
+
+# Test configuration
+PROVIDERS: List[ProviderName] = [
+ "openai",
+ "anthropic",
+ "openrouter",
+ "deepinfra",
+ "groq",
+ "google",
+ "cloudflare",
+]
+
+
+def test_api_key() -> str:
+ """Get test Supermemory API key from environment."""
+ api_key = os.getenv("SUPERMEMORY_API_KEY")
+ if not api_key:
+ pytest.skip("SUPERMEMORY_API_KEY environment variable is required for tests")
+ return api_key
+
+
+def test_provider_api_key() -> str:
+ """Get test provider API key from environment."""
+ api_key = os.getenv("PROVIDER_API_KEY")
+ if not api_key:
+ pytest.skip("PROVIDER_API_KEY environment variable is required for tests")
+ return api_key
+
+
+def test_provider_name() -> ProviderName:
+ """Get test provider name from environment."""
+ provider_name = os.getenv("PROVIDER_NAME", "openai")
+ if provider_name not in PROVIDERS:
+ pytest.fail(f"Invalid provider name: {provider_name}")
+ return provider_name # type: ignore
+
+
+def test_provider_url() -> str:
+ """Get test provider URL from environment."""
+ return os.getenv("PROVIDER_URL", "")
+
+
+def test_model_name() -> str:
+ """Get test model name from environment."""
+ return os.getenv("MODEL_NAME", "gpt-4o-mini")
+
+
+def test_headers() -> dict:
+ """Get test headers."""
+ return {"custom-header": "test-value"}
+
+
+def test_messages() -> List[List[ChatCompletionMessageParam]]:
+ """Test message sets."""
+ return [
+ [{"role": "user", "content": "Hello!"}],
+ [
+ {"role": "system", "content": "You are a helpful assistant."},
+ {"role": "user", "content": "What is AI?"},
+ ],
+ [
+ {"role": "user", "content": "Tell me a joke"},
+ {
+ "role": "assistant",
+ "content": "Why don't scientists trust atoms? Because they make up everything!",
+ },
+ {"role": "user", "content": "Tell me another one"},
+ ],
+ ]
+
+
+class TestClientCreation:
+ """Test client creation."""
+
+ def test_create_client_with_provider_name(
+ self,
+ test_api_key: str,
+ test_provider_api_key: str,
+ test_provider_name: ProviderName,
+ test_headers: dict,
+ ):
+ """Test creating client with provider name configuration."""
+ config = SupermemoryInfiniteChatConfigWithProviderName(
+ provider_name=test_provider_name,
+ provider_api_key=test_provider_api_key,
+ headers=test_headers,
+ )
+
+ client = SupermemoryOpenAI(test_api_key, config)
+
+ assert client is not None
+ assert client.chat is not None
+
+ def test_create_client_with_openai_provider(
+ self, test_api_key: str, test_provider_api_key: str, test_headers: dict
+ ):
+ """Test creating client with OpenAI provider configuration."""
+ config = SupermemoryInfiniteChatConfigWithProviderName(
+ provider_name="openai",
+ provider_api_key=test_provider_api_key,
+ headers=test_headers,
+ )
+
+ client = SupermemoryOpenAI(test_api_key, config)
+
+ assert client is not None
+
+ def test_create_client_with_custom_provider_url(
+ self, test_api_key: str, test_provider_api_key: str, test_headers: dict
+ ):
+ """Test creating client with custom provider URL."""
+ custom_url = "https://custom-provider.com/v1"
+ config = SupermemoryInfiniteChatConfigWithProviderUrl(
+ provider_url=custom_url,
+ provider_api_key=test_provider_api_key,
+ headers=test_headers,
+ )
+
+ client = SupermemoryOpenAI(test_api_key, config)
+
+ assert client is not None
+
+
+class TestChatCompletions:
+ """Test chat completions functionality."""
+
+ @pytest.mark.asyncio
+ async def test_create_chat_completion_simple_message(
+ self,
+ test_api_key: str,
+ test_provider_api_key: str,
+ test_provider_name: ProviderName,
+ test_model_name: str,
+ test_messages: List[List[ChatCompletionMessageParam]],
+ ):
+ """Test creating chat completion with simple message."""
+ config = SupermemoryInfiniteChatConfigWithProviderName(
+ provider_name=test_provider_name,
+ provider_api_key=test_provider_api_key,
+ headers={},
+ )
+
+ client = SupermemoryOpenAI(test_api_key, config)
+
+ result = await client.create_chat_completion(
+ model=test_model_name,
+ messages=test_messages[0], # "Hello!"
+ )
+
+ assert result is not None
+ assert hasattr(result, "choices")
+ assert len(result.choices) > 0
+ assert result.choices[0].message.content is not None
+
+ @pytest.mark.asyncio
+ async def test_chat_completion_convenience_method(
+ self,
+ test_api_key: str,
+ test_provider_api_key: str,
+ test_provider_name: ProviderName,
+ test_model_name: str,
+ test_messages: List[List[ChatCompletionMessageParam]],
+ ):
+ """Test chat completion using convenience method."""
+ config = SupermemoryInfiniteChatConfigWithProviderName(
+ provider_name=test_provider_name,
+ provider_api_key=test_provider_api_key,
+ headers={},
+ )
+
+ client = SupermemoryOpenAI(test_api_key, config)
+
+ result = await client.chat_completion(
+ messages=test_messages[1], # System + user messages
+ model=test_model_name,
+ temperature=0.7,
+ )
+
+ assert result is not None
+ assert hasattr(result, "choices")
+ assert len(result.choices) > 0
+ assert result.choices[0].message.content is not None
+
+ @pytest.mark.asyncio
+ async def test_handle_conversation_history(
+ self,
+ test_api_key: str,
+ test_provider_api_key: str,
+ test_provider_name: ProviderName,
+ test_model_name: str,
+ test_messages: List[List[ChatCompletionMessageParam]],
+ ):
+ """Test handling conversation history."""
+ config = SupermemoryInfiniteChatConfigWithProviderName(
+ provider_name=test_provider_name,
+ provider_api_key=test_provider_api_key,
+ headers={},
+ )
+
+ client = SupermemoryOpenAI(test_api_key, config)
+
+ result = await client.chat_completion(
+ messages=test_messages[2], # Multi-turn conversation
+ model=test_model_name,
+ )
+
+ assert result is not None
+ assert hasattr(result, "choices")
+ assert len(result.choices) > 0
+ assert result.choices[0].message.content is not None
+
+ @pytest.mark.asyncio
+ async def test_custom_headers(
+ self,
+ test_api_key: str,
+ test_provider_api_key: str,
+ test_provider_name: ProviderName,
+ test_model_name: str,
+ ):
+ """Test working with custom headers."""
+ config = SupermemoryInfiniteChatConfigWithProviderName(
+ provider_name=test_provider_name,
+ provider_api_key=test_provider_api_key,
+ headers={"x-custom-header": "test-value"},
+ )
+
+ client = SupermemoryOpenAI(test_api_key, config)
+
+ result = await client.chat_completion(
+ messages=[{"role": "user", "content": "Hello"}],
+ model=test_model_name,
+ )
+
+ assert result is not None
+ assert hasattr(result, "choices")
+
+
+class TestConfigurationValidation:
+ """Test configuration validation."""
+
+ def test_handle_empty_headers_object(
+ self,
+ test_api_key: str,
+ test_provider_api_key: str,
+ test_provider_name: ProviderName,
+ ):
+ """Test handling empty headers object."""
+ config = SupermemoryInfiniteChatConfigWithProviderName(
+ provider_name=test_provider_name,
+ provider_api_key=test_provider_api_key,
+ headers={},
+ )
+
+ client = SupermemoryOpenAI(test_api_key, config)
+
+ assert client is not None
+
+ def test_handle_configuration_without_headers(
+ self,
+ test_api_key: str,
+ test_provider_api_key: str,
+ test_provider_name: ProviderName,
+ ):
+ """Test handling configuration without headers."""
+ config = SupermemoryInfiniteChatConfigWithProviderName(
+ provider_name=test_provider_name,
+ provider_api_key=test_provider_api_key,
+ )
+
+ client = SupermemoryOpenAI(test_api_key, config)
+
+ assert client is not None
+
+ def test_handle_different_api_keys(self):
+ """Test handling different API keys."""
+ config = SupermemoryInfiniteChatConfigWithProviderName(
+ provider_name="openai",
+ provider_api_key="different-provider-key",
+ )
+
+ client = SupermemoryOpenAI("different-sm-key", config)
+
+ assert client is not None
+
+
+class TestDisabledEndpoints:
+ """Test that non-chat endpoints are disabled."""
+
+ def test_disabled_endpoints_throw_errors(
+ self, test_api_key: str, test_provider_api_key: str
+ ):
+ """Test that all disabled endpoints throw appropriate errors."""
+ config = SupermemoryInfiniteChatConfigWithProviderName(
+ provider_name="openai",
+ provider_api_key=test_provider_api_key,
+ )
+
+ client = SupermemoryOpenAI(test_api_key, config)
+
+ # Test that all disabled endpoints throw appropriate errors
+ with pytest.raises(
+ RuntimeError, match="Supermemory only supports chat completions"
+ ):
+ _ = client.embeddings
+
+ with pytest.raises(
+ RuntimeError, match="Supermemory only supports chat completions"
+ ):
+ _ = client.fine_tuning
+
+ with pytest.raises(
+ RuntimeError, match="Supermemory only supports chat completions"
+ ):
+ _ = client.images
+
+ with pytest.raises(
+ RuntimeError, match="Supermemory only supports chat completions"
+ ):
+ _ = client.audio
+
+ with pytest.raises(
+ RuntimeError, match="Supermemory only supports chat completions"
+ ):
+ _ = client.models
+
+ with pytest.raises(
+ RuntimeError, match="Supermemory only supports chat completions"
+ ):
+ _ = client.moderations
+
+ with pytest.raises(
+ RuntimeError, match="Supermemory only supports chat completions"
+ ):
+ _ = client.files
+
+ with pytest.raises(
+ RuntimeError, match="Supermemory only supports chat completions"
+ ):
+ _ = client.batches
+
+ with pytest.raises(
+ RuntimeError, match="Supermemory only supports chat completions"
+ ):
+ _ = client.uploads
+
+ with pytest.raises(
+ RuntimeError, match="Supermemory only supports chat completions"
+ ):
+ _ = client.beta
+
+ def test_chat_completions_still_work(
+ self, test_api_key: str, test_provider_api_key: str
+ ):
+ """Test that chat completions still work after disabling other endpoints."""
+ config = SupermemoryInfiniteChatConfigWithProviderName(
+ provider_name="openai",
+ provider_api_key=test_provider_api_key,
+ )
+
+ client = SupermemoryOpenAI(test_api_key, config)
+
+ # Chat completions should still be accessible
+ assert client.chat is not None
+ assert client.chat.completions is not None
+ assert callable(client.create_chat_completion)
+ assert callable(client.chat_completion)
diff --git a/packages/openai-sdk-python/tests/test_tools.py b/packages/openai-sdk-python/tests/test_tools.py
new file mode 100644
index 00000000..835622c7
--- /dev/null
+++ b/packages/openai-sdk-python/tests/test_tools.py
@@ -0,0 +1,350 @@
+"""Tests for tools module."""
+
+import os
+import pytest
+import json
+from typing import List
+
+from openai.types.chat import ChatCompletionMessageToolCall
+from ..src import (
+ SupermemoryTools,
+ SupermemoryToolsConfig,
+ SupermemoryOpenAI,
+ SupermemoryInfiniteChatConfigWithProviderName,
+ create_supermemory_tools,
+ get_memory_tool_definitions,
+ execute_memory_tool_calls,
+ create_search_memories_tool,
+ create_add_memory_tool,
+)
+
+
+def test_api_key() -> str:
+ """Get test Supermemory API key from environment."""
+ api_key = os.getenv("SUPERMEMORY_API_KEY")
+ if not api_key:
+ pytest.skip("SUPERMEMORY_API_KEY environment variable is required for tests")
+ return api_key
+
+
+def test_provider_api_key() -> str:
+ """Get test provider API key from environment."""
+ api_key = os.getenv("PROVIDER_API_KEY")
+ if not api_key:
+ pytest.skip("PROVIDER_API_KEY environment variable is required for tests")
+ return api_key
+
+
+def test_base_url() -> str:
+ """Get test base URL from environment."""
+ return os.getenv("SUPERMEMORY_BASE_URL", "")
+
+
+def test_model_name() -> str:
+ """Get test model name from environment."""
+ return os.getenv("MODEL_NAME", "gpt-4o-mini")
+
+
+class TestToolInitialization:
+ """Test tool initialization."""
+
+ def test_create_tools_with_default_configuration(self, test_api_key: str):
+ """Test creating tools with default configuration."""
+ config: SupermemoryToolsConfig = {}
+ tools = SupermemoryTools(test_api_key, config)
+
+ assert tools is not None
+ assert tools.get_tool_definitions() is not None
+ assert len(tools.get_tool_definitions()) == 3
+
+ def test_create_tools_with_helper(self, test_api_key: str):
+ """Test creating tools with createSupermemoryTools helper."""
+ tools = create_supermemory_tools(
+ test_api_key,
+ {
+ "project_id": "test-project",
+ },
+ )
+
+ assert tools is not None
+ assert tools.get_tool_definitions() is not None
+
+ def test_create_tools_with_custom_base_url(
+ self, test_api_key: str, test_base_url: str
+ ):
+ """Test creating tools with custom baseUrl."""
+ if not test_base_url:
+ pytest.skip("SUPERMEMORY_BASE_URL not provided")
+
+ config: SupermemoryToolsConfig = {
+ "base_url": test_base_url,
+ }
+ tools = SupermemoryTools(test_api_key, config)
+
+ assert tools is not None
+ assert len(tools.get_tool_definitions()) == 3
+
+ def test_create_tools_with_project_id(self, test_api_key: str):
+ """Test creating tools with projectId configuration."""
+ config: SupermemoryToolsConfig = {
+ "project_id": "test-project-123",
+ }
+ tools = SupermemoryTools(test_api_key, config)
+
+ assert tools is not None
+ assert len(tools.get_tool_definitions()) == 3
+
+ def test_create_tools_with_custom_container_tags(self, test_api_key: str):
+ """Test creating tools with custom container tags."""
+ config: SupermemoryToolsConfig = {
+ "container_tags": ["custom-tag-1", "custom-tag-2"],
+ }
+ tools = SupermemoryTools(test_api_key, config)
+
+ assert tools is not None
+ assert len(tools.get_tool_definitions()) == 3
+
+
+class TestToolDefinitions:
+ """Test tool definitions."""
+
+ def test_return_proper_openai_function_definitions(self):
+ """Test returning proper OpenAI function definitions."""
+ definitions = get_memory_tool_definitions()
+
+ assert definitions is not None
+ assert len(definitions) == 3
+
+ # Check searchMemories
+ search_tool = next(
+ (d for d in definitions if d["function"]["name"] == "search_memories"), None
+ )
+ assert search_tool is not None
+ assert search_tool["type"] == "function"
+ assert "information_to_get" in search_tool["function"]["parameters"]["required"]
+
+ # Check addMemory
+ add_tool = next(
+ (d for d in definitions if d["function"]["name"] == "add_memory"), None
+ )
+ assert add_tool is not None
+ assert add_tool["type"] == "function"
+ assert "memory" in add_tool["function"]["parameters"]["required"]
+
+ def test_consistent_tool_definitions_from_class_and_helper(self, test_api_key: str):
+ """Test that tool definitions are consistent between class and helper."""
+ tools = SupermemoryTools(test_api_key)
+ class_definitions = tools.get_tool_definitions()
+ helper_definitions = get_memory_tool_definitions()
+
+ assert class_definitions == helper_definitions
+
+
+class TestMemoryOperations:
+ """Test memory operations."""
+
+ @pytest.mark.asyncio
+ async def test_search_memories(self, test_api_key: str, test_base_url: str):
+ """Test searching memories."""
+ config: SupermemoryToolsConfig = {
+ "project_id": "test-search",
+ }
+ if test_base_url:
+ config["base_url"] = test_base_url
+
+ tools = SupermemoryTools(test_api_key, config)
+
+ result = await tools.search_memories(
+ information_to_get="test preferences",
+ limit=5,
+ )
+
+ assert result is not None
+ assert "success" in result
+ assert isinstance(result["success"], bool)
+
+ if result["success"]:
+ assert "results" in result
+ assert "count" in result
+ assert isinstance(result["count"], int)
+ else:
+ assert "error" in result
+
+ @pytest.mark.asyncio
+ async def test_add_memory(self, test_api_key: str, test_base_url: str):
+ """Test adding memory."""
+ config: SupermemoryToolsConfig = {
+ "container_tags": ["test-add-memory"],
+ }
+ if test_base_url:
+ config["base_url"] = test_base_url
+
+ tools = SupermemoryTools(test_api_key, config)
+
+ result = await tools.add_memory(
+ memory="User prefers dark roast coffee in the morning - test memory"
+ )
+
+ assert result is not None
+ assert "success" in result
+ assert isinstance(result["success"], bool)
+
+ if result["success"]:
+ assert "memory" in result
+ else:
+ assert "error" in result
+
+
+class TestIndividualToolCreators:
+ """Test individual tool creators."""
+
+ def test_create_individual_search_tool(self, test_api_key: str):
+ """Test creating individual search tool."""
+ search_tool = create_search_memories_tool(
+ test_api_key,
+ {
+ "project_id": "test-individual",
+ },
+ )
+
+ assert search_tool is not None
+ assert search_tool.definition is not None
+ assert callable(search_tool.execute)
+ assert search_tool.definition["function"]["name"] == "search_memories"
+
+ def test_create_individual_add_tool(self, test_api_key: str):
+ """Test creating individual add tool."""
+ add_tool = create_add_memory_tool(
+ test_api_key,
+ {
+ "project_id": "test-individual",
+ },
+ )
+
+ assert add_tool is not None
+ assert add_tool.definition is not None
+ assert callable(add_tool.execute)
+ assert add_tool.definition["function"]["name"] == "add_memory"
+
+
+class TestOpenAIIntegration:
+ """Test OpenAI integration."""
+
+ @pytest.mark.asyncio
+ async def test_work_with_supermemory_openai_for_function_calling(
+ self,
+ test_api_key: str,
+ test_provider_api_key: str,
+ test_model_name: str,
+ test_base_url: str,
+ ):
+ """Test working with SupermemoryOpenAI for function calling."""
+ client = SupermemoryOpenAI(
+ test_api_key,
+ SupermemoryInfiniteChatConfigWithProviderName(
+ provider_name="openai",
+ provider_api_key=test_provider_api_key,
+ ),
+ )
+
+ tools_config: SupermemoryToolsConfig = {
+ "project_id": "test-openai-integration",
+ }
+ if test_base_url:
+ tools_config["base_url"] = test_base_url
+
+ tools = SupermemoryTools(test_api_key, tools_config)
+
+ response = await client.chat_completion(
+ messages=[
+ {
+ "role": "system",
+ "content": (
+ "You are a helpful assistant with access to user memories. "
+ "When the user asks you to remember something, use the add_memory tool."
+ ),
+ },
+ {
+ "role": "user",
+ "content": "Please remember that I prefer tea over coffee",
+ },
+ ],
+ model=test_model_name,
+ tools=tools.get_tool_definitions(),
+ )
+
+ assert response is not None
+ assert hasattr(response, "choices")
+
+ choice = response.choices[0]
+ assert choice.message is not None
+
+ # If the model decided to use function calling, test the execution
+ if hasattr(choice.message, "tool_calls") and choice.message.tool_calls:
+ tool_results = await execute_memory_tool_calls(
+ test_api_key,
+ choice.message.tool_calls,
+ tools_config,
+ )
+
+ assert tool_results is not None
+ assert len(tool_results) == len(choice.message.tool_calls)
+
+ for result in tool_results:
+ assert result["role"] == "tool"
+ assert "content" in result
+ assert "tool_call_id" in result
+
+ @pytest.mark.asyncio
+ async def test_handle_multiple_tool_calls(
+ self, test_api_key: str, test_base_url: str
+ ):
+ """Test handling multiple tool calls."""
+ tools_config: SupermemoryToolsConfig = {
+ "container_tags": ["test-multi-tools"],
+ }
+ if test_base_url:
+ tools_config["base_url"] = test_base_url
+
+ # Simulate tool calls (normally these would come from OpenAI)
+ mock_tool_calls: List[ChatCompletionMessageToolCall] = [
+ ChatCompletionMessageToolCall(
+ id="call_1",
+ type="function",
+ function={
+ "name": "search_memories",
+ "arguments": json.dumps({"information_to_get": "preferences"}),
+ },
+ ),
+ ChatCompletionMessageToolCall(
+ id="call_2",
+ type="function",
+ function={
+ "name": "add_memory",
+ "arguments": json.dumps(
+ {"memory": "Test memory for multiple calls"}
+ ),
+ },
+ ),
+ ]
+
+ results = await execute_memory_tool_calls(
+ test_api_key, mock_tool_calls, tools_config
+ )
+
+ assert results is not None
+ assert len(results) == 2
+
+ assert results[0]["tool_call_id"] == "call_1"
+ assert results[1]["tool_call_id"] == "call_2"
+
+ for result in results:
+ assert result["role"] == "tool"
+ assert "content" in result
+
+ content = json.loads(result["content"])
+ assert "success" in content