diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index f391d416..27d2fbbc 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "3.6.0"
+ ".": "3.7.0"
}
\ No newline at end of file
diff --git a/.stats.yml b/.stats.yml
index 0b389cd6..fa22dd06 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 18
+configured_endpoints: 19
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/supermemory--inc%2Fsupermemory-new-ebd5e757d0e76cb83013e01a1e0bb3dba62beb83b2a2ffa28d148ea032e96fd0.yml
openapi_spec_hash: f930474a6ad230545154244045cc602e
-config_hash: 5bc39292a7e2f871b35cdebbecd9f022
+config_hash: ec08a36e60458b4d83e71798a8043484
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8e3dbe79..0a6f9c74 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,17 @@
# Changelog
+## 3.7.0 (2025-11-26)
+
+Full Changelog: [v3.6.0...v3.7.0](https://github.com/supermemoryai/python-sdk/compare/v3.6.0...v3.7.0)
+
+### Features
+
+* **api:** manual updates ([ee2daac](https://github.com/supermemoryai/python-sdk/commit/ee2daac3a0c1a085971a71ef9605d1d4f6fdb3f7))
+* **api:** manual updates ([89a6e6d](https://github.com/supermemoryai/python-sdk/commit/89a6e6d1220cd8fd2c38d1c54f412650913a9184))
+* **api:** manual updates ([7f0b5aa](https://github.com/supermemoryai/python-sdk/commit/7f0b5aa308004d68b5620f6956068e0c7fbc20da))
+* **api:** manual updates ([3f2f954](https://github.com/supermemoryai/python-sdk/commit/3f2f954a542c4f2e6fc7d6e204c7e44fe640ec7d))
+* **api:** manual updates ([8680e72](https://github.com/supermemoryai/python-sdk/commit/8680e723f9bd9cdc930ed33914557dc60d5242c0))
+
## 3.6.0 (2025-11-26)
Full Changelog: [v3.5.0...v3.6.0](https://github.com/supermemoryai/python-sdk/compare/v3.5.0...v3.6.0)
diff --git a/README.md b/README.md
index 9ed1ed88..7cc684a6 100644
--- a/README.md
+++ b/README.md
@@ -160,7 +160,7 @@ from supermemory import Supermemory
client = Supermemory()
try:
- client.memories.add(
+ client.add(
content="content",
)
except supermemory.APIConnectionError as e:
@@ -205,7 +205,7 @@ client = Supermemory(
)
# Or, configure per-request:
-client.with_options(max_retries=5).memories.add(
+client.with_options(max_retries=5).add(
content="content",
)
```
@@ -230,7 +230,7 @@ client = Supermemory(
)
# Override per-request:
-client.with_options(timeout=5.0).memories.add(
+client.with_options(timeout=5.0).add(
content="content",
)
```
@@ -273,13 +273,13 @@ The "raw" Response object can be accessed by prefixing `.with_raw_response.` to
from supermemory import Supermemory
client = Supermemory()
-response = client.memories.with_raw_response.add(
+response = client.with_raw_response.add(
content="content",
)
print(response.headers.get('X-My-Header'))
-memory = response.parse() # get the object that `memories.add()` would have returned
-print(memory.id)
+client = response.parse() # get the object that `add()` would have returned
+print(client.id)
```
These methods return an [`APIResponse`](https://github.com/supermemoryai/python-sdk/tree/main/src/supermemory/_response.py) object.
@@ -293,7 +293,7 @@ The above interface eagerly reads the full response body when you make the reque
To stream the response body, use `.with_streaming_response` instead, which requires a context manager and only reads the response body once you call `.read()`, `.text()`, `.json()`, `.iter_bytes()`, `.iter_text()`, `.iter_lines()` or `.parse()`. In the async client, these are async methods.
```python
-with client.memories.with_streaming_response.add(
+with client.with_streaming_response.add(
content="content",
) as response:
print(response.headers.get("X-My-Header"))
diff --git a/api.md b/api.md
index 4451d8b1..43179a60 100644
--- a/api.md
+++ b/api.md
@@ -1,9 +1,16 @@
-# Shared Types
+# Supermemory
+
+Types:
```python
-from supermemory.types import And, Or
+from supermemory.types import AddResponse, ProfileResponse
```
+Methods:
+
+- client.add(\*\*params) -> AddResponse
+- client.profile(\*\*params) -> ProfileResponse
+
# Memories
Types:
diff --git a/pyproject.toml b/pyproject.toml
index ac4ed2c5..e7dcc47a 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "supermemory"
-version = "3.6.0"
+version = "3.7.0"
description = "The official Python library for the supermemory API"
dynamic = ["readme"]
license = "Apache-2.0"
diff --git a/src/supermemory/_client.py b/src/supermemory/_client.py
index 0de41593..e9070a3b 100644
--- a/src/supermemory/_client.py
+++ b/src/supermemory/_client.py
@@ -3,24 +3,41 @@
from __future__ import annotations
import os
-from typing import Any, Mapping
+from typing import Any, Dict, Union, Mapping
from typing_extensions import Self, override
import httpx
from . import _exceptions
from ._qs import Querystring
+from .types import client_add_params, client_profile_params
from ._types import (
+ Body,
Omit,
+ Query,
+ Headers,
Timeout,
NotGiven,
Transport,
ProxiesTypes,
RequestOptions,
+ SequenceNotStr,
+ omit,
not_given,
)
-from ._utils import is_given, get_async_library
+from ._utils import (
+ is_given,
+ maybe_transform,
+ get_async_library,
+ async_maybe_transform,
+)
from ._version import __version__
+from ._response import (
+ to_raw_response_wrapper,
+ to_streamed_response_wrapper,
+ async_to_raw_response_wrapper,
+ async_to_streamed_response_wrapper,
+)
from .resources import search, memories, settings, documents, connections
from ._streaming import Stream as Stream, AsyncStream as AsyncStream
from ._exceptions import APIStatusError, SupermemoryError
@@ -28,7 +45,10 @@
DEFAULT_MAX_RETRIES,
SyncAPIClient,
AsyncAPIClient,
+ make_request_options,
)
+from .types.add_response import AddResponse
+from .types.profile_response import ProfileResponse
__all__ = [
"Timeout",
@@ -184,6 +204,106 @@ def copy(
# client.with_options(timeout=10).foo.create(...)
with_options = copy
+ def add(
+ self,
+ *,
+ content: str,
+ container_tag: str | Omit = omit,
+ container_tags: SequenceNotStr[str] | Omit = omit,
+ custom_id: str | Omit = omit,
+ metadata: Dict[str, Union[str, float, bool, SequenceNotStr[str]]] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> AddResponse:
+ """
+ Add a document with any content type (text, url, file, etc.) and metadata
+
+ Args:
+ content: The content to extract and process into a document. This can be a URL to a
+ website, a PDF, an image, or a video.
+
+ container_tag: Optional tag this document should be containerized by. Max 100 characters,
+ alphanumeric with hyphens and underscores only.
+
+ custom_id: Optional custom ID of the document. Max 100 characters, alphanumeric with
+ hyphens and underscores only.
+
+ metadata: Optional metadata for the document.
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ return self.post(
+ "/v3/documents",
+ body=maybe_transform(
+ {
+ "content": content,
+ "container_tag": container_tag,
+ "container_tags": container_tags,
+ "custom_id": custom_id,
+ "metadata": metadata,
+ },
+ client_add_params.ClientAddParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=AddResponse,
+ )
+
+ def profile(
+ self,
+ *,
+ container_tag: str,
+ q: str | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> ProfileResponse:
+ """
+ Get user profile with optional search results
+
+ Args:
+ container_tag: Tag to filter the profile by. This can be an ID for your user, a project ID, or
+ any other identifier you wish to use to filter memories.
+
+ q: Optional search query to include search results in the response
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ return self.post(
+ "/v4/profile",
+ body=maybe_transform(
+ {
+ "container_tag": container_tag,
+ "q": q,
+ },
+ client_profile_params.ClientProfileParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ProfileResponse,
+ )
+
@override
def _make_status_error(
self,
@@ -360,6 +480,106 @@ def copy(
# client.with_options(timeout=10).foo.create(...)
with_options = copy
+ async def add(
+ self,
+ *,
+ content: str,
+ container_tag: str | Omit = omit,
+ container_tags: SequenceNotStr[str] | Omit = omit,
+ custom_id: str | Omit = omit,
+ metadata: Dict[str, Union[str, float, bool, SequenceNotStr[str]]] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> AddResponse:
+ """
+ Add a document with any content type (text, url, file, etc.) and metadata
+
+ Args:
+ content: The content to extract and process into a document. This can be a URL to a
+ website, a PDF, an image, or a video.
+
+ container_tag: Optional tag this document should be containerized by. Max 100 characters,
+ alphanumeric with hyphens and underscores only.
+
+ custom_id: Optional custom ID of the document. Max 100 characters, alphanumeric with
+ hyphens and underscores only.
+
+ metadata: Optional metadata for the document.
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ return await self.post(
+ "/v3/documents",
+ body=await async_maybe_transform(
+ {
+ "content": content,
+ "container_tag": container_tag,
+ "container_tags": container_tags,
+ "custom_id": custom_id,
+ "metadata": metadata,
+ },
+ client_add_params.ClientAddParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=AddResponse,
+ )
+
+ async def profile(
+ self,
+ *,
+ container_tag: str,
+ q: str | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> ProfileResponse:
+ """
+ Get user profile with optional search results
+
+ Args:
+ container_tag: Tag to filter the profile by. This can be an ID for your user, a project ID, or
+ any other identifier you wish to use to filter memories.
+
+ q: Optional search query to include search results in the response
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ return await self.post(
+ "/v4/profile",
+ body=await async_maybe_transform(
+ {
+ "container_tag": container_tag,
+ "q": q,
+ },
+ client_profile_params.ClientProfileParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ProfileResponse,
+ )
+
@override
def _make_status_error(
self,
@@ -402,6 +622,13 @@ def __init__(self, client: Supermemory) -> None:
self.settings = settings.SettingsResourceWithRawResponse(client.settings)
self.connections = connections.ConnectionsResourceWithRawResponse(client.connections)
+ self.add = to_raw_response_wrapper(
+ client.add,
+ )
+ self.profile = to_raw_response_wrapper(
+ client.profile,
+ )
+
class AsyncSupermemoryWithRawResponse:
def __init__(self, client: AsyncSupermemory) -> None:
@@ -411,6 +638,13 @@ def __init__(self, client: AsyncSupermemory) -> None:
self.settings = settings.AsyncSettingsResourceWithRawResponse(client.settings)
self.connections = connections.AsyncConnectionsResourceWithRawResponse(client.connections)
+ self.add = async_to_raw_response_wrapper(
+ client.add,
+ )
+ self.profile = async_to_raw_response_wrapper(
+ client.profile,
+ )
+
class SupermemoryWithStreamedResponse:
def __init__(self, client: Supermemory) -> None:
@@ -420,6 +654,13 @@ def __init__(self, client: Supermemory) -> None:
self.settings = settings.SettingsResourceWithStreamingResponse(client.settings)
self.connections = connections.ConnectionsResourceWithStreamingResponse(client.connections)
+ self.add = to_streamed_response_wrapper(
+ client.add,
+ )
+ self.profile = to_streamed_response_wrapper(
+ client.profile,
+ )
+
class AsyncSupermemoryWithStreamedResponse:
def __init__(self, client: AsyncSupermemory) -> None:
@@ -429,6 +670,13 @@ def __init__(self, client: AsyncSupermemory) -> None:
self.settings = settings.AsyncSettingsResourceWithStreamingResponse(client.settings)
self.connections = connections.AsyncConnectionsResourceWithStreamingResponse(client.connections)
+ self.add = async_to_streamed_response_wrapper(
+ client.add,
+ )
+ self.profile = async_to_streamed_response_wrapper(
+ client.profile,
+ )
+
Client = Supermemory
diff --git a/src/supermemory/_version.py b/src/supermemory/_version.py
index 859e0c9e..3beee285 100644
--- a/src/supermemory/_version.py
+++ b/src/supermemory/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "supermemory"
-__version__ = "3.6.0" # x-release-please-version
+__version__ = "3.7.0" # x-release-please-version
diff --git a/src/supermemory/types/__init__.py b/src/supermemory/types/__init__.py
index 54bc0e85..33058382 100644
--- a/src/supermemory/types/__init__.py
+++ b/src/supermemory/types/__init__.py
@@ -2,7 +2,9 @@
from __future__ import annotations
-from .shared import Or as Or, And as And
+from .add_response import AddResponse as AddResponse
+from .profile_response import ProfileResponse as ProfileResponse
+from .client_add_params import ClientAddParams as ClientAddParams
from .memory_add_params import MemoryAddParams as MemoryAddParams
from .memory_list_params import MemoryListParams as MemoryListParams
from .document_add_params import DocumentAddParams as DocumentAddParams
@@ -12,6 +14,7 @@
from .memory_list_response import MemoryListResponse as MemoryListResponse
from .memory_update_params import MemoryUpdateParams as MemoryUpdateParams
from .setting_get_response import SettingGetResponse as SettingGetResponse
+from .client_profile_params import ClientProfileParams as ClientProfileParams
from .document_add_response import DocumentAddResponse as DocumentAddResponse
from .document_get_response import DocumentGetResponse as DocumentGetResponse
from .search_execute_params import SearchExecuteParams as SearchExecuteParams
diff --git a/src/supermemory/types/add_response.py b/src/supermemory/types/add_response.py
new file mode 100644
index 00000000..cfa9c5fb
--- /dev/null
+++ b/src/supermemory/types/add_response.py
@@ -0,0 +1,13 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .._models import BaseModel
+
+__all__ = ["AddResponse"]
+
+
+class AddResponse(BaseModel):
+ id: str
+ """Unique identifier of the document"""
+
+ status: str
+ """Status of the document"""
diff --git a/src/supermemory/types/client_add_params.py b/src/supermemory/types/client_add_params.py
new file mode 100644
index 00000000..2d9e5c02
--- /dev/null
+++ b/src/supermemory/types/client_add_params.py
@@ -0,0 +1,36 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Dict, Union
+from typing_extensions import Required, Annotated, TypedDict
+
+from .._types import SequenceNotStr
+from .._utils import PropertyInfo
+
+__all__ = ["ClientAddParams"]
+
+
+class ClientAddParams(TypedDict, total=False):
+ content: Required[str]
+ """The content to extract and process into a document.
+
+ This can be a URL to a website, a PDF, an image, or a video.
+ """
+
+ container_tag: Annotated[str, PropertyInfo(alias="containerTag")]
+ """Optional tag this document should be containerized by.
+
+ Max 100 characters, alphanumeric with hyphens and underscores only.
+ """
+
+ container_tags: Annotated[SequenceNotStr[str], PropertyInfo(alias="containerTags")]
+
+ custom_id: Annotated[str, PropertyInfo(alias="customId")]
+ """Optional custom ID of the document.
+
+ Max 100 characters, alphanumeric with hyphens and underscores only.
+ """
+
+ metadata: Dict[str, Union[str, float, bool, SequenceNotStr[str]]]
+ """Optional metadata for the document."""
diff --git a/src/supermemory/types/client_profile_params.py b/src/supermemory/types/client_profile_params.py
new file mode 100644
index 00000000..428b62aa
--- /dev/null
+++ b/src/supermemory/types/client_profile_params.py
@@ -0,0 +1,21 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, Annotated, TypedDict
+
+from .._utils import PropertyInfo
+
+__all__ = ["ClientProfileParams"]
+
+
+class ClientProfileParams(TypedDict, total=False):
+ container_tag: Required[Annotated[str, PropertyInfo(alias="containerTag")]]
+ """Tag to filter the profile by.
+
+ This can be an ID for your user, a project ID, or any other identifier you wish
+ to use to filter memories.
+ """
+
+ q: str
+ """Optional search query to include search results in the response"""
diff --git a/src/supermemory/types/document_list_params.py b/src/supermemory/types/document_list_params.py
index f48c76f1..3b62b1a6 100644
--- a/src/supermemory/types/document_list_params.py
+++ b/src/supermemory/types/document_list_params.py
@@ -2,15 +2,13 @@
from __future__ import annotations
-from typing import Union
-from typing_extensions import Literal, Annotated, TypeAlias, TypedDict
+from typing import Union, Iterable
+from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict
from .._types import SequenceNotStr
from .._utils import PropertyInfo
-from .shared_params.or_ import Or
-from .shared_params.and_ import And
-__all__ = ["DocumentListParams", "Filters"]
+__all__ = ["DocumentListParams", "Filters", "FiltersOr", "FiltersAnd"]
class DocumentListParams(TypedDict, total=False):
@@ -43,4 +41,12 @@ class DocumentListParams(TypedDict, total=False):
"""Field to sort by"""
-Filters: TypeAlias = Union[Or, And]
+class FiltersOr(TypedDict, total=False):
+ or_: Required[Annotated[Iterable[object], PropertyInfo(alias="OR")]]
+
+
+class FiltersAnd(TypedDict, total=False):
+ and_: Required[Annotated[Iterable[object], PropertyInfo(alias="AND")]]
+
+
+Filters: TypeAlias = Union[FiltersOr, FiltersAnd]
diff --git a/src/supermemory/types/memory_list_params.py b/src/supermemory/types/memory_list_params.py
index 07eb8d9a..48eb7f6d 100644
--- a/src/supermemory/types/memory_list_params.py
+++ b/src/supermemory/types/memory_list_params.py
@@ -2,15 +2,13 @@
from __future__ import annotations
-from typing import Union
-from typing_extensions import Literal, Annotated, TypeAlias, TypedDict
+from typing import Union, Iterable
+from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict
from .._types import SequenceNotStr
from .._utils import PropertyInfo
-from .shared_params.or_ import Or
-from .shared_params.and_ import And
-__all__ = ["MemoryListParams", "Filters"]
+__all__ = ["MemoryListParams", "Filters", "FiltersOr", "FiltersAnd"]
class MemoryListParams(TypedDict, total=False):
@@ -43,4 +41,12 @@ class MemoryListParams(TypedDict, total=False):
"""Field to sort by"""
-Filters: TypeAlias = Union[Or, And]
+class FiltersOr(TypedDict, total=False):
+ or_: Required[Annotated[Iterable[object], PropertyInfo(alias="OR")]]
+
+
+class FiltersAnd(TypedDict, total=False):
+ and_: Required[Annotated[Iterable[object], PropertyInfo(alias="AND")]]
+
+
+Filters: TypeAlias = Union[FiltersOr, FiltersAnd]
diff --git a/src/supermemory/types/profile_response.py b/src/supermemory/types/profile_response.py
new file mode 100644
index 00000000..3eb5e2b0
--- /dev/null
+++ b/src/supermemory/types/profile_response.py
@@ -0,0 +1,35 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+
+from pydantic import Field as FieldInfo
+
+from .._models import BaseModel
+
+__all__ = ["ProfileResponse", "Profile", "SearchResults"]
+
+
+class Profile(BaseModel):
+ dynamic: List[str]
+ """Dynamic profile information (recent memories)"""
+
+ static: List[str]
+ """Static profile information that remains relevant long-term"""
+
+
+class SearchResults(BaseModel):
+ results: List[object]
+ """Search results for the provided query"""
+
+ timing: float
+ """Search timing in milliseconds"""
+
+ total: float
+ """Total number of search results"""
+
+
+class ProfileResponse(BaseModel):
+ profile: Profile
+
+ search_results: Optional[SearchResults] = FieldInfo(alias="searchResults", default=None)
+ """Search results if a search query was provided"""
diff --git a/src/supermemory/types/search_documents_params.py b/src/supermemory/types/search_documents_params.py
index 20f62b3c..2b88d453 100644
--- a/src/supermemory/types/search_documents_params.py
+++ b/src/supermemory/types/search_documents_params.py
@@ -2,15 +2,13 @@
from __future__ import annotations
-from typing import Union
+from typing import Union, Iterable
from typing_extensions import Required, Annotated, TypeAlias, TypedDict
from .._types import SequenceNotStr
from .._utils import PropertyInfo
-from .shared_params.or_ import Or
-from .shared_params.and_ import And
-__all__ = ["SearchDocumentsParams", "Filters"]
+__all__ = ["SearchDocumentsParams", "Filters", "FiltersOr", "FiltersAnd"]
class SearchDocumentsParams(TypedDict, total=False):
@@ -84,4 +82,12 @@ class SearchDocumentsParams(TypedDict, total=False):
"""
-Filters: TypeAlias = Union[Or, And]
+class FiltersOr(TypedDict, total=False):
+ or_: Required[Annotated[Iterable[object], PropertyInfo(alias="OR")]]
+
+
+class FiltersAnd(TypedDict, total=False):
+ and_: Required[Annotated[Iterable[object], PropertyInfo(alias="AND")]]
+
+
+Filters: TypeAlias = Union[FiltersOr, FiltersAnd]
diff --git a/src/supermemory/types/search_execute_params.py b/src/supermemory/types/search_execute_params.py
index da786065..9a49c448 100644
--- a/src/supermemory/types/search_execute_params.py
+++ b/src/supermemory/types/search_execute_params.py
@@ -2,15 +2,13 @@
from __future__ import annotations
-from typing import Union
+from typing import Union, Iterable
from typing_extensions import Required, Annotated, TypeAlias, TypedDict
from .._types import SequenceNotStr
from .._utils import PropertyInfo
-from .shared_params.or_ import Or
-from .shared_params.and_ import And
-__all__ = ["SearchExecuteParams", "Filters"]
+__all__ = ["SearchExecuteParams", "Filters", "FiltersOr", "FiltersAnd"]
class SearchExecuteParams(TypedDict, total=False):
@@ -84,4 +82,12 @@ class SearchExecuteParams(TypedDict, total=False):
"""
-Filters: TypeAlias = Union[Or, And]
+class FiltersOr(TypedDict, total=False):
+ or_: Required[Annotated[Iterable[object], PropertyInfo(alias="OR")]]
+
+
+class FiltersAnd(TypedDict, total=False):
+ and_: Required[Annotated[Iterable[object], PropertyInfo(alias="AND")]]
+
+
+Filters: TypeAlias = Union[FiltersOr, FiltersAnd]
diff --git a/src/supermemory/types/search_memories_params.py b/src/supermemory/types/search_memories_params.py
index cca09bc1..20328dc7 100644
--- a/src/supermemory/types/search_memories_params.py
+++ b/src/supermemory/types/search_memories_params.py
@@ -2,14 +2,12 @@
from __future__ import annotations
-from typing import Union
+from typing import Union, Iterable
from typing_extensions import Required, Annotated, TypeAlias, TypedDict
from .._utils import PropertyInfo
-from .shared_params.or_ import Or
-from .shared_params.and_ import And
-__all__ = ["SearchMemoriesParams", "Filters", "Include"]
+__all__ = ["SearchMemoriesParams", "Filters", "FiltersOr", "FiltersAnd", "Include"]
class SearchMemoriesParams(TypedDict, total=False):
@@ -51,7 +49,15 @@ class SearchMemoriesParams(TypedDict, total=False):
"""
-Filters: TypeAlias = Union[Or, And]
+class FiltersOr(TypedDict, total=False):
+ or_: Required[Annotated[Iterable[object], PropertyInfo(alias="OR")]]
+
+
+class FiltersAnd(TypedDict, total=False):
+ and_: Required[Annotated[Iterable[object], PropertyInfo(alias="AND")]]
+
+
+Filters: TypeAlias = Union[FiltersOr, FiltersAnd]
class Include(TypedDict, total=False):
diff --git a/src/supermemory/types/shared/__init__.py b/src/supermemory/types/shared/__init__.py
deleted file mode 100644
index 96ecf13e..00000000
--- a/src/supermemory/types/shared/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from .or_ import Or as Or
-from .and_ import And as And
diff --git a/src/supermemory/types/shared/and_.py b/src/supermemory/types/shared/and_.py
deleted file mode 100644
index 980dbb24..00000000
--- a/src/supermemory/types/shared/and_.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import List
-
-from pydantic import Field as FieldInfo
-
-from ..._models import BaseModel
-
-__all__ = ["And"]
-
-
-class And(BaseModel):
- and_: List[object] = FieldInfo(alias="AND")
diff --git a/src/supermemory/types/shared/or_.py b/src/supermemory/types/shared/or_.py
deleted file mode 100644
index fe2c5a95..00000000
--- a/src/supermemory/types/shared/or_.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import List
-
-from pydantic import Field as FieldInfo
-
-from ..._models import BaseModel
-
-__all__ = ["Or"]
-
-
-class Or(BaseModel):
- or_: List[object] = FieldInfo(alias="OR")
diff --git a/src/supermemory/types/shared_params/__init__.py b/src/supermemory/types/shared_params/__init__.py
deleted file mode 100644
index 96ecf13e..00000000
--- a/src/supermemory/types/shared_params/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from .or_ import Or as Or
-from .and_ import And as And
diff --git a/src/supermemory/types/shared_params/and_.py b/src/supermemory/types/shared_params/and_.py
deleted file mode 100644
index 0e0dad21..00000000
--- a/src/supermemory/types/shared_params/and_.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Iterable
-from typing_extensions import Required, Annotated, TypedDict
-
-from ..._utils import PropertyInfo
-
-__all__ = ["And"]
-
-
-class And(TypedDict, total=False):
- and_: Required[Annotated[Iterable[object], PropertyInfo(alias="AND")]]
diff --git a/src/supermemory/types/shared_params/or_.py b/src/supermemory/types/shared_params/or_.py
deleted file mode 100644
index fdb83e1f..00000000
--- a/src/supermemory/types/shared_params/or_.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Iterable
-from typing_extensions import Required, Annotated, TypedDict
-
-from ..._utils import PropertyInfo
-
-__all__ = ["Or"]
-
-
-class Or(TypedDict, total=False):
- or_: Required[Annotated[Iterable[object], PropertyInfo(alias="OR")]]
diff --git a/tests/api_resources/test_client.py b/tests/api_resources/test_client.py
new file mode 100644
index 00000000..37b1c63e
--- /dev/null
+++ b/tests/api_resources/test_client.py
@@ -0,0 +1,202 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import os
+from typing import Any, cast
+
+import pytest
+
+from supermemory import Supermemory, AsyncSupermemory
+from tests.utils import assert_matches_type
+from supermemory.types import AddResponse, ProfileResponse
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestClient:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_add(self, client: Supermemory) -> None:
+ client_ = client.add(
+ content="content",
+ )
+ assert_matches_type(AddResponse, client_, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_add_with_all_params(self, client: Supermemory) -> None:
+ client_ = client.add(
+ content="content",
+ container_tag="containerTag",
+ container_tags=["string"],
+ custom_id="customId",
+ metadata={"foo": "string"},
+ )
+ assert_matches_type(AddResponse, client_, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_add(self, client: Supermemory) -> None:
+ response = client.with_raw_response.add(
+ content="content",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ client_ = response.parse()
+ assert_matches_type(AddResponse, client_, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_add(self, client: Supermemory) -> None:
+ with client.with_streaming_response.add(
+ content="content",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ client_ = response.parse()
+ assert_matches_type(AddResponse, client_, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_profile(self, client: Supermemory) -> None:
+ client_ = client.profile(
+ container_tag="containerTag",
+ )
+ assert_matches_type(ProfileResponse, client_, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_profile_with_all_params(self, client: Supermemory) -> None:
+ client_ = client.profile(
+ container_tag="containerTag",
+ q="q",
+ )
+ assert_matches_type(ProfileResponse, client_, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_profile(self, client: Supermemory) -> None:
+ response = client.with_raw_response.profile(
+ container_tag="containerTag",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ client_ = response.parse()
+ assert_matches_type(ProfileResponse, client_, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_profile(self, client: Supermemory) -> None:
+ with client.with_streaming_response.profile(
+ container_tag="containerTag",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ client_ = response.parse()
+ assert_matches_type(ProfileResponse, client_, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncClient:
+ parametrize = pytest.mark.parametrize(
+ "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_add(self, async_client: AsyncSupermemory) -> None:
+ client = await async_client.add(
+ content="content",
+ )
+ assert_matches_type(AddResponse, client, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_add_with_all_params(self, async_client: AsyncSupermemory) -> None:
+ client = await async_client.add(
+ content="content",
+ container_tag="containerTag",
+ container_tags=["string"],
+ custom_id="customId",
+ metadata={"foo": "string"},
+ )
+ assert_matches_type(AddResponse, client, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_add(self, async_client: AsyncSupermemory) -> None:
+ response = await async_client.with_raw_response.add(
+ content="content",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ client = await response.parse()
+ assert_matches_type(AddResponse, client, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_add(self, async_client: AsyncSupermemory) -> None:
+ async with async_client.with_streaming_response.add(
+ content="content",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ client = await response.parse()
+ assert_matches_type(AddResponse, client, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_profile(self, async_client: AsyncSupermemory) -> None:
+ client = await async_client.profile(
+ container_tag="containerTag",
+ )
+ assert_matches_type(ProfileResponse, client, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_profile_with_all_params(self, async_client: AsyncSupermemory) -> None:
+ client = await async_client.profile(
+ container_tag="containerTag",
+ q="q",
+ )
+ assert_matches_type(ProfileResponse, client, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_profile(self, async_client: AsyncSupermemory) -> None:
+ response = await async_client.with_raw_response.profile(
+ container_tag="containerTag",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ client = await response.parse()
+ assert_matches_type(ProfileResponse, client, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_profile(self, async_client: AsyncSupermemory) -> None:
+ async with async_client.with_streaming_response.profile(
+ container_tag="containerTag",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ client = await response.parse()
+ assert_matches_type(ProfileResponse, client, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/test_client.py b/tests/test_client.py
index aa1ea71c..3d65c9a7 100644
--- a/tests/test_client.py
+++ b/tests/test_client.py
@@ -747,7 +747,7 @@ def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter, clien
respx_mock.post("/v3/documents").mock(side_effect=httpx.TimeoutException("Test timeout error"))
with pytest.raises(APITimeoutError):
- client.memories.with_streaming_response.add(content="content").__enter__()
+ client.with_streaming_response.add(content="content").__enter__()
assert _get_open_connections(client) == 0
@@ -757,7 +757,7 @@ def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter, client
respx_mock.post("/v3/documents").mock(return_value=httpx.Response(500))
with pytest.raises(APIStatusError):
- client.memories.with_streaming_response.add(content="content").__enter__()
+ client.with_streaming_response.add(content="content").__enter__()
assert _get_open_connections(client) == 0
@pytest.mark.parametrize("failures_before_success", [0, 2, 4])
@@ -786,7 +786,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/v3/documents").mock(side_effect=retry_handler)
- response = client.memories.with_raw_response.add(content="content")
+ response = client.with_raw_response.add(content="content")
assert response.retries_taken == failures_before_success
assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success
@@ -810,9 +810,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/v3/documents").mock(side_effect=retry_handler)
- response = client.memories.with_raw_response.add(
- content="content", extra_headers={"x-stainless-retry-count": Omit()}
- )
+ response = client.with_raw_response.add(content="content", extra_headers={"x-stainless-retry-count": Omit()})
assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0
@@ -835,9 +833,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/v3/documents").mock(side_effect=retry_handler)
- response = client.memories.with_raw_response.add(
- content="content", extra_headers={"x-stainless-retry-count": "42"}
- )
+ response = client.with_raw_response.add(content="content", extra_headers={"x-stainless-retry-count": "42"})
assert response.http_request.headers.get("x-stainless-retry-count") == "42"
@@ -1587,7 +1583,7 @@ async def test_retrying_timeout_errors_doesnt_leak(
respx_mock.post("/v3/documents").mock(side_effect=httpx.TimeoutException("Test timeout error"))
with pytest.raises(APITimeoutError):
- await async_client.memories.with_streaming_response.add(content="content").__aenter__()
+ await async_client.with_streaming_response.add(content="content").__aenter__()
assert _get_open_connections(async_client) == 0
@@ -1599,7 +1595,7 @@ async def test_retrying_status_errors_doesnt_leak(
respx_mock.post("/v3/documents").mock(return_value=httpx.Response(500))
with pytest.raises(APIStatusError):
- await async_client.memories.with_streaming_response.add(content="content").__aenter__()
+ await async_client.with_streaming_response.add(content="content").__aenter__()
assert _get_open_connections(async_client) == 0
@pytest.mark.parametrize("failures_before_success", [0, 2, 4])
@@ -1628,7 +1624,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/v3/documents").mock(side_effect=retry_handler)
- response = await client.memories.with_raw_response.add(content="content")
+ response = await client.with_raw_response.add(content="content")
assert response.retries_taken == failures_before_success
assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success
@@ -1652,7 +1648,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/v3/documents").mock(side_effect=retry_handler)
- response = await client.memories.with_raw_response.add(
+ response = await client.with_raw_response.add(
content="content", extra_headers={"x-stainless-retry-count": Omit()}
)
@@ -1677,7 +1673,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/v3/documents").mock(side_effect=retry_handler)
- response = await client.memories.with_raw_response.add(
+ response = await client.with_raw_response.add(
content="content", extra_headers={"x-stainless-retry-count": "42"}
)