diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index d52d2b97..b4e9013b 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.13.0"
+ ".": "0.16.0"
}
\ No newline at end of file
diff --git a/.stats.yml b/.stats.yml
index fd6cf3f6..6b2619bf 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 10
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/hyperspell%2Fhyperspell-287b83fd66b657b044f4ab280ab0e72a2ed72c0da50e4a7d09ce98123982262f.yml
-openapi_spec_hash: fcef51b5cf5e602a2d8025546e27e24a
-config_hash: a39dfe90372d06d735dfb3d27b30409f
+configured_endpoints: 12
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/hyperspell%2Fhyperspell-472f6034747ca75f970d64e57875f1cb24991ad422e17f3e9839757b84e2cb3d.yml
+openapi_spec_hash: 9759125c6a0c64da09c94923667f34a5
+config_hash: da009f16a6b9b4db17be2949180ace1e
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3ebd15c3..db238388 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,15 @@
# Changelog
+## 0.16.0 (2025-05-29)
+
+Full Changelog: [v0.13.0...v0.16.0](https://github.com/hyperspell/python-sdk/compare/v0.13.0...v0.16.0)
+
+### Features
+
+* **api:** api update ([3334f14](https://github.com/hyperspell/python-sdk/commit/3334f14582bda6ec78c9b479317c8d818b1c1227))
+* **api:** api update ([b6ad9f4](https://github.com/hyperspell/python-sdk/commit/b6ad9f43113a8cbf23580027c37ecaf95cb37cb3))
+* **api:** update via SDK Studio ([bff74c9](https://github.com/hyperspell/python-sdk/commit/bff74c98b5b08e45e291381753340a22c6b04c89))
+
## 0.13.0 (2025-05-26)
Full Changelog: [v0.12.0...v0.13.0](https://github.com/hyperspell/python-sdk/compare/v0.12.0...v0.13.0)
diff --git a/api.md b/api.md
index e5aee0a0..c8fcbbc2 100644
--- a/api.md
+++ b/api.md
@@ -39,13 +39,15 @@ Methods:
Types:
```python
-from hyperspell.types import DocumentStatus, DocumentListResponse
+from hyperspell.types import Document, DocumentStatus, DocumentStatusResponse
```
Methods:
-- client.documents.list(\*\*params) -> SyncCursorPage[DocumentListResponse]
+- client.documents.list(\*\*params) -> SyncCursorPage[Document]
- client.documents.add(\*\*params) -> DocumentStatus
+- client.documents.get(resource_id, \*, source) -> Document
+- client.documents.status() -> DocumentStatusResponse
- client.documents.upload(\*\*params) -> DocumentStatus
# Collections
diff --git a/pyproject.toml b/pyproject.toml
index 5e390d44..01599def 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "hyperspell"
-version = "0.13.0"
+version = "0.16.0"
description = "The official Python library for the hyperspell API"
dynamic = ["readme"]
license = "Apache-2.0"
diff --git a/src/hyperspell/_version.py b/src/hyperspell/_version.py
index 58ec2dd0..1d221945 100644
--- a/src/hyperspell/_version.py
+++ b/src/hyperspell/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "hyperspell"
-__version__ = "0.13.0" # x-release-please-version
+__version__ = "0.16.0" # x-release-please-version
diff --git a/src/hyperspell/resources/auth.py b/src/hyperspell/resources/auth.py
index c579a191..b9e17f87 100644
--- a/src/hyperspell/resources/auth.py
+++ b/src/hyperspell/resources/auth.py
@@ -2,6 +2,8 @@
from __future__ import annotations
+from typing import Optional
+
import httpx
from ..types import auth_user_token_params
@@ -65,6 +67,7 @@ def user_token(
self,
*,
user_id: str,
+ expires_in: Optional[str] | NotGiven = NOT_GIVEN,
# 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,
@@ -78,6 +81,8 @@ def user_token(
safely passed to your user-facing front-end.
Args:
+ expires_in: Token lifetime, e.g., '30m', '2h', '1d'. Defaults to 24 hours if not provided.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -88,7 +93,13 @@ def user_token(
"""
return self._post(
"/auth/user_token",
- body=maybe_transform({"user_id": user_id}, auth_user_token_params.AuthUserTokenParams),
+ body=maybe_transform(
+ {
+ "user_id": user_id,
+ "expires_in": expires_in,
+ },
+ auth_user_token_params.AuthUserTokenParams,
+ ),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -139,6 +150,7 @@ async def user_token(
self,
*,
user_id: str,
+ expires_in: Optional[str] | NotGiven = NOT_GIVEN,
# 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,
@@ -152,6 +164,8 @@ async def user_token(
safely passed to your user-facing front-end.
Args:
+ expires_in: Token lifetime, e.g., '30m', '2h', '1d'. Defaults to 24 hours if not provided.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -162,7 +176,13 @@ async def user_token(
"""
return await self._post(
"/auth/user_token",
- body=await async_maybe_transform({"user_id": user_id}, auth_user_token_params.AuthUserTokenParams),
+ body=await async_maybe_transform(
+ {
+ "user_id": user_id,
+ "expires_in": expires_in,
+ },
+ auth_user_token_params.AuthUserTokenParams,
+ ),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
diff --git a/src/hyperspell/resources/documents.py b/src/hyperspell/resources/documents.py
index 8b35d2e2..eda88282 100644
--- a/src/hyperspell/resources/documents.py
+++ b/src/hyperspell/resources/documents.py
@@ -4,6 +4,7 @@
from typing import Union, Mapping, Optional, cast
from datetime import datetime
+from typing_extensions import Literal
import httpx
@@ -20,8 +21,9 @@
)
from ..pagination import SyncCursorPage, AsyncCursorPage
from .._base_client import AsyncPaginator, make_request_options
+from ..types.document import Document
from ..types.document_status import DocumentStatus
-from ..types.document_list_response import DocumentListResponse
+from ..types.document_status_response import DocumentStatusResponse
__all__ = ["DocumentsResource", "AsyncDocumentsResource"]
@@ -52,13 +54,63 @@ def list(
collection: Optional[str] | NotGiven = NOT_GIVEN,
cursor: Optional[str] | NotGiven = NOT_GIVEN,
size: int | NotGiven = NOT_GIVEN,
+ source: Optional[
+ Literal[
+ "collections",
+ "web_crawler",
+ "notion",
+ "slack",
+ "google_calendar",
+ "reddit",
+ "box",
+ "google_drive",
+ "airtable",
+ "algolia",
+ "amplitude",
+ "asana",
+ "ashby",
+ "bamboohr",
+ "basecamp",
+ "bubbles",
+ "calendly",
+ "confluence",
+ "clickup",
+ "datadog",
+ "deel",
+ "discord",
+ "dropbox",
+ "exa",
+ "facebook",
+ "front",
+ "github",
+ "gitlab",
+ "google_docs",
+ "google_mail",
+ "google_sheet",
+ "hubspot",
+ "jira",
+ "linear",
+ "microsoft_teams",
+ "mixpanel",
+ "monday",
+ "outlook",
+ "perplexity",
+ "rippling",
+ "salesforce",
+ "segment",
+ "todoist",
+ "twitter",
+ "zoom",
+ ]
+ ]
+ | NotGiven = NOT_GIVEN,
# 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,
- ) -> SyncCursorPage[DocumentListResponse]:
+ ) -> SyncCursorPage[Document]:
"""This endpoint allows you to paginate through all documents in the index.
You can
@@ -67,6 +119,8 @@ def list(
Args:
collection: Filter documents by collection.
+ source: Filter documents by source.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -77,7 +131,7 @@ def list(
"""
return self._get_api_list(
"/documents/list",
- page=SyncCursorPage[DocumentListResponse],
+ page=SyncCursorPage[Document],
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -88,11 +142,12 @@ def list(
"collection": collection,
"cursor": cursor,
"size": size,
+ "source": source,
},
document_list_params.DocumentListParams,
),
),
- model=DocumentListResponse,
+ model=Document,
)
def add(
@@ -152,6 +207,110 @@ def add(
cast_to=DocumentStatus,
)
+ def get(
+ self,
+ resource_id: str,
+ *,
+ source: Literal[
+ "collections",
+ "web_crawler",
+ "notion",
+ "slack",
+ "google_calendar",
+ "reddit",
+ "box",
+ "google_drive",
+ "airtable",
+ "algolia",
+ "amplitude",
+ "asana",
+ "ashby",
+ "bamboohr",
+ "basecamp",
+ "bubbles",
+ "calendly",
+ "confluence",
+ "clickup",
+ "datadog",
+ "deel",
+ "discord",
+ "dropbox",
+ "exa",
+ "facebook",
+ "front",
+ "github",
+ "gitlab",
+ "google_docs",
+ "google_mail",
+ "google_sheet",
+ "hubspot",
+ "jira",
+ "linear",
+ "microsoft_teams",
+ "mixpanel",
+ "monday",
+ "outlook",
+ "perplexity",
+ "rippling",
+ "salesforce",
+ "segment",
+ "todoist",
+ "twitter",
+ "zoom",
+ ],
+ # 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,
+ ) -> Document:
+ """
+ Retrieves a document by provider and resource_id.
+
+ Args:
+ 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
+ """
+ if not source:
+ raise ValueError(f"Expected a non-empty value for `source` but received {source!r}")
+ if not resource_id:
+ raise ValueError(f"Expected a non-empty value for `resource_id` but received {resource_id!r}")
+ return self._get(
+ f"/documents/get/{source}/{resource_id}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=Document,
+ )
+
+ def status(
+ self,
+ *,
+ # 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,
+ ) -> DocumentStatusResponse:
+ """
+ This endpoint shows the indexing progress of documents, both by provider and
+ total.
+ """
+ return self._get(
+ "/documents/status",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=DocumentStatusResponse,
+ )
+
def upload(
self,
*,
@@ -232,13 +391,63 @@ def list(
collection: Optional[str] | NotGiven = NOT_GIVEN,
cursor: Optional[str] | NotGiven = NOT_GIVEN,
size: int | NotGiven = NOT_GIVEN,
+ source: Optional[
+ Literal[
+ "collections",
+ "web_crawler",
+ "notion",
+ "slack",
+ "google_calendar",
+ "reddit",
+ "box",
+ "google_drive",
+ "airtable",
+ "algolia",
+ "amplitude",
+ "asana",
+ "ashby",
+ "bamboohr",
+ "basecamp",
+ "bubbles",
+ "calendly",
+ "confluence",
+ "clickup",
+ "datadog",
+ "deel",
+ "discord",
+ "dropbox",
+ "exa",
+ "facebook",
+ "front",
+ "github",
+ "gitlab",
+ "google_docs",
+ "google_mail",
+ "google_sheet",
+ "hubspot",
+ "jira",
+ "linear",
+ "microsoft_teams",
+ "mixpanel",
+ "monday",
+ "outlook",
+ "perplexity",
+ "rippling",
+ "salesforce",
+ "segment",
+ "todoist",
+ "twitter",
+ "zoom",
+ ]
+ ]
+ | NotGiven = NOT_GIVEN,
# 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,
- ) -> AsyncPaginator[DocumentListResponse, AsyncCursorPage[DocumentListResponse]]:
+ ) -> AsyncPaginator[Document, AsyncCursorPage[Document]]:
"""This endpoint allows you to paginate through all documents in the index.
You can
@@ -247,6 +456,8 @@ def list(
Args:
collection: Filter documents by collection.
+ source: Filter documents by source.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -257,7 +468,7 @@ def list(
"""
return self._get_api_list(
"/documents/list",
- page=AsyncCursorPage[DocumentListResponse],
+ page=AsyncCursorPage[Document],
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -268,11 +479,12 @@ def list(
"collection": collection,
"cursor": cursor,
"size": size,
+ "source": source,
},
document_list_params.DocumentListParams,
),
),
- model=DocumentListResponse,
+ model=Document,
)
async def add(
@@ -332,6 +544,110 @@ async def add(
cast_to=DocumentStatus,
)
+ async def get(
+ self,
+ resource_id: str,
+ *,
+ source: Literal[
+ "collections",
+ "web_crawler",
+ "notion",
+ "slack",
+ "google_calendar",
+ "reddit",
+ "box",
+ "google_drive",
+ "airtable",
+ "algolia",
+ "amplitude",
+ "asana",
+ "ashby",
+ "bamboohr",
+ "basecamp",
+ "bubbles",
+ "calendly",
+ "confluence",
+ "clickup",
+ "datadog",
+ "deel",
+ "discord",
+ "dropbox",
+ "exa",
+ "facebook",
+ "front",
+ "github",
+ "gitlab",
+ "google_docs",
+ "google_mail",
+ "google_sheet",
+ "hubspot",
+ "jira",
+ "linear",
+ "microsoft_teams",
+ "mixpanel",
+ "monday",
+ "outlook",
+ "perplexity",
+ "rippling",
+ "salesforce",
+ "segment",
+ "todoist",
+ "twitter",
+ "zoom",
+ ],
+ # 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,
+ ) -> Document:
+ """
+ Retrieves a document by provider and resource_id.
+
+ Args:
+ 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
+ """
+ if not source:
+ raise ValueError(f"Expected a non-empty value for `source` but received {source!r}")
+ if not resource_id:
+ raise ValueError(f"Expected a non-empty value for `resource_id` but received {resource_id!r}")
+ return await self._get(
+ f"/documents/get/{source}/{resource_id}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=Document,
+ )
+
+ async def status(
+ self,
+ *,
+ # 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,
+ ) -> DocumentStatusResponse:
+ """
+ This endpoint shows the indexing progress of documents, both by provider and
+ total.
+ """
+ return await self._get(
+ "/documents/status",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=DocumentStatusResponse,
+ )
+
async def upload(
self,
*,
@@ -396,6 +712,12 @@ def __init__(self, documents: DocumentsResource) -> None:
self.add = to_raw_response_wrapper(
documents.add,
)
+ self.get = to_raw_response_wrapper(
+ documents.get,
+ )
+ self.status = to_raw_response_wrapper(
+ documents.status,
+ )
self.upload = to_raw_response_wrapper(
documents.upload,
)
@@ -411,6 +733,12 @@ def __init__(self, documents: AsyncDocumentsResource) -> None:
self.add = async_to_raw_response_wrapper(
documents.add,
)
+ self.get = async_to_raw_response_wrapper(
+ documents.get,
+ )
+ self.status = async_to_raw_response_wrapper(
+ documents.status,
+ )
self.upload = async_to_raw_response_wrapper(
documents.upload,
)
@@ -426,6 +754,12 @@ def __init__(self, documents: DocumentsResource) -> None:
self.add = to_streamed_response_wrapper(
documents.add,
)
+ self.get = to_streamed_response_wrapper(
+ documents.get,
+ )
+ self.status = to_streamed_response_wrapper(
+ documents.status,
+ )
self.upload = to_streamed_response_wrapper(
documents.upload,
)
@@ -441,6 +775,12 @@ def __init__(self, documents: AsyncDocumentsResource) -> None:
self.add = async_to_streamed_response_wrapper(
documents.add,
)
+ self.get = async_to_streamed_response_wrapper(
+ documents.get,
+ )
+ self.status = async_to_streamed_response_wrapper(
+ documents.status,
+ )
self.upload = async_to_streamed_response_wrapper(
documents.upload,
)
diff --git a/src/hyperspell/types/__init__.py b/src/hyperspell/types/__init__.py
index 178fb32e..4027566b 100644
--- a/src/hyperspell/types/__init__.py
+++ b/src/hyperspell/types/__init__.py
@@ -3,6 +3,7 @@
from __future__ import annotations
from .token import Token as Token
+from .document import Document as Document
from .document_status import DocumentStatus as DocumentStatus
from .auth_me_response import AuthMeResponse as AuthMeResponse
from .document_add_params import DocumentAddParams as DocumentAddParams
@@ -11,7 +12,7 @@
from .query_search_response import QuerySearchResponse as QuerySearchResponse
from .auth_user_token_params import AuthUserTokenParams as AuthUserTokenParams
from .collection_list_params import CollectionListParams as CollectionListParams
-from .document_list_response import DocumentListResponse as DocumentListResponse
from .document_upload_params import DocumentUploadParams as DocumentUploadParams
from .collection_list_response import CollectionListResponse as CollectionListResponse
+from .document_status_response import DocumentStatusResponse as DocumentStatusResponse
from .integration_revoke_response import IntegrationRevokeResponse as IntegrationRevokeResponse
diff --git a/src/hyperspell/types/auth_user_token_params.py b/src/hyperspell/types/auth_user_token_params.py
index b1e44fdc..fa7cc949 100644
--- a/src/hyperspell/types/auth_user_token_params.py
+++ b/src/hyperspell/types/auth_user_token_params.py
@@ -2,6 +2,7 @@
from __future__ import annotations
+from typing import Optional
from typing_extensions import Required, TypedDict
__all__ = ["AuthUserTokenParams"]
@@ -9,3 +10,6 @@
class AuthUserTokenParams(TypedDict, total=False):
user_id: Required[str]
+
+ expires_in: Optional[str]
+ """Token lifetime, e.g., '30m', '2h', '1d'. Defaults to 24 hours if not provided."""
diff --git a/src/hyperspell/types/document_list_response.py b/src/hyperspell/types/document.py
similarity index 78%
rename from src/hyperspell/types/document_list_response.py
rename to src/hyperspell/types/document.py
index de9f9bf8..69eab7b2 100644
--- a/src/hyperspell/types/document_list_response.py
+++ b/src/hyperspell/types/document.py
@@ -1,20 +1,30 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import TYPE_CHECKING, Optional
+from typing import TYPE_CHECKING, List, Optional
from datetime import datetime
from typing_extensions import Literal
from .._models import BaseModel
-__all__ = ["DocumentListResponse", "Metadata"]
+__all__ = ["Document", "Metadata", "MetadataEvent"]
+
+
+class MetadataEvent(BaseModel):
+ message: str
+
+ type: Literal["error", "warning", "info", "success"]
+
+ time: Optional[datetime] = None
class Metadata(BaseModel):
- created_at: Optional[datetime] = None
+ events: Optional[List[MetadataEvent]] = None
+
+ indexed_at: Optional[datetime] = None
last_modified: Optional[datetime] = None
- url: Optional[str] = None
+ status: Optional[Literal["pending", "processing", "completed", "failed"]] = None
if TYPE_CHECKING:
# Stub to indicate that arbitrary properties are accepted.
@@ -23,7 +33,7 @@ class Metadata(BaseModel):
def __getattr__(self, attr: str) -> object: ...
-class DocumentListResponse(BaseModel):
+class Document(BaseModel):
resource_id: str
source: Literal[
diff --git a/src/hyperspell/types/document_list_params.py b/src/hyperspell/types/document_list_params.py
index 6d142ffc..53440ca9 100644
--- a/src/hyperspell/types/document_list_params.py
+++ b/src/hyperspell/types/document_list_params.py
@@ -3,7 +3,7 @@
from __future__ import annotations
from typing import Optional
-from typing_extensions import TypedDict
+from typing_extensions import Literal, TypedDict
__all__ = ["DocumentListParams"]
@@ -15,3 +15,54 @@ class DocumentListParams(TypedDict, total=False):
cursor: Optional[str]
size: int
+
+ source: Optional[
+ Literal[
+ "collections",
+ "web_crawler",
+ "notion",
+ "slack",
+ "google_calendar",
+ "reddit",
+ "box",
+ "google_drive",
+ "airtable",
+ "algolia",
+ "amplitude",
+ "asana",
+ "ashby",
+ "bamboohr",
+ "basecamp",
+ "bubbles",
+ "calendly",
+ "confluence",
+ "clickup",
+ "datadog",
+ "deel",
+ "discord",
+ "dropbox",
+ "exa",
+ "facebook",
+ "front",
+ "github",
+ "gitlab",
+ "google_docs",
+ "google_mail",
+ "google_sheet",
+ "hubspot",
+ "jira",
+ "linear",
+ "microsoft_teams",
+ "mixpanel",
+ "monday",
+ "outlook",
+ "perplexity",
+ "rippling",
+ "salesforce",
+ "segment",
+ "todoist",
+ "twitter",
+ "zoom",
+ ]
+ ]
+ """Filter documents by source."""
diff --git a/src/hyperspell/types/document_status_response.py b/src/hyperspell/types/document_status_response.py
new file mode 100644
index 00000000..022be1c7
--- /dev/null
+++ b/src/hyperspell/types/document_status_response.py
@@ -0,0 +1,13 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Dict
+
+from .._models import BaseModel
+
+__all__ = ["DocumentStatusResponse"]
+
+
+class DocumentStatusResponse(BaseModel):
+ providers: Dict[str, Dict[str, int]]
+
+ total: Dict[str, int]
diff --git a/src/hyperspell/types/query_search_response.py b/src/hyperspell/types/query_search_response.py
index 498aa516..e02d76d4 100644
--- a/src/hyperspell/types/query_search_response.py
+++ b/src/hyperspell/types/query_search_response.py
@@ -1,83 +1,11 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import TYPE_CHECKING, Dict, List, Optional
-from datetime import datetime
-from typing_extensions import Literal
+from typing import Dict, List, Optional
from .._models import BaseModel
+from .document import Document
-__all__ = ["QuerySearchResponse", "Document", "DocumentMetadata"]
-
-
-class DocumentMetadata(BaseModel):
- created_at: Optional[datetime] = None
-
- last_modified: Optional[datetime] = None
-
- url: Optional[str] = None
-
- if TYPE_CHECKING:
- # Stub to indicate that arbitrary properties are accepted.
- # To access properties that are not valid identifiers you can use `getattr`, e.g.
- # `getattr(obj, '$type')`
- def __getattr__(self, attr: str) -> object: ...
-
-
-class Document(BaseModel):
- resource_id: str
-
- source: Literal[
- "collections",
- "web_crawler",
- "notion",
- "slack",
- "google_calendar",
- "reddit",
- "box",
- "google_drive",
- "airtable",
- "algolia",
- "amplitude",
- "asana",
- "ashby",
- "bamboohr",
- "basecamp",
- "bubbles",
- "calendly",
- "confluence",
- "clickup",
- "datadog",
- "deel",
- "discord",
- "dropbox",
- "exa",
- "facebook",
- "front",
- "github",
- "gitlab",
- "google_docs",
- "google_mail",
- "google_sheet",
- "hubspot",
- "jira",
- "linear",
- "microsoft_teams",
- "mixpanel",
- "monday",
- "outlook",
- "perplexity",
- "rippling",
- "salesforce",
- "segment",
- "todoist",
- "twitter",
- "zoom",
- ]
-
- metadata: Optional[DocumentMetadata] = None
-
- score: Optional[float] = None
- """The relevance of the resource to the query"""
+__all__ = ["QuerySearchResponse"]
class QuerySearchResponse(BaseModel):
diff --git a/tests/api_resources/test_auth.py b/tests/api_resources/test_auth.py
index a609ea76..e4207ba8 100644
--- a/tests/api_resources/test_auth.py
+++ b/tests/api_resources/test_auth.py
@@ -49,6 +49,14 @@ def test_method_user_token(self, client: Hyperspell) -> None:
)
assert_matches_type(Token, auth, path=["response"])
+ @parametrize
+ def test_method_user_token_with_all_params(self, client: Hyperspell) -> None:
+ auth = client.auth.user_token(
+ user_id="user_id",
+ expires_in="30m",
+ )
+ assert_matches_type(Token, auth, path=["response"])
+
@parametrize
def test_raw_response_user_token(self, client: Hyperspell) -> None:
response = client.auth.with_raw_response.user_token(
@@ -109,6 +117,14 @@ async def test_method_user_token(self, async_client: AsyncHyperspell) -> None:
)
assert_matches_type(Token, auth, path=["response"])
+ @parametrize
+ async def test_method_user_token_with_all_params(self, async_client: AsyncHyperspell) -> None:
+ auth = await async_client.auth.user_token(
+ user_id="user_id",
+ expires_in="30m",
+ )
+ assert_matches_type(Token, auth, path=["response"])
+
@parametrize
async def test_raw_response_user_token(self, async_client: AsyncHyperspell) -> None:
response = await async_client.auth.with_raw_response.user_token(
diff --git a/tests/api_resources/test_documents.py b/tests/api_resources/test_documents.py
index 37d3c95a..5f4260a5 100644
--- a/tests/api_resources/test_documents.py
+++ b/tests/api_resources/test_documents.py
@@ -10,8 +10,9 @@
from hyperspell import Hyperspell, AsyncHyperspell
from tests.utils import assert_matches_type
from hyperspell.types import (
+ Document,
DocumentStatus,
- DocumentListResponse,
+ DocumentStatusResponse,
)
from hyperspell._utils import parse_datetime
from hyperspell.pagination import SyncCursorPage, AsyncCursorPage
@@ -25,7 +26,7 @@ class TestDocuments:
@parametrize
def test_method_list(self, client: Hyperspell) -> None:
document = client.documents.list()
- assert_matches_type(SyncCursorPage[DocumentListResponse], document, path=["response"])
+ assert_matches_type(SyncCursorPage[Document], document, path=["response"])
@parametrize
def test_method_list_with_all_params(self, client: Hyperspell) -> None:
@@ -33,8 +34,9 @@ def test_method_list_with_all_params(self, client: Hyperspell) -> None:
collection="collection",
cursor="cursor",
size=0,
+ source="collections",
)
- assert_matches_type(SyncCursorPage[DocumentListResponse], document, path=["response"])
+ assert_matches_type(SyncCursorPage[Document], document, path=["response"])
@parametrize
def test_raw_response_list(self, client: Hyperspell) -> None:
@@ -43,7 +45,7 @@ def test_raw_response_list(self, client: Hyperspell) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
document = response.parse()
- assert_matches_type(SyncCursorPage[DocumentListResponse], document, path=["response"])
+ assert_matches_type(SyncCursorPage[Document], document, path=["response"])
@parametrize
def test_streaming_response_list(self, client: Hyperspell) -> None:
@@ -52,7 +54,7 @@ def test_streaming_response_list(self, client: Hyperspell) -> None:
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
document = response.parse()
- assert_matches_type(SyncCursorPage[DocumentListResponse], document, path=["response"])
+ assert_matches_type(SyncCursorPage[Document], document, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -97,6 +99,73 @@ def test_streaming_response_add(self, client: Hyperspell) -> None:
assert cast(Any, response.is_closed) is True
+ @parametrize
+ def test_method_get(self, client: Hyperspell) -> None:
+ document = client.documents.get(
+ resource_id="resource_id",
+ source="collections",
+ )
+ assert_matches_type(Document, document, path=["response"])
+
+ @parametrize
+ def test_raw_response_get(self, client: Hyperspell) -> None:
+ response = client.documents.with_raw_response.get(
+ resource_id="resource_id",
+ source="collections",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ document = response.parse()
+ assert_matches_type(Document, document, path=["response"])
+
+ @parametrize
+ def test_streaming_response_get(self, client: Hyperspell) -> None:
+ with client.documents.with_streaming_response.get(
+ resource_id="resource_id",
+ source="collections",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ document = response.parse()
+ assert_matches_type(Document, document, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_get(self, client: Hyperspell) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `resource_id` but received ''"):
+ client.documents.with_raw_response.get(
+ resource_id="",
+ source="collections",
+ )
+
+ @parametrize
+ def test_method_status(self, client: Hyperspell) -> None:
+ document = client.documents.status()
+ assert_matches_type(DocumentStatusResponse, document, path=["response"])
+
+ @parametrize
+ def test_raw_response_status(self, client: Hyperspell) -> None:
+ response = client.documents.with_raw_response.status()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ document = response.parse()
+ assert_matches_type(DocumentStatusResponse, document, path=["response"])
+
+ @parametrize
+ def test_streaming_response_status(self, client: Hyperspell) -> None:
+ with client.documents.with_streaming_response.status() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ document = response.parse()
+ assert_matches_type(DocumentStatusResponse, document, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@parametrize
def test_method_upload(self, client: Hyperspell) -> None:
document = client.documents.upload(
@@ -143,7 +212,7 @@ class TestAsyncDocuments:
@parametrize
async def test_method_list(self, async_client: AsyncHyperspell) -> None:
document = await async_client.documents.list()
- assert_matches_type(AsyncCursorPage[DocumentListResponse], document, path=["response"])
+ assert_matches_type(AsyncCursorPage[Document], document, path=["response"])
@parametrize
async def test_method_list_with_all_params(self, async_client: AsyncHyperspell) -> None:
@@ -151,8 +220,9 @@ async def test_method_list_with_all_params(self, async_client: AsyncHyperspell)
collection="collection",
cursor="cursor",
size=0,
+ source="collections",
)
- assert_matches_type(AsyncCursorPage[DocumentListResponse], document, path=["response"])
+ assert_matches_type(AsyncCursorPage[Document], document, path=["response"])
@parametrize
async def test_raw_response_list(self, async_client: AsyncHyperspell) -> None:
@@ -161,7 +231,7 @@ async def test_raw_response_list(self, async_client: AsyncHyperspell) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
document = await response.parse()
- assert_matches_type(AsyncCursorPage[DocumentListResponse], document, path=["response"])
+ assert_matches_type(AsyncCursorPage[Document], document, path=["response"])
@parametrize
async def test_streaming_response_list(self, async_client: AsyncHyperspell) -> None:
@@ -170,7 +240,7 @@ async def test_streaming_response_list(self, async_client: AsyncHyperspell) -> N
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
document = await response.parse()
- assert_matches_type(AsyncCursorPage[DocumentListResponse], document, path=["response"])
+ assert_matches_type(AsyncCursorPage[Document], document, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -215,6 +285,73 @@ async def test_streaming_response_add(self, async_client: AsyncHyperspell) -> No
assert cast(Any, response.is_closed) is True
+ @parametrize
+ async def test_method_get(self, async_client: AsyncHyperspell) -> None:
+ document = await async_client.documents.get(
+ resource_id="resource_id",
+ source="collections",
+ )
+ assert_matches_type(Document, document, path=["response"])
+
+ @parametrize
+ async def test_raw_response_get(self, async_client: AsyncHyperspell) -> None:
+ response = await async_client.documents.with_raw_response.get(
+ resource_id="resource_id",
+ source="collections",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ document = await response.parse()
+ assert_matches_type(Document, document, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_get(self, async_client: AsyncHyperspell) -> None:
+ async with async_client.documents.with_streaming_response.get(
+ resource_id="resource_id",
+ source="collections",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ document = await response.parse()
+ assert_matches_type(Document, document, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_get(self, async_client: AsyncHyperspell) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `resource_id` but received ''"):
+ await async_client.documents.with_raw_response.get(
+ resource_id="",
+ source="collections",
+ )
+
+ @parametrize
+ async def test_method_status(self, async_client: AsyncHyperspell) -> None:
+ document = await async_client.documents.status()
+ assert_matches_type(DocumentStatusResponse, document, path=["response"])
+
+ @parametrize
+ async def test_raw_response_status(self, async_client: AsyncHyperspell) -> None:
+ response = await async_client.documents.with_raw_response.status()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ document = await response.parse()
+ assert_matches_type(DocumentStatusResponse, document, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_status(self, async_client: AsyncHyperspell) -> None:
+ async with async_client.documents.with_streaming_response.status() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ document = await response.parse()
+ assert_matches_type(DocumentStatusResponse, document, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@parametrize
async def test_method_upload(self, async_client: AsyncHyperspell) -> None:
document = await async_client.documents.upload(