diff --git a/.stats.yml b/.stats.yml
index 1fd29914..05f0faf0 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1 +1 @@
-configured_endpoints: 41
+configured_endpoints: 36
diff --git a/README.md b/README.md
index 592361c0..f9e3bbc3 100644
--- a/README.md
+++ b/README.md
@@ -137,12 +137,12 @@ client = Hyperspell(
user_id="My User ID",
)
-all_context_documents = []
+all_entities = []
# Automatically fetches more pages as needed.
-for context_document in client.context_documents.list():
- # Do something with context_document here
- all_context_documents.append(context_document)
-print(all_context_documents)
+for entity in client.entities.list():
+ # Do something with entity here
+ all_entities.append(entity)
+print(all_entities)
```
Or, asynchronously:
@@ -157,11 +157,11 @@ client = AsyncHyperspell(
async def main() -> None:
- all_context_documents = []
+ all_entities = []
# Iterate through items across all pages, issuing requests as needed.
- async for context_document in client.context_documents.list():
- all_context_documents.append(context_document)
- print(all_context_documents)
+ async for entity in client.entities.list():
+ all_entities.append(entity)
+ print(all_entities)
asyncio.run(main())
@@ -170,11 +170,11 @@ asyncio.run(main())
Alternatively, you can use the `.has_next_page()`, `.next_page_info()`, or `.get_next_page()` methods for more granular control working with pages:
```python
-first_page = await client.context_documents.list()
+first_page = await client.entities.list()
if first_page.has_next_page():
print(f"will fetch next page using these details: {first_page.next_page_info()}")
next_page = await first_page.get_next_page()
- print(f"number of items we just fetched: {len(next_page.documents)}")
+ print(f"number of items we just fetched: {len(next_page.items)}")
# Remove `await` for non-async usage.
```
@@ -182,11 +182,11 @@ if first_page.has_next_page():
Or just work directly with the returned data:
```python
-first_page = await client.context_documents.list()
+first_page = await client.entities.list()
print(f"next page cursor: {first_page.next_cursor}") # => "next page cursor: ..."
-for context_document in first_page.documents:
- print(context_document.document_id)
+for entity in first_page.items:
+ print(entity.id)
# Remove `await` for non-async usage.
```
@@ -202,10 +202,11 @@ client = Hyperspell(
user_id="My User ID",
)
-config = client.context_documents.config.update(
- structure={},
+query_result = client.memories.search(
+ query="What does Hyperspell do?",
+ options={"filter": {}},
)
-print(config.structure)
+print(query_result.options)
```
## File uploads
diff --git a/api.md b/api.md
index d8e50312..6a83b1d1 100644
--- a/api.md
+++ b/api.md
@@ -108,74 +108,39 @@ Methods:
- client.integrations.web_crawler.index(\*\*params) -> WebCrawlerIndexResponse
-# ContextDocuments
+# Entities
Types:
```python
-from hyperspell.types import (
- ContextDocumentListResponse,
- ContextDocumentGenerateResponse,
- ContextDocumentGetResponse,
-)
-```
-
-Methods:
-
-- client.context_documents.list(\*\*params) -> SyncContextDocumentsCursorPage[ContextDocumentListResponse]
-- client.context_documents.generate(\*\*params) -> ContextDocumentGenerateResponse
-- client.context_documents.get(document_id) -> ContextDocumentGetResponse
-
-## Trees
-
-Types:
-
-```python
-from hyperspell.types.context_documents import (
- TreeGenerateResponse,
- TreeGetResponse,
- TreeGetLatestResponse,
- TreeProgressResponse,
-)
+from hyperspell.types import EntityListResponse, EntityGetResponse, EntitySearchResponse
```
Methods:
-- client.context_documents.trees.generate(\*\*params) -> TreeGenerateResponse
-- client.context_documents.trees.get(tree_id) -> TreeGetResponse
-- client.context_documents.trees.get_latest(\*\*params) -> TreeGetLatestResponse
-- client.context_documents.trees.progress(tree_id) -> TreeProgressResponse
+- client.entities.list(\*\*params) -> SyncEntityCursorPage[EntityListResponse]
+- client.entities.get(entity_id) -> EntityGetResponse
+- client.entities.search(\*\*params) -> EntitySearchResponse
-## Digests
+# Live
Types:
```python
-from hyperspell.types.context_documents import DigestListResponse, DigestGenerateResponse
-```
-
-Methods:
-
-- client.context_documents.digests.list(\*\*params) -> DigestListResponse
-- client.context_documents.digests.generate(\*\*params) -> DigestGenerateResponse
-
-## Config
-
-Types:
-
-```python
-from hyperspell.types.context_documents import (
- ConfigUpdateResponse,
- ConfigGetResponse,
- ConfigResetResponse,
+from hyperspell.types import (
+ LiveGetResourceResponse,
+ LiveListResourcesResponse,
+ LiveListSourcesResponse,
+ LiveSearchResponse,
)
```
Methods:
-- client.context_documents.config.update(\*\*params) -> ConfigUpdateResponse
-- client.context_documents.config.get() -> ConfigGetResponse
-- client.context_documents.config.reset() -> ConfigResetResponse
+- client.live.get_resource(resource_id, \*, source, \*\*params) -> LiveGetResourceResponse
+- client.live.list_resources(source, \*\*params) -> SyncCursorPage[LiveListResourcesResponse]
+- client.live.list_sources() -> LiveListSourcesResponse
+- client.live.search(source, \*\*params) -> LiveSearchResponse
# Memories
diff --git a/scripts/mock b/scripts/mock
index 342ec614..e71f87b5 100755
--- a/scripts/mock
+++ b/scripts/mock
@@ -11,7 +11,7 @@ elif [ -n "$STAINLESS_OPENAPI_SPEC_URL" ]; then
URL="$STAINLESS_OPENAPI_SPEC_URL"
else
# Embedded OpenAPI spec (base64-encoded, gzipped)
- EMBEDDED_SPEC="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"
+ EMBEDDED_SPEC="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"
SPEC_TMPFILE="$(mktemp)"
trap 'rm -f "$SPEC_TMPFILE"' EXIT
echo "$EMBEDDED_SPEC" | base64 --decode | gunzip > "$SPEC_TMPFILE"
diff --git a/src/hyperspell/_client.py b/src/hyperspell/_client.py
index d05ded7a..8303553f 100644
--- a/src/hyperspell/_client.py
+++ b/src/hyperspell/_client.py
@@ -37,26 +37,28 @@
if TYPE_CHECKING:
from .resources import (
auth,
+ live,
vaults,
actions,
folders,
+ entities,
evaluate,
memories,
sessions,
connections,
integrations,
- context_documents,
)
from .resources.auth import AuthResource, AsyncAuthResource
+ from .resources.live import LiveResource, AsyncLiveResource
from .resources.vaults import VaultsResource, AsyncVaultsResource
from .resources.actions import ActionsResource, AsyncActionsResource
from .resources.folders import FoldersResource, AsyncFoldersResource
+ from .resources.entities import EntitiesResource, AsyncEntitiesResource
from .resources.evaluate import EvaluateResource, AsyncEvaluateResource
from .resources.memories import MemoriesResource, AsyncMemoriesResource
from .resources.sessions import SessionsResource, AsyncSessionsResource
from .resources.connections import ConnectionsResource, AsyncConnectionsResource
from .resources.integrations.integrations import IntegrationsResource, AsyncIntegrationsResource
- from .resources.context_documents.context_documents import ContextDocumentsResource, AsyncContextDocumentsResource
__all__ = [
"Timeout",
@@ -157,10 +159,16 @@ def integrations(self) -> IntegrationsResource:
return IntegrationsResource(self)
@cached_property
- def context_documents(self) -> ContextDocumentsResource:
- from .resources.context_documents import ContextDocumentsResource
+ def entities(self) -> EntitiesResource:
+ from .resources.entities import EntitiesResource
- return ContextDocumentsResource(self)
+ return EntitiesResource(self)
+
+ @cached_property
+ def live(self) -> LiveResource:
+ from .resources.live import LiveResource
+
+ return LiveResource(self)
@cached_property
def memories(self) -> MemoriesResource:
@@ -401,10 +409,16 @@ def integrations(self) -> AsyncIntegrationsResource:
return AsyncIntegrationsResource(self)
@cached_property
- def context_documents(self) -> AsyncContextDocumentsResource:
- from .resources.context_documents import AsyncContextDocumentsResource
+ def entities(self) -> AsyncEntitiesResource:
+ from .resources.entities import AsyncEntitiesResource
- return AsyncContextDocumentsResource(self)
+ return AsyncEntitiesResource(self)
+
+ @cached_property
+ def live(self) -> AsyncLiveResource:
+ from .resources.live import AsyncLiveResource
+
+ return AsyncLiveResource(self)
@cached_property
def memories(self) -> AsyncMemoriesResource:
@@ -583,10 +597,16 @@ def integrations(self) -> integrations.IntegrationsResourceWithRawResponse:
return IntegrationsResourceWithRawResponse(self._client.integrations)
@cached_property
- def context_documents(self) -> context_documents.ContextDocumentsResourceWithRawResponse:
- from .resources.context_documents import ContextDocumentsResourceWithRawResponse
+ def entities(self) -> entities.EntitiesResourceWithRawResponse:
+ from .resources.entities import EntitiesResourceWithRawResponse
+
+ return EntitiesResourceWithRawResponse(self._client.entities)
+
+ @cached_property
+ def live(self) -> live.LiveResourceWithRawResponse:
+ from .resources.live import LiveResourceWithRawResponse
- return ContextDocumentsResourceWithRawResponse(self._client.context_documents)
+ return LiveResourceWithRawResponse(self._client.live)
@cached_property
def memories(self) -> memories.MemoriesResourceWithRawResponse:
@@ -650,10 +670,16 @@ def integrations(self) -> integrations.AsyncIntegrationsResourceWithRawResponse:
return AsyncIntegrationsResourceWithRawResponse(self._client.integrations)
@cached_property
- def context_documents(self) -> context_documents.AsyncContextDocumentsResourceWithRawResponse:
- from .resources.context_documents import AsyncContextDocumentsResourceWithRawResponse
+ def entities(self) -> entities.AsyncEntitiesResourceWithRawResponse:
+ from .resources.entities import AsyncEntitiesResourceWithRawResponse
- return AsyncContextDocumentsResourceWithRawResponse(self._client.context_documents)
+ return AsyncEntitiesResourceWithRawResponse(self._client.entities)
+
+ @cached_property
+ def live(self) -> live.AsyncLiveResourceWithRawResponse:
+ from .resources.live import AsyncLiveResourceWithRawResponse
+
+ return AsyncLiveResourceWithRawResponse(self._client.live)
@cached_property
def memories(self) -> memories.AsyncMemoriesResourceWithRawResponse:
@@ -717,10 +743,16 @@ def integrations(self) -> integrations.IntegrationsResourceWithStreamingResponse
return IntegrationsResourceWithStreamingResponse(self._client.integrations)
@cached_property
- def context_documents(self) -> context_documents.ContextDocumentsResourceWithStreamingResponse:
- from .resources.context_documents import ContextDocumentsResourceWithStreamingResponse
+ def entities(self) -> entities.EntitiesResourceWithStreamingResponse:
+ from .resources.entities import EntitiesResourceWithStreamingResponse
- return ContextDocumentsResourceWithStreamingResponse(self._client.context_documents)
+ return EntitiesResourceWithStreamingResponse(self._client.entities)
+
+ @cached_property
+ def live(self) -> live.LiveResourceWithStreamingResponse:
+ from .resources.live import LiveResourceWithStreamingResponse
+
+ return LiveResourceWithStreamingResponse(self._client.live)
@cached_property
def memories(self) -> memories.MemoriesResourceWithStreamingResponse:
@@ -784,10 +816,16 @@ def integrations(self) -> integrations.AsyncIntegrationsResourceWithStreamingRes
return AsyncIntegrationsResourceWithStreamingResponse(self._client.integrations)
@cached_property
- def context_documents(self) -> context_documents.AsyncContextDocumentsResourceWithStreamingResponse:
- from .resources.context_documents import AsyncContextDocumentsResourceWithStreamingResponse
+ def entities(self) -> entities.AsyncEntitiesResourceWithStreamingResponse:
+ from .resources.entities import AsyncEntitiesResourceWithStreamingResponse
+
+ return AsyncEntitiesResourceWithStreamingResponse(self._client.entities)
+
+ @cached_property
+ def live(self) -> live.AsyncLiveResourceWithStreamingResponse:
+ from .resources.live import AsyncLiveResourceWithStreamingResponse
- return AsyncContextDocumentsResourceWithStreamingResponse(self._client.context_documents)
+ return AsyncLiveResourceWithStreamingResponse(self._client.live)
@cached_property
def memories(self) -> memories.AsyncMemoriesResourceWithStreamingResponse:
diff --git a/src/hyperspell/pagination.py b/src/hyperspell/pagination.py
index 5da3aa10..919340cb 100644
--- a/src/hyperspell/pagination.py
+++ b/src/hyperspell/pagination.py
@@ -5,7 +5,7 @@
from ._base_client import BasePage, PageInfo, BaseSyncPage, BaseAsyncPage
-__all__ = ["SyncCursorPage", "AsyncCursorPage", "SyncContextDocumentsCursorPage", "AsyncContextDocumentsCursorPage"]
+__all__ = ["SyncCursorPage", "AsyncCursorPage", "SyncEntityCursorPage", "AsyncEntityCursorPage"]
_T = TypeVar("_T")
@@ -50,16 +50,16 @@ def next_page_info(self) -> Optional[PageInfo]:
return PageInfo(params={"cursor": next_cursor})
-class SyncContextDocumentsCursorPage(BaseSyncPage[_T], BasePage[_T], Generic[_T]):
- documents: List[_T]
+class SyncEntityCursorPage(BaseSyncPage[_T], BasePage[_T], Generic[_T]):
+ items: List[_T]
next_cursor: Optional[str] = None
@override
def _get_page_items(self) -> List[_T]:
- documents = self.documents
- if not documents:
+ items = self.items
+ if not items:
return []
- return documents
+ return items
@override
def next_page_info(self) -> Optional[PageInfo]:
@@ -70,16 +70,16 @@ def next_page_info(self) -> Optional[PageInfo]:
return PageInfo(params={"cursor": next_cursor})
-class AsyncContextDocumentsCursorPage(BaseAsyncPage[_T], BasePage[_T], Generic[_T]):
- documents: List[_T]
+class AsyncEntityCursorPage(BaseAsyncPage[_T], BasePage[_T], Generic[_T]):
+ items: List[_T]
next_cursor: Optional[str] = None
@override
def _get_page_items(self) -> List[_T]:
- documents = self.documents
- if not documents:
+ items = self.items
+ if not items:
return []
- return documents
+ return items
@override
def next_page_info(self) -> Optional[PageInfo]:
diff --git a/src/hyperspell/resources/__init__.py b/src/hyperspell/resources/__init__.py
index 2553e993..6ece35b7 100644
--- a/src/hyperspell/resources/__init__.py
+++ b/src/hyperspell/resources/__init__.py
@@ -8,6 +8,14 @@
AuthResourceWithStreamingResponse,
AsyncAuthResourceWithStreamingResponse,
)
+from .live import (
+ LiveResource,
+ AsyncLiveResource,
+ LiveResourceWithRawResponse,
+ AsyncLiveResourceWithRawResponse,
+ LiveResourceWithStreamingResponse,
+ AsyncLiveResourceWithStreamingResponse,
+)
from .vaults import (
VaultsResource,
AsyncVaultsResource,
@@ -32,6 +40,14 @@
FoldersResourceWithStreamingResponse,
AsyncFoldersResourceWithStreamingResponse,
)
+from .entities import (
+ EntitiesResource,
+ AsyncEntitiesResource,
+ EntitiesResourceWithRawResponse,
+ AsyncEntitiesResourceWithRawResponse,
+ EntitiesResourceWithStreamingResponse,
+ AsyncEntitiesResourceWithStreamingResponse,
+)
from .evaluate import (
EvaluateResource,
AsyncEvaluateResource,
@@ -72,14 +88,6 @@
IntegrationsResourceWithStreamingResponse,
AsyncIntegrationsResourceWithStreamingResponse,
)
-from .context_documents import (
- ContextDocumentsResource,
- AsyncContextDocumentsResource,
- ContextDocumentsResourceWithRawResponse,
- AsyncContextDocumentsResourceWithRawResponse,
- ContextDocumentsResourceWithStreamingResponse,
- AsyncContextDocumentsResourceWithStreamingResponse,
-)
__all__ = [
"ConnectionsResource",
@@ -100,12 +108,18 @@
"AsyncIntegrationsResourceWithRawResponse",
"IntegrationsResourceWithStreamingResponse",
"AsyncIntegrationsResourceWithStreamingResponse",
- "ContextDocumentsResource",
- "AsyncContextDocumentsResource",
- "ContextDocumentsResourceWithRawResponse",
- "AsyncContextDocumentsResourceWithRawResponse",
- "ContextDocumentsResourceWithStreamingResponse",
- "AsyncContextDocumentsResourceWithStreamingResponse",
+ "EntitiesResource",
+ "AsyncEntitiesResource",
+ "EntitiesResourceWithRawResponse",
+ "AsyncEntitiesResourceWithRawResponse",
+ "EntitiesResourceWithStreamingResponse",
+ "AsyncEntitiesResourceWithStreamingResponse",
+ "LiveResource",
+ "AsyncLiveResource",
+ "LiveResourceWithRawResponse",
+ "AsyncLiveResourceWithRawResponse",
+ "LiveResourceWithStreamingResponse",
+ "AsyncLiveResourceWithStreamingResponse",
"MemoriesResource",
"AsyncMemoriesResource",
"MemoriesResourceWithRawResponse",
diff --git a/src/hyperspell/resources/context_documents/__init__.py b/src/hyperspell/resources/context_documents/__init__.py
deleted file mode 100644
index 34942511..00000000
--- a/src/hyperspell/resources/context_documents/__init__.py
+++ /dev/null
@@ -1,61 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from .trees import (
- TreesResource,
- AsyncTreesResource,
- TreesResourceWithRawResponse,
- AsyncTreesResourceWithRawResponse,
- TreesResourceWithStreamingResponse,
- AsyncTreesResourceWithStreamingResponse,
-)
-from .config import (
- ConfigResource,
- AsyncConfigResource,
- ConfigResourceWithRawResponse,
- AsyncConfigResourceWithRawResponse,
- ConfigResourceWithStreamingResponse,
- AsyncConfigResourceWithStreamingResponse,
-)
-from .digests import (
- DigestsResource,
- AsyncDigestsResource,
- DigestsResourceWithRawResponse,
- AsyncDigestsResourceWithRawResponse,
- DigestsResourceWithStreamingResponse,
- AsyncDigestsResourceWithStreamingResponse,
-)
-from .context_documents import (
- ContextDocumentsResource,
- AsyncContextDocumentsResource,
- ContextDocumentsResourceWithRawResponse,
- AsyncContextDocumentsResourceWithRawResponse,
- ContextDocumentsResourceWithStreamingResponse,
- AsyncContextDocumentsResourceWithStreamingResponse,
-)
-
-__all__ = [
- "TreesResource",
- "AsyncTreesResource",
- "TreesResourceWithRawResponse",
- "AsyncTreesResourceWithRawResponse",
- "TreesResourceWithStreamingResponse",
- "AsyncTreesResourceWithStreamingResponse",
- "DigestsResource",
- "AsyncDigestsResource",
- "DigestsResourceWithRawResponse",
- "AsyncDigestsResourceWithRawResponse",
- "DigestsResourceWithStreamingResponse",
- "AsyncDigestsResourceWithStreamingResponse",
- "ConfigResource",
- "AsyncConfigResource",
- "ConfigResourceWithRawResponse",
- "AsyncConfigResourceWithRawResponse",
- "ConfigResourceWithStreamingResponse",
- "AsyncConfigResourceWithStreamingResponse",
- "ContextDocumentsResource",
- "AsyncContextDocumentsResource",
- "ContextDocumentsResourceWithRawResponse",
- "AsyncContextDocumentsResourceWithRawResponse",
- "ContextDocumentsResourceWithStreamingResponse",
- "AsyncContextDocumentsResourceWithStreamingResponse",
-]
diff --git a/src/hyperspell/resources/context_documents/config.py b/src/hyperspell/resources/context_documents/config.py
deleted file mode 100644
index 6078d950..00000000
--- a/src/hyperspell/resources/context_documents/config.py
+++ /dev/null
@@ -1,323 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Dict, Optional
-
-import httpx
-
-from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
-from ..._utils import maybe_transform, async_maybe_transform
-from ..._compat import cached_property
-from ..._resource import SyncAPIResource, AsyncAPIResource
-from ..._response import (
- to_raw_response_wrapper,
- to_streamed_response_wrapper,
- async_to_raw_response_wrapper,
- async_to_streamed_response_wrapper,
-)
-from ..._base_client import make_request_options
-from ...types.context_documents import config_update_params
-from ...types.context_documents.config_get_response import ConfigGetResponse
-from ...types.context_documents.config_reset_response import ConfigResetResponse
-from ...types.context_documents.config_update_response import ConfigUpdateResponse
-
-__all__ = ["ConfigResource", "AsyncConfigResource"]
-
-
-class ConfigResource(SyncAPIResource):
- @cached_property
- def with_raw_response(self) -> ConfigResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/hyperspell/python-sdk#accessing-raw-response-data-eg-headers
- """
- return ConfigResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> ConfigResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/hyperspell/python-sdk#with_streaming_response
- """
- return ConfigResourceWithStreamingResponse(self)
-
- def update(
- self,
- *,
- company_prompts: Optional[Dict[str, str]] | Omit = omit,
- detection_prompt: Optional[str] | Omit = omit,
- domain: Optional[str] | Omit = omit,
- personal_prompt: Optional[str] | Omit = omit,
- source_weights: Optional[Dict[str, str]] | Omit = omit,
- structure: Optional[config_update_params.Structure] | Omit = omit,
- workstream_prompts: Optional[Dict[str, 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,
- ) -> ConfigUpdateResponse:
- """Update the supplied generation settings.
-
- Changes apply to the next generation.
-
- This endpoint does not start a generation
- or modify existing context documents.
-
- Args:
- structure: Per-tier document definitions for custom generation.
-
- 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._patch(
- "/context-documents/config",
- body=maybe_transform(
- {
- "company_prompts": company_prompts,
- "detection_prompt": detection_prompt,
- "domain": domain,
- "personal_prompt": personal_prompt,
- "source_weights": source_weights,
- "structure": structure,
- "workstream_prompts": workstream_prompts,
- },
- config_update_params.ConfigUpdateParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=ConfigUpdateResponse,
- )
-
- def get(
- 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,
- ) -> ConfigGetResponse:
- """Read the customer-editable generation config for the authenticated app."""
- return self._get(
- "/context-documents/config",
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=ConfigGetResponse,
- )
-
- def reset(
- 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,
- ) -> ConfigResetResponse:
- """
- Reset customer-editable generation settings to their defaults.
-
- Existing context documents remain unchanged. `detected_domain` is retained and
- used for future generations unless a new domain override is set.
- """
- return self._post(
- "/context-documents/config/reset",
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=ConfigResetResponse,
- )
-
-
-class AsyncConfigResource(AsyncAPIResource):
- @cached_property
- def with_raw_response(self) -> AsyncConfigResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/hyperspell/python-sdk#accessing-raw-response-data-eg-headers
- """
- return AsyncConfigResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> AsyncConfigResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/hyperspell/python-sdk#with_streaming_response
- """
- return AsyncConfigResourceWithStreamingResponse(self)
-
- async def update(
- self,
- *,
- company_prompts: Optional[Dict[str, str]] | Omit = omit,
- detection_prompt: Optional[str] | Omit = omit,
- domain: Optional[str] | Omit = omit,
- personal_prompt: Optional[str] | Omit = omit,
- source_weights: Optional[Dict[str, str]] | Omit = omit,
- structure: Optional[config_update_params.Structure] | Omit = omit,
- workstream_prompts: Optional[Dict[str, 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,
- ) -> ConfigUpdateResponse:
- """Update the supplied generation settings.
-
- Changes apply to the next generation.
-
- This endpoint does not start a generation
- or modify existing context documents.
-
- Args:
- structure: Per-tier document definitions for custom generation.
-
- 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._patch(
- "/context-documents/config",
- body=await async_maybe_transform(
- {
- "company_prompts": company_prompts,
- "detection_prompt": detection_prompt,
- "domain": domain,
- "personal_prompt": personal_prompt,
- "source_weights": source_weights,
- "structure": structure,
- "workstream_prompts": workstream_prompts,
- },
- config_update_params.ConfigUpdateParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=ConfigUpdateResponse,
- )
-
- async def get(
- 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,
- ) -> ConfigGetResponse:
- """Read the customer-editable generation config for the authenticated app."""
- return await self._get(
- "/context-documents/config",
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=ConfigGetResponse,
- )
-
- async def reset(
- 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,
- ) -> ConfigResetResponse:
- """
- Reset customer-editable generation settings to their defaults.
-
- Existing context documents remain unchanged. `detected_domain` is retained and
- used for future generations unless a new domain override is set.
- """
- return await self._post(
- "/context-documents/config/reset",
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=ConfigResetResponse,
- )
-
-
-class ConfigResourceWithRawResponse:
- def __init__(self, config: ConfigResource) -> None:
- self._config = config
-
- self.update = to_raw_response_wrapper(
- config.update,
- )
- self.get = to_raw_response_wrapper(
- config.get,
- )
- self.reset = to_raw_response_wrapper(
- config.reset,
- )
-
-
-class AsyncConfigResourceWithRawResponse:
- def __init__(self, config: AsyncConfigResource) -> None:
- self._config = config
-
- self.update = async_to_raw_response_wrapper(
- config.update,
- )
- self.get = async_to_raw_response_wrapper(
- config.get,
- )
- self.reset = async_to_raw_response_wrapper(
- config.reset,
- )
-
-
-class ConfigResourceWithStreamingResponse:
- def __init__(self, config: ConfigResource) -> None:
- self._config = config
-
- self.update = to_streamed_response_wrapper(
- config.update,
- )
- self.get = to_streamed_response_wrapper(
- config.get,
- )
- self.reset = to_streamed_response_wrapper(
- config.reset,
- )
-
-
-class AsyncConfigResourceWithStreamingResponse:
- def __init__(self, config: AsyncConfigResource) -> None:
- self._config = config
-
- self.update = async_to_streamed_response_wrapper(
- config.update,
- )
- self.get = async_to_streamed_response_wrapper(
- config.get,
- )
- self.reset = async_to_streamed_response_wrapper(
- config.reset,
- )
diff --git a/src/hyperspell/resources/context_documents/context_documents.py b/src/hyperspell/resources/context_documents/context_documents.py
deleted file mode 100644
index ef19f965..00000000
--- a/src/hyperspell/resources/context_documents/context_documents.py
+++ /dev/null
@@ -1,491 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Optional
-from typing_extensions import Literal
-
-import httpx
-
-from .trees import (
- TreesResource,
- AsyncTreesResource,
- TreesResourceWithRawResponse,
- AsyncTreesResourceWithRawResponse,
- TreesResourceWithStreamingResponse,
- AsyncTreesResourceWithStreamingResponse,
-)
-from .config import (
- ConfigResource,
- AsyncConfigResource,
- ConfigResourceWithRawResponse,
- AsyncConfigResourceWithRawResponse,
- ConfigResourceWithStreamingResponse,
- AsyncConfigResourceWithStreamingResponse,
-)
-from ...types import context_document_list_params, context_document_generate_params
-from .digests import (
- DigestsResource,
- AsyncDigestsResource,
- DigestsResourceWithRawResponse,
- AsyncDigestsResourceWithRawResponse,
- DigestsResourceWithStreamingResponse,
- AsyncDigestsResourceWithStreamingResponse,
-)
-from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given
-from ..._utils import path_template, maybe_transform, async_maybe_transform
-from ..._compat import cached_property
-from ..._resource import SyncAPIResource, AsyncAPIResource
-from ..._response import (
- to_raw_response_wrapper,
- to_streamed_response_wrapper,
- async_to_raw_response_wrapper,
- async_to_streamed_response_wrapper,
-)
-from ...pagination import SyncContextDocumentsCursorPage, AsyncContextDocumentsCursorPage
-from ..._base_client import AsyncPaginator, make_request_options
-from ...types.context_document_get_response import ContextDocumentGetResponse
-from ...types.context_document_list_response import ContextDocumentListResponse
-from ...types.context_document_generate_response import ContextDocumentGenerateResponse
-
-__all__ = ["ContextDocumentsResource", "AsyncContextDocumentsResource"]
-
-
-class ContextDocumentsResource(SyncAPIResource):
- @cached_property
- def trees(self) -> TreesResource:
- return TreesResource(self._client)
-
- @cached_property
- def digests(self) -> DigestsResource:
- return DigestsResource(self._client)
-
- @cached_property
- def config(self) -> ConfigResource:
- return ConfigResource(self._client)
-
- @cached_property
- def with_raw_response(self) -> ContextDocumentsResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/hyperspell/python-sdk#accessing-raw-response-data-eg-headers
- """
- return ContextDocumentsResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> ContextDocumentsResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/hyperspell/python-sdk#with_streaming_response
- """
- return ContextDocumentsResourceWithStreamingResponse(self)
-
- def list(
- self,
- *,
- cursor: Optional[str] | Omit = omit,
- limit: int | Omit = omit,
- status: Optional[Literal["processing", "completed", "failed"]] | 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,
- ) -> SyncContextDocumentsCursorPage[ContextDocumentListResponse]:
- """
- List context documents for the authenticated app, most recent first.
-
- 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
- """
- return self._get_api_list(
- "/context-documents",
- page=SyncContextDocumentsCursorPage[ContextDocumentListResponse],
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=maybe_transform(
- {
- "cursor": cursor,
- "limit": limit,
- "status": status,
- },
- context_document_list_params.ContextDocumentListParams,
- ),
- ),
- model=ContextDocumentListResponse,
- )
-
- def generate(
- self,
- *,
- model: str | Omit = omit,
- prompt: Optional[str] | Omit = omit,
- sources: Optional[SequenceNotStr[str]] | Omit = omit,
- user_id: Optional[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,
- ) -> ContextDocumentGenerateResponse:
- """
- Generate an LLM-synthesized context document from the app's synced data.
-
- Generation runs asynchronously. The endpoint returns immediately with status
- `PROCESSING`; synthesis time depends on the amount of source data.
-
- Args:
- model: Model used for final synthesis.
-
- prompt: Custom prompt template. Replaces the standard summary prompt.
-
- sources: Integration sources to include (e.g., ['gmail', 'slack']). Defaults to all
- connected integrations.
-
- user_id: Scope generation to a specific user's data.
-
- 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(
- "/context-documents/generate",
- body=maybe_transform(
- {
- "model": model,
- "prompt": prompt,
- "sources": sources,
- "user_id": user_id,
- },
- context_document_generate_params.ContextDocumentGenerateParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=ContextDocumentGenerateResponse,
- )
-
- def get(
- self,
- document_id: str,
- *,
- # 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,
- ) -> ContextDocumentGetResponse:
- """
- Get a specific context document by 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 document_id:
- raise ValueError(f"Expected a non-empty value for `document_id` but received {document_id!r}")
- return self._get(
- path_template("/context-documents/{document_id}", document_id=document_id),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=ContextDocumentGetResponse,
- )
-
-
-class AsyncContextDocumentsResource(AsyncAPIResource):
- @cached_property
- def trees(self) -> AsyncTreesResource:
- return AsyncTreesResource(self._client)
-
- @cached_property
- def digests(self) -> AsyncDigestsResource:
- return AsyncDigestsResource(self._client)
-
- @cached_property
- def config(self) -> AsyncConfigResource:
- return AsyncConfigResource(self._client)
-
- @cached_property
- def with_raw_response(self) -> AsyncContextDocumentsResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/hyperspell/python-sdk#accessing-raw-response-data-eg-headers
- """
- return AsyncContextDocumentsResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> AsyncContextDocumentsResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/hyperspell/python-sdk#with_streaming_response
- """
- return AsyncContextDocumentsResourceWithStreamingResponse(self)
-
- def list(
- self,
- *,
- cursor: Optional[str] | Omit = omit,
- limit: int | Omit = omit,
- status: Optional[Literal["processing", "completed", "failed"]] | 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,
- ) -> AsyncPaginator[ContextDocumentListResponse, AsyncContextDocumentsCursorPage[ContextDocumentListResponse]]:
- """
- List context documents for the authenticated app, most recent first.
-
- 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
- """
- return self._get_api_list(
- "/context-documents",
- page=AsyncContextDocumentsCursorPage[ContextDocumentListResponse],
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=maybe_transform(
- {
- "cursor": cursor,
- "limit": limit,
- "status": status,
- },
- context_document_list_params.ContextDocumentListParams,
- ),
- ),
- model=ContextDocumentListResponse,
- )
-
- async def generate(
- self,
- *,
- model: str | Omit = omit,
- prompt: Optional[str] | Omit = omit,
- sources: Optional[SequenceNotStr[str]] | Omit = omit,
- user_id: Optional[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,
- ) -> ContextDocumentGenerateResponse:
- """
- Generate an LLM-synthesized context document from the app's synced data.
-
- Generation runs asynchronously. The endpoint returns immediately with status
- `PROCESSING`; synthesis time depends on the amount of source data.
-
- Args:
- model: Model used for final synthesis.
-
- prompt: Custom prompt template. Replaces the standard summary prompt.
-
- sources: Integration sources to include (e.g., ['gmail', 'slack']). Defaults to all
- connected integrations.
-
- user_id: Scope generation to a specific user's data.
-
- 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(
- "/context-documents/generate",
- body=await async_maybe_transform(
- {
- "model": model,
- "prompt": prompt,
- "sources": sources,
- "user_id": user_id,
- },
- context_document_generate_params.ContextDocumentGenerateParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=ContextDocumentGenerateResponse,
- )
-
- async def get(
- self,
- document_id: str,
- *,
- # 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,
- ) -> ContextDocumentGetResponse:
- """
- Get a specific context document by 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 document_id:
- raise ValueError(f"Expected a non-empty value for `document_id` but received {document_id!r}")
- return await self._get(
- path_template("/context-documents/{document_id}", document_id=document_id),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=ContextDocumentGetResponse,
- )
-
-
-class ContextDocumentsResourceWithRawResponse:
- def __init__(self, context_documents: ContextDocumentsResource) -> None:
- self._context_documents = context_documents
-
- self.list = to_raw_response_wrapper(
- context_documents.list,
- )
- self.generate = to_raw_response_wrapper(
- context_documents.generate,
- )
- self.get = to_raw_response_wrapper(
- context_documents.get,
- )
-
- @cached_property
- def trees(self) -> TreesResourceWithRawResponse:
- return TreesResourceWithRawResponse(self._context_documents.trees)
-
- @cached_property
- def digests(self) -> DigestsResourceWithRawResponse:
- return DigestsResourceWithRawResponse(self._context_documents.digests)
-
- @cached_property
- def config(self) -> ConfigResourceWithRawResponse:
- return ConfigResourceWithRawResponse(self._context_documents.config)
-
-
-class AsyncContextDocumentsResourceWithRawResponse:
- def __init__(self, context_documents: AsyncContextDocumentsResource) -> None:
- self._context_documents = context_documents
-
- self.list = async_to_raw_response_wrapper(
- context_documents.list,
- )
- self.generate = async_to_raw_response_wrapper(
- context_documents.generate,
- )
- self.get = async_to_raw_response_wrapper(
- context_documents.get,
- )
-
- @cached_property
- def trees(self) -> AsyncTreesResourceWithRawResponse:
- return AsyncTreesResourceWithRawResponse(self._context_documents.trees)
-
- @cached_property
- def digests(self) -> AsyncDigestsResourceWithRawResponse:
- return AsyncDigestsResourceWithRawResponse(self._context_documents.digests)
-
- @cached_property
- def config(self) -> AsyncConfigResourceWithRawResponse:
- return AsyncConfigResourceWithRawResponse(self._context_documents.config)
-
-
-class ContextDocumentsResourceWithStreamingResponse:
- def __init__(self, context_documents: ContextDocumentsResource) -> None:
- self._context_documents = context_documents
-
- self.list = to_streamed_response_wrapper(
- context_documents.list,
- )
- self.generate = to_streamed_response_wrapper(
- context_documents.generate,
- )
- self.get = to_streamed_response_wrapper(
- context_documents.get,
- )
-
- @cached_property
- def trees(self) -> TreesResourceWithStreamingResponse:
- return TreesResourceWithStreamingResponse(self._context_documents.trees)
-
- @cached_property
- def digests(self) -> DigestsResourceWithStreamingResponse:
- return DigestsResourceWithStreamingResponse(self._context_documents.digests)
-
- @cached_property
- def config(self) -> ConfigResourceWithStreamingResponse:
- return ConfigResourceWithStreamingResponse(self._context_documents.config)
-
-
-class AsyncContextDocumentsResourceWithStreamingResponse:
- def __init__(self, context_documents: AsyncContextDocumentsResource) -> None:
- self._context_documents = context_documents
-
- self.list = async_to_streamed_response_wrapper(
- context_documents.list,
- )
- self.generate = async_to_streamed_response_wrapper(
- context_documents.generate,
- )
- self.get = async_to_streamed_response_wrapper(
- context_documents.get,
- )
-
- @cached_property
- def trees(self) -> AsyncTreesResourceWithStreamingResponse:
- return AsyncTreesResourceWithStreamingResponse(self._context_documents.trees)
-
- @cached_property
- def digests(self) -> AsyncDigestsResourceWithStreamingResponse:
- return AsyncDigestsResourceWithStreamingResponse(self._context_documents.digests)
-
- @cached_property
- def config(self) -> AsyncConfigResourceWithStreamingResponse:
- return AsyncConfigResourceWithStreamingResponse(self._context_documents.config)
diff --git a/src/hyperspell/resources/context_documents/digests.py b/src/hyperspell/resources/context_documents/digests.py
deleted file mode 100644
index a3a983aa..00000000
--- a/src/hyperspell/resources/context_documents/digests.py
+++ /dev/null
@@ -1,319 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Union, Optional
-from datetime import datetime
-
-import httpx
-
-from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given
-from ..._utils import maybe_transform, async_maybe_transform
-from ..._compat import cached_property
-from ..._resource import SyncAPIResource, AsyncAPIResource
-from ..._response import (
- to_raw_response_wrapper,
- to_streamed_response_wrapper,
- async_to_raw_response_wrapper,
- async_to_streamed_response_wrapper,
-)
-from ..._base_client import make_request_options
-from ...types.context_documents import digest_list_params, digest_generate_params
-from ...types.context_documents.digest_list_response import DigestListResponse
-from ...types.context_documents.digest_generate_response import DigestGenerateResponse
-
-__all__ = ["DigestsResource", "AsyncDigestsResource"]
-
-
-class DigestsResource(SyncAPIResource):
- @cached_property
- def with_raw_response(self) -> DigestsResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/hyperspell/python-sdk#accessing-raw-response-data-eg-headers
- """
- return DigestsResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> DigestsResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/hyperspell/python-sdk#with_streaming_response
- """
- return DigestsResourceWithStreamingResponse(self)
-
- def list(
- self,
- *,
- limit: int | Omit = omit,
- period: Optional[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,
- ) -> DigestListResponse:
- """
- List recent digest summaries, newest first.
-
- Filter by cadence with `period=daily` or `period=weekly`. Fetch full content
- with `GET /context-documents/tree/by-id/{tree_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
- """
- return self._get(
- "/context-documents/digest/list",
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=maybe_transform(
- {
- "limit": limit,
- "period": period,
- },
- digest_list_params.DigestListParams,
- ),
- ),
- cast_to=DigestListResponse,
- )
-
- def generate(
- self,
- *,
- period: str | Omit = omit,
- sources: Optional[SequenceNotStr[str]] | Omit = omit,
- window_end: Union[str, datetime, None] | Omit = omit,
- window_start: Union[str, datetime, None] | 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,
- ) -> DigestGenerateResponse:
- """
- Generate a date-windowed "what the company did today" digest.
-
- Returns immediately with a tree ID. Poll
- `GET /context-documents/tree/{tree_id}/progress` for completion or fetch the
- result with `GET /context-documents/tree/by-id/{tree_id}`.
-
- Args:
- period: Digest cadence: 'daily' or 'weekly'. Sets the default window when none is given.
-
- sources: Integration sources to include (e.g., ['slack', 'github']). Defaults to all.
-
- window_end: Exclusive upper bound of the digest window. Defaults to now.
-
- window_start: Inclusive lower bound of the digest window. Defaults to midnight UTC today
- (paired with window_end=now) when omitted. Both bounds must be supplied
- together.
-
- 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(
- "/context-documents/digest",
- body=maybe_transform(
- {
- "period": period,
- "sources": sources,
- "window_end": window_end,
- "window_start": window_start,
- },
- digest_generate_params.DigestGenerateParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=DigestGenerateResponse,
- )
-
-
-class AsyncDigestsResource(AsyncAPIResource):
- @cached_property
- def with_raw_response(self) -> AsyncDigestsResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/hyperspell/python-sdk#accessing-raw-response-data-eg-headers
- """
- return AsyncDigestsResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> AsyncDigestsResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/hyperspell/python-sdk#with_streaming_response
- """
- return AsyncDigestsResourceWithStreamingResponse(self)
-
- async def list(
- self,
- *,
- limit: int | Omit = omit,
- period: Optional[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,
- ) -> DigestListResponse:
- """
- List recent digest summaries, newest first.
-
- Filter by cadence with `period=daily` or `period=weekly`. Fetch full content
- with `GET /context-documents/tree/by-id/{tree_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
- """
- return await self._get(
- "/context-documents/digest/list",
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=await async_maybe_transform(
- {
- "limit": limit,
- "period": period,
- },
- digest_list_params.DigestListParams,
- ),
- ),
- cast_to=DigestListResponse,
- )
-
- async def generate(
- self,
- *,
- period: str | Omit = omit,
- sources: Optional[SequenceNotStr[str]] | Omit = omit,
- window_end: Union[str, datetime, None] | Omit = omit,
- window_start: Union[str, datetime, None] | 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,
- ) -> DigestGenerateResponse:
- """
- Generate a date-windowed "what the company did today" digest.
-
- Returns immediately with a tree ID. Poll
- `GET /context-documents/tree/{tree_id}/progress` for completion or fetch the
- result with `GET /context-documents/tree/by-id/{tree_id}`.
-
- Args:
- period: Digest cadence: 'daily' or 'weekly'. Sets the default window when none is given.
-
- sources: Integration sources to include (e.g., ['slack', 'github']). Defaults to all.
-
- window_end: Exclusive upper bound of the digest window. Defaults to now.
-
- window_start: Inclusive lower bound of the digest window. Defaults to midnight UTC today
- (paired with window_end=now) when omitted. Both bounds must be supplied
- together.
-
- 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(
- "/context-documents/digest",
- body=await async_maybe_transform(
- {
- "period": period,
- "sources": sources,
- "window_end": window_end,
- "window_start": window_start,
- },
- digest_generate_params.DigestGenerateParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=DigestGenerateResponse,
- )
-
-
-class DigestsResourceWithRawResponse:
- def __init__(self, digests: DigestsResource) -> None:
- self._digests = digests
-
- self.list = to_raw_response_wrapper(
- digests.list,
- )
- self.generate = to_raw_response_wrapper(
- digests.generate,
- )
-
-
-class AsyncDigestsResourceWithRawResponse:
- def __init__(self, digests: AsyncDigestsResource) -> None:
- self._digests = digests
-
- self.list = async_to_raw_response_wrapper(
- digests.list,
- )
- self.generate = async_to_raw_response_wrapper(
- digests.generate,
- )
-
-
-class DigestsResourceWithStreamingResponse:
- def __init__(self, digests: DigestsResource) -> None:
- self._digests = digests
-
- self.list = to_streamed_response_wrapper(
- digests.list,
- )
- self.generate = to_streamed_response_wrapper(
- digests.generate,
- )
-
-
-class AsyncDigestsResourceWithStreamingResponse:
- def __init__(self, digests: AsyncDigestsResource) -> None:
- self._digests = digests
-
- self.list = async_to_streamed_response_wrapper(
- digests.list,
- )
- self.generate = async_to_streamed_response_wrapper(
- digests.generate,
- )
diff --git a/src/hyperspell/resources/context_documents/trees.py b/src/hyperspell/resources/context_documents/trees.py
deleted file mode 100644
index 3ae75cf3..00000000
--- a/src/hyperspell/resources/context_documents/trees.py
+++ /dev/null
@@ -1,470 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Optional
-
-import httpx
-
-from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given
-from ..._utils import path_template, maybe_transform, async_maybe_transform
-from ..._compat import cached_property
-from ..._resource import SyncAPIResource, AsyncAPIResource
-from ..._response import (
- to_raw_response_wrapper,
- to_streamed_response_wrapper,
- async_to_raw_response_wrapper,
- async_to_streamed_response_wrapper,
-)
-from ..._base_client import make_request_options
-from ...types.context_documents import tree_generate_params, tree_get_latest_params
-from ...types.context_documents.tree_get_response import TreeGetResponse
-from ...types.context_documents.tree_generate_response import TreeGenerateResponse
-from ...types.context_documents.tree_progress_response import TreeProgressResponse
-from ...types.context_documents.tree_get_latest_response import TreeGetLatestResponse
-
-__all__ = ["TreesResource", "AsyncTreesResource"]
-
-
-class TreesResource(SyncAPIResource):
- @cached_property
- def with_raw_response(self) -> TreesResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/hyperspell/python-sdk#accessing-raw-response-data-eg-headers
- """
- return TreesResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> TreesResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/hyperspell/python-sdk#with_streaming_response
- """
- return TreesResourceWithStreamingResponse(self)
-
- def generate(
- self,
- *,
- sources: Optional[SequenceNotStr[str]] | Omit = omit,
- user_id: Optional[str] | Omit = omit,
- workstream_name: Optional[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,
- ) -> TreeGenerateResponse:
- """
- Generate a three-tier context document tree for local push delivery.
-
- Creates company, workstream, and personal context documents from the app's
- synced data. Returns immediately with a tree ID; use
- `GET /context-documents/tree/latest` to retrieve the result.
-
- Args:
- sources: Integration sources to include (e.g., ['gmail', 'slack']). Defaults to all.
-
- user_id: User ID for personal tier scoping. When set, personal/context.md is generated
- from this user's data only. Company and workstream tiers still use all data.
-
- workstream_name: Generate docs for this workstream only (skip auto-detection).
-
- 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(
- "/context-documents/tree",
- body=maybe_transform(
- {
- "sources": sources,
- "user_id": user_id,
- "workstream_name": workstream_name,
- },
- tree_generate_params.TreeGenerateParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=TreeGenerateResponse,
- )
-
- def get(
- self,
- tree_id: str,
- *,
- # 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,
- ) -> TreeGetResponse:
- """
- Fetch a specific tree by its tree ID instead of selecting the latest one.
-
- 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 tree_id:
- raise ValueError(f"Expected a non-empty value for `tree_id` but received {tree_id!r}")
- return self._get(
- path_template("/context-documents/tree/by-id/{tree_id}", tree_id=tree_id),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=TreeGetResponse,
- )
-
- def get_latest(
- self,
- *,
- status: Optional[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,
- ) -> TreeGetLatestResponse:
- """
- Get the most recent context document tree for the authenticated app.
-
- By default, the endpoint returns the latest ready tree. Readiness depends on
- whether the app has `require_review` enabled:
-
- - `require_review=False` (default): return the latest completed tree.
- - `require_review=True`: return the latest published tree.
-
- `status` filters to a specific status (case-insensitive). When no ready tree
- exists yet, the endpoint returns the newest available generation state.
-
- 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
- """
- return self._get(
- "/context-documents/tree/latest",
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=maybe_transform({"status": status}, tree_get_latest_params.TreeGetLatestParams),
- ),
- cast_to=TreeGetLatestResponse,
- )
-
- def progress(
- self,
- tree_id: str,
- *,
- # 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,
- ) -> TreeProgressResponse:
- """
- Return the generation progress for a single tree.
-
- Active generations include phase and counter data. Completed generations, and
- generations without detailed progress data, return status only.
-
- 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 tree_id:
- raise ValueError(f"Expected a non-empty value for `tree_id` but received {tree_id!r}")
- return self._get(
- path_template("/context-documents/tree/{tree_id}/progress", tree_id=tree_id),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=TreeProgressResponse,
- )
-
-
-class AsyncTreesResource(AsyncAPIResource):
- @cached_property
- def with_raw_response(self) -> AsyncTreesResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/hyperspell/python-sdk#accessing-raw-response-data-eg-headers
- """
- return AsyncTreesResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> AsyncTreesResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/hyperspell/python-sdk#with_streaming_response
- """
- return AsyncTreesResourceWithStreamingResponse(self)
-
- async def generate(
- self,
- *,
- sources: Optional[SequenceNotStr[str]] | Omit = omit,
- user_id: Optional[str] | Omit = omit,
- workstream_name: Optional[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,
- ) -> TreeGenerateResponse:
- """
- Generate a three-tier context document tree for local push delivery.
-
- Creates company, workstream, and personal context documents from the app's
- synced data. Returns immediately with a tree ID; use
- `GET /context-documents/tree/latest` to retrieve the result.
-
- Args:
- sources: Integration sources to include (e.g., ['gmail', 'slack']). Defaults to all.
-
- user_id: User ID for personal tier scoping. When set, personal/context.md is generated
- from this user's data only. Company and workstream tiers still use all data.
-
- workstream_name: Generate docs for this workstream only (skip auto-detection).
-
- 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(
- "/context-documents/tree",
- body=await async_maybe_transform(
- {
- "sources": sources,
- "user_id": user_id,
- "workstream_name": workstream_name,
- },
- tree_generate_params.TreeGenerateParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=TreeGenerateResponse,
- )
-
- async def get(
- self,
- tree_id: str,
- *,
- # 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,
- ) -> TreeGetResponse:
- """
- Fetch a specific tree by its tree ID instead of selecting the latest one.
-
- 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 tree_id:
- raise ValueError(f"Expected a non-empty value for `tree_id` but received {tree_id!r}")
- return await self._get(
- path_template("/context-documents/tree/by-id/{tree_id}", tree_id=tree_id),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=TreeGetResponse,
- )
-
- async def get_latest(
- self,
- *,
- status: Optional[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,
- ) -> TreeGetLatestResponse:
- """
- Get the most recent context document tree for the authenticated app.
-
- By default, the endpoint returns the latest ready tree. Readiness depends on
- whether the app has `require_review` enabled:
-
- - `require_review=False` (default): return the latest completed tree.
- - `require_review=True`: return the latest published tree.
-
- `status` filters to a specific status (case-insensitive). When no ready tree
- exists yet, the endpoint returns the newest available generation state.
-
- 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
- """
- return await self._get(
- "/context-documents/tree/latest",
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=await async_maybe_transform({"status": status}, tree_get_latest_params.TreeGetLatestParams),
- ),
- cast_to=TreeGetLatestResponse,
- )
-
- async def progress(
- self,
- tree_id: str,
- *,
- # 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,
- ) -> TreeProgressResponse:
- """
- Return the generation progress for a single tree.
-
- Active generations include phase and counter data. Completed generations, and
- generations without detailed progress data, return status only.
-
- 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 tree_id:
- raise ValueError(f"Expected a non-empty value for `tree_id` but received {tree_id!r}")
- return await self._get(
- path_template("/context-documents/tree/{tree_id}/progress", tree_id=tree_id),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=TreeProgressResponse,
- )
-
-
-class TreesResourceWithRawResponse:
- def __init__(self, trees: TreesResource) -> None:
- self._trees = trees
-
- self.generate = to_raw_response_wrapper(
- trees.generate,
- )
- self.get = to_raw_response_wrapper(
- trees.get,
- )
- self.get_latest = to_raw_response_wrapper(
- trees.get_latest,
- )
- self.progress = to_raw_response_wrapper(
- trees.progress,
- )
-
-
-class AsyncTreesResourceWithRawResponse:
- def __init__(self, trees: AsyncTreesResource) -> None:
- self._trees = trees
-
- self.generate = async_to_raw_response_wrapper(
- trees.generate,
- )
- self.get = async_to_raw_response_wrapper(
- trees.get,
- )
- self.get_latest = async_to_raw_response_wrapper(
- trees.get_latest,
- )
- self.progress = async_to_raw_response_wrapper(
- trees.progress,
- )
-
-
-class TreesResourceWithStreamingResponse:
- def __init__(self, trees: TreesResource) -> None:
- self._trees = trees
-
- self.generate = to_streamed_response_wrapper(
- trees.generate,
- )
- self.get = to_streamed_response_wrapper(
- trees.get,
- )
- self.get_latest = to_streamed_response_wrapper(
- trees.get_latest,
- )
- self.progress = to_streamed_response_wrapper(
- trees.progress,
- )
-
-
-class AsyncTreesResourceWithStreamingResponse:
- def __init__(self, trees: AsyncTreesResource) -> None:
- self._trees = trees
-
- self.generate = async_to_streamed_response_wrapper(
- trees.generate,
- )
- self.get = async_to_streamed_response_wrapper(
- trees.get,
- )
- self.get_latest = async_to_streamed_response_wrapper(
- trees.get_latest,
- )
- self.progress = async_to_streamed_response_wrapper(
- trees.progress,
- )
diff --git a/src/hyperspell/resources/entities.py b/src/hyperspell/resources/entities.py
new file mode 100644
index 00000000..995157fb
--- /dev/null
+++ b/src/hyperspell/resources/entities.py
@@ -0,0 +1,405 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Optional
+from typing_extensions import Literal
+
+import httpx
+
+from ..types import entity_list_params, entity_search_params
+from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
+from .._utils import path_template, maybe_transform, async_maybe_transform
+from .._compat import cached_property
+from .._resource import SyncAPIResource, AsyncAPIResource
+from .._response import (
+ to_raw_response_wrapper,
+ to_streamed_response_wrapper,
+ async_to_raw_response_wrapper,
+ async_to_streamed_response_wrapper,
+)
+from ..pagination import SyncEntityCursorPage, AsyncEntityCursorPage
+from .._base_client import AsyncPaginator, make_request_options
+from ..types.entity_get_response import EntityGetResponse
+from ..types.entity_list_response import EntityListResponse
+from ..types.entity_search_response import EntitySearchResponse
+
+__all__ = ["EntitiesResource", "AsyncEntitiesResource"]
+
+
+class EntitiesResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> EntitiesResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/hyperspell/python-sdk#accessing-raw-response-data-eg-headers
+ """
+ return EntitiesResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> EntitiesResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/hyperspell/python-sdk#with_streaming_response
+ """
+ return EntitiesResourceWithStreamingResponse(self)
+
+ def list(
+ self,
+ *,
+ cursor: Optional[str] | Omit = omit,
+ limit: int | Omit = omit,
+ min_supporting_documents: Optional[int] | Omit = omit,
+ name_prefix: Optional[str] | Omit = omit,
+ search: Optional[str] | Omit = omit,
+ sort_by: Literal["id", "name", "type", "prominence"] | Omit = omit,
+ sort_dir: Literal["asc", "desc"] | Omit = omit,
+ status: Optional[Literal["provisional", "confirmed"]] | Omit = omit,
+ type: Optional[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,
+ ) -> SyncEntityCursorPage[EntityListResponse]:
+ """
+ List entities available to the current app.
+
+ Results can be filtered by type, status, name, and supporting-document count.
+ Use the returned cursor to retrieve the next page.
+
+ Args:
+ status: How strongly the entity's current identity has been established.
+
+ 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._get_api_list(
+ "/entities",
+ page=SyncEntityCursorPage[EntityListResponse],
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "cursor": cursor,
+ "limit": limit,
+ "min_supporting_documents": min_supporting_documents,
+ "name_prefix": name_prefix,
+ "search": search,
+ "sort_by": sort_by,
+ "sort_dir": sort_dir,
+ "status": status,
+ "type": type,
+ },
+ entity_list_params.EntityListParams,
+ ),
+ ),
+ model=EntityListResponse,
+ )
+
+ def get(
+ self,
+ entity_id: str,
+ *,
+ # 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,
+ ) -> EntityGetResponse:
+ """
+ Fetch a single entity belonging to the current app.
+
+ Returns 404 when the entity does not exist or is not visible to the app.
+
+ 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 entity_id:
+ raise ValueError(f"Expected a non-empty value for `entity_id` but received {entity_id!r}")
+ return self._get(
+ path_template("/entities/{entity_id}", entity_id=entity_id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=EntityGetResponse,
+ )
+
+ def search(
+ self,
+ *,
+ query: str,
+ limit: int | Omit = omit,
+ type: Optional[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,
+ ) -> EntitySearchResponse:
+ """
+ Search the current app's entities by meaning.
+
+ 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
+ """
+ return self._post(
+ "/entities/search",
+ body=maybe_transform(
+ {
+ "query": query,
+ "limit": limit,
+ "type": type,
+ },
+ entity_search_params.EntitySearchParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=EntitySearchResponse,
+ )
+
+
+class AsyncEntitiesResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncEntitiesResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/hyperspell/python-sdk#accessing-raw-response-data-eg-headers
+ """
+ return AsyncEntitiesResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncEntitiesResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/hyperspell/python-sdk#with_streaming_response
+ """
+ return AsyncEntitiesResourceWithStreamingResponse(self)
+
+ def list(
+ self,
+ *,
+ cursor: Optional[str] | Omit = omit,
+ limit: int | Omit = omit,
+ min_supporting_documents: Optional[int] | Omit = omit,
+ name_prefix: Optional[str] | Omit = omit,
+ search: Optional[str] | Omit = omit,
+ sort_by: Literal["id", "name", "type", "prominence"] | Omit = omit,
+ sort_dir: Literal["asc", "desc"] | Omit = omit,
+ status: Optional[Literal["provisional", "confirmed"]] | Omit = omit,
+ type: Optional[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,
+ ) -> AsyncPaginator[EntityListResponse, AsyncEntityCursorPage[EntityListResponse]]:
+ """
+ List entities available to the current app.
+
+ Results can be filtered by type, status, name, and supporting-document count.
+ Use the returned cursor to retrieve the next page.
+
+ Args:
+ status: How strongly the entity's current identity has been established.
+
+ 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._get_api_list(
+ "/entities",
+ page=AsyncEntityCursorPage[EntityListResponse],
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "cursor": cursor,
+ "limit": limit,
+ "min_supporting_documents": min_supporting_documents,
+ "name_prefix": name_prefix,
+ "search": search,
+ "sort_by": sort_by,
+ "sort_dir": sort_dir,
+ "status": status,
+ "type": type,
+ },
+ entity_list_params.EntityListParams,
+ ),
+ ),
+ model=EntityListResponse,
+ )
+
+ async def get(
+ self,
+ entity_id: str,
+ *,
+ # 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,
+ ) -> EntityGetResponse:
+ """
+ Fetch a single entity belonging to the current app.
+
+ Returns 404 when the entity does not exist or is not visible to the app.
+
+ 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 entity_id:
+ raise ValueError(f"Expected a non-empty value for `entity_id` but received {entity_id!r}")
+ return await self._get(
+ path_template("/entities/{entity_id}", entity_id=entity_id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=EntityGetResponse,
+ )
+
+ async def search(
+ self,
+ *,
+ query: str,
+ limit: int | Omit = omit,
+ type: Optional[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,
+ ) -> EntitySearchResponse:
+ """
+ Search the current app's entities by meaning.
+
+ 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
+ """
+ return await self._post(
+ "/entities/search",
+ body=await async_maybe_transform(
+ {
+ "query": query,
+ "limit": limit,
+ "type": type,
+ },
+ entity_search_params.EntitySearchParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=EntitySearchResponse,
+ )
+
+
+class EntitiesResourceWithRawResponse:
+ def __init__(self, entities: EntitiesResource) -> None:
+ self._entities = entities
+
+ self.list = to_raw_response_wrapper(
+ entities.list,
+ )
+ self.get = to_raw_response_wrapper(
+ entities.get,
+ )
+ self.search = to_raw_response_wrapper(
+ entities.search,
+ )
+
+
+class AsyncEntitiesResourceWithRawResponse:
+ def __init__(self, entities: AsyncEntitiesResource) -> None:
+ self._entities = entities
+
+ self.list = async_to_raw_response_wrapper(
+ entities.list,
+ )
+ self.get = async_to_raw_response_wrapper(
+ entities.get,
+ )
+ self.search = async_to_raw_response_wrapper(
+ entities.search,
+ )
+
+
+class EntitiesResourceWithStreamingResponse:
+ def __init__(self, entities: EntitiesResource) -> None:
+ self._entities = entities
+
+ self.list = to_streamed_response_wrapper(
+ entities.list,
+ )
+ self.get = to_streamed_response_wrapper(
+ entities.get,
+ )
+ self.search = to_streamed_response_wrapper(
+ entities.search,
+ )
+
+
+class AsyncEntitiesResourceWithStreamingResponse:
+ def __init__(self, entities: AsyncEntitiesResource) -> None:
+ self._entities = entities
+
+ self.list = async_to_streamed_response_wrapper(
+ entities.list,
+ )
+ self.get = async_to_streamed_response_wrapper(
+ entities.get,
+ )
+ self.search = async_to_streamed_response_wrapper(
+ entities.search,
+ )
diff --git a/src/hyperspell/resources/live.py b/src/hyperspell/resources/live.py
new file mode 100644
index 00000000..027642e2
--- /dev/null
+++ b/src/hyperspell/resources/live.py
@@ -0,0 +1,716 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Optional
+from typing_extensions import Literal
+
+import httpx
+
+from ..types import live_search_params, live_get_resource_params, live_list_resources_params
+from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
+from .._utils import path_template, maybe_transform, async_maybe_transform
+from .._compat import cached_property
+from .._resource import SyncAPIResource, AsyncAPIResource
+from .._response import (
+ to_raw_response_wrapper,
+ to_streamed_response_wrapper,
+ async_to_raw_response_wrapper,
+ async_to_streamed_response_wrapper,
+)
+from ..pagination import SyncCursorPage, AsyncCursorPage
+from .._base_client import AsyncPaginator, make_request_options
+from ..types.live_search_response import LiveSearchResponse
+from ..types.live_get_resource_response import LiveGetResourceResponse
+from ..types.live_list_sources_response import LiveListSourcesResponse
+from ..types.live_list_resources_response import LiveListResourcesResponse
+
+__all__ = ["LiveResource", "AsyncLiveResource"]
+
+
+class LiveResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> LiveResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/hyperspell/python-sdk#accessing-raw-response-data-eg-headers
+ """
+ return LiveResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> LiveResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/hyperspell/python-sdk#with_streaming_response
+ """
+ return LiveResourceWithStreamingResponse(self)
+
+ def get_resource(
+ self,
+ resource_id: str,
+ *,
+ source: Literal[
+ "reddit",
+ "notion",
+ "slack",
+ "google_calendar",
+ "google_mail",
+ "imap",
+ "google_meet",
+ "box",
+ "dropbox",
+ "github",
+ "gitlab",
+ "google_drive",
+ "vault",
+ "web_crawler",
+ "trace",
+ "microsoft_outlook",
+ "microsoft_teams",
+ "granola",
+ "fathom",
+ "fireflies",
+ "figma",
+ "linear",
+ "hubspot",
+ "salesforce",
+ "coda",
+ "confluence",
+ "jira",
+ "metabase",
+ "gong",
+ "clickup",
+ "lightfield",
+ "pylon",
+ "fellow",
+ "odoo",
+ "external_mcp",
+ ],
+ connection_id: Optional[str] | Omit = omit,
+ index: bool | 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,
+ ) -> LiveGetResourceResponse:
+ """Fetch one resource live by id.
+
+ A single fetch may fan out into several resources
+ (e.g. a thread → its messages); all are returned.
+
+ Args:
+ connection_id: Specific connection id.
+
+ index: Also queue this resource for indexing.
+
+ 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(
+ path_template("/live/{source}/resources/{resource_id}", source=source, resource_id=resource_id),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "connection_id": connection_id,
+ "index": index,
+ },
+ live_get_resource_params.LiveGetResourceParams,
+ ),
+ ),
+ cast_to=LiveGetResourceResponse,
+ )
+
+ def list_resources(
+ self,
+ source: Literal[
+ "reddit",
+ "notion",
+ "slack",
+ "google_calendar",
+ "google_mail",
+ "imap",
+ "google_meet",
+ "box",
+ "dropbox",
+ "github",
+ "gitlab",
+ "google_drive",
+ "vault",
+ "web_crawler",
+ "trace",
+ "microsoft_outlook",
+ "microsoft_teams",
+ "granola",
+ "fathom",
+ "fireflies",
+ "figma",
+ "linear",
+ "hubspot",
+ "salesforce",
+ "coda",
+ "confluence",
+ "jira",
+ "metabase",
+ "gong",
+ "clickup",
+ "lightfield",
+ "pylon",
+ "fellow",
+ "odoo",
+ "external_mcp",
+ ],
+ *,
+ connection_id: Optional[str] | Omit = omit,
+ cursor: Optional[str] | Omit = omit,
+ size: int | 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,
+ ) -> SyncCursorPage[LiveListResourcesResponse]:
+ """
+ Page through a source's resources live (no indexing side effect).
+
+ The cursor is opaque and integration-defined — pass back the `next_cursor` from
+ the previous page verbatim.
+
+ Args:
+ connection_id: Specific connection id.
+
+ 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}")
+ return self._get_api_list(
+ path_template("/live/{source}/resources", source=source),
+ page=SyncCursorPage[LiveListResourcesResponse],
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "connection_id": connection_id,
+ "cursor": cursor,
+ "size": size,
+ },
+ live_list_resources_params.LiveListResourcesParams,
+ ),
+ ),
+ model=LiveListResourcesResponse,
+ )
+
+ def list_sources(
+ 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,
+ ) -> LiveListSourcesResponse:
+ """List the user's connected sources and the live capabilities each supports."""
+ return self._get(
+ "/live/sources",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=LiveListSourcesResponse,
+ )
+
+ def search(
+ self,
+ source: Literal[
+ "reddit",
+ "notion",
+ "slack",
+ "google_calendar",
+ "google_mail",
+ "imap",
+ "google_meet",
+ "box",
+ "dropbox",
+ "github",
+ "gitlab",
+ "google_drive",
+ "vault",
+ "web_crawler",
+ "trace",
+ "microsoft_outlook",
+ "microsoft_teams",
+ "granola",
+ "fathom",
+ "fireflies",
+ "figma",
+ "linear",
+ "hubspot",
+ "salesforce",
+ "coda",
+ "confluence",
+ "jira",
+ "metabase",
+ "gong",
+ "clickup",
+ "lightfield",
+ "pylon",
+ "fellow",
+ "odoo",
+ "external_mcp",
+ ],
+ *,
+ query: str,
+ connection_id: Optional[str] | Omit = omit,
+ index: bool | 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,
+ ) -> LiveSearchResponse:
+ """Search a source live for content that may not be indexed yet.
+
+ With `index=true`,
+ each hit is queued for indexing (no-op for live-only sources like Google
+ Calendar — see `notes` in the response).
+
+ Args:
+ query: Live search query.
+
+ connection_id: Specific connection id when the user has multiple for this source.
+
+ index: If true, queue each hit for indexing so it's on-hand next time.
+
+ 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}")
+ return self._post(
+ path_template("/live/{source}/search", source=source),
+ body=maybe_transform(
+ {
+ "query": query,
+ "connection_id": connection_id,
+ "index": index,
+ },
+ live_search_params.LiveSearchParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=LiveSearchResponse,
+ )
+
+
+class AsyncLiveResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncLiveResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/hyperspell/python-sdk#accessing-raw-response-data-eg-headers
+ """
+ return AsyncLiveResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncLiveResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/hyperspell/python-sdk#with_streaming_response
+ """
+ return AsyncLiveResourceWithStreamingResponse(self)
+
+ async def get_resource(
+ self,
+ resource_id: str,
+ *,
+ source: Literal[
+ "reddit",
+ "notion",
+ "slack",
+ "google_calendar",
+ "google_mail",
+ "imap",
+ "google_meet",
+ "box",
+ "dropbox",
+ "github",
+ "gitlab",
+ "google_drive",
+ "vault",
+ "web_crawler",
+ "trace",
+ "microsoft_outlook",
+ "microsoft_teams",
+ "granola",
+ "fathom",
+ "fireflies",
+ "figma",
+ "linear",
+ "hubspot",
+ "salesforce",
+ "coda",
+ "confluence",
+ "jira",
+ "metabase",
+ "gong",
+ "clickup",
+ "lightfield",
+ "pylon",
+ "fellow",
+ "odoo",
+ "external_mcp",
+ ],
+ connection_id: Optional[str] | Omit = omit,
+ index: bool | 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,
+ ) -> LiveGetResourceResponse:
+ """Fetch one resource live by id.
+
+ A single fetch may fan out into several resources
+ (e.g. a thread → its messages); all are returned.
+
+ Args:
+ connection_id: Specific connection id.
+
+ index: Also queue this resource for indexing.
+
+ 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(
+ path_template("/live/{source}/resources/{resource_id}", source=source, resource_id=resource_id),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform(
+ {
+ "connection_id": connection_id,
+ "index": index,
+ },
+ live_get_resource_params.LiveGetResourceParams,
+ ),
+ ),
+ cast_to=LiveGetResourceResponse,
+ )
+
+ def list_resources(
+ self,
+ source: Literal[
+ "reddit",
+ "notion",
+ "slack",
+ "google_calendar",
+ "google_mail",
+ "imap",
+ "google_meet",
+ "box",
+ "dropbox",
+ "github",
+ "gitlab",
+ "google_drive",
+ "vault",
+ "web_crawler",
+ "trace",
+ "microsoft_outlook",
+ "microsoft_teams",
+ "granola",
+ "fathom",
+ "fireflies",
+ "figma",
+ "linear",
+ "hubspot",
+ "salesforce",
+ "coda",
+ "confluence",
+ "jira",
+ "metabase",
+ "gong",
+ "clickup",
+ "lightfield",
+ "pylon",
+ "fellow",
+ "odoo",
+ "external_mcp",
+ ],
+ *,
+ connection_id: Optional[str] | Omit = omit,
+ cursor: Optional[str] | Omit = omit,
+ size: int | 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,
+ ) -> AsyncPaginator[LiveListResourcesResponse, AsyncCursorPage[LiveListResourcesResponse]]:
+ """
+ Page through a source's resources live (no indexing side effect).
+
+ The cursor is opaque and integration-defined — pass back the `next_cursor` from
+ the previous page verbatim.
+
+ Args:
+ connection_id: Specific connection id.
+
+ 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}")
+ return self._get_api_list(
+ path_template("/live/{source}/resources", source=source),
+ page=AsyncCursorPage[LiveListResourcesResponse],
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "connection_id": connection_id,
+ "cursor": cursor,
+ "size": size,
+ },
+ live_list_resources_params.LiveListResourcesParams,
+ ),
+ ),
+ model=LiveListResourcesResponse,
+ )
+
+ async def list_sources(
+ 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,
+ ) -> LiveListSourcesResponse:
+ """List the user's connected sources and the live capabilities each supports."""
+ return await self._get(
+ "/live/sources",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=LiveListSourcesResponse,
+ )
+
+ async def search(
+ self,
+ source: Literal[
+ "reddit",
+ "notion",
+ "slack",
+ "google_calendar",
+ "google_mail",
+ "imap",
+ "google_meet",
+ "box",
+ "dropbox",
+ "github",
+ "gitlab",
+ "google_drive",
+ "vault",
+ "web_crawler",
+ "trace",
+ "microsoft_outlook",
+ "microsoft_teams",
+ "granola",
+ "fathom",
+ "fireflies",
+ "figma",
+ "linear",
+ "hubspot",
+ "salesforce",
+ "coda",
+ "confluence",
+ "jira",
+ "metabase",
+ "gong",
+ "clickup",
+ "lightfield",
+ "pylon",
+ "fellow",
+ "odoo",
+ "external_mcp",
+ ],
+ *,
+ query: str,
+ connection_id: Optional[str] | Omit = omit,
+ index: bool | 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,
+ ) -> LiveSearchResponse:
+ """Search a source live for content that may not be indexed yet.
+
+ With `index=true`,
+ each hit is queued for indexing (no-op for live-only sources like Google
+ Calendar — see `notes` in the response).
+
+ Args:
+ query: Live search query.
+
+ connection_id: Specific connection id when the user has multiple for this source.
+
+ index: If true, queue each hit for indexing so it's on-hand next time.
+
+ 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}")
+ return await self._post(
+ path_template("/live/{source}/search", source=source),
+ body=await async_maybe_transform(
+ {
+ "query": query,
+ "connection_id": connection_id,
+ "index": index,
+ },
+ live_search_params.LiveSearchParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=LiveSearchResponse,
+ )
+
+
+class LiveResourceWithRawResponse:
+ def __init__(self, live: LiveResource) -> None:
+ self._live = live
+
+ self.get_resource = to_raw_response_wrapper(
+ live.get_resource,
+ )
+ self.list_resources = to_raw_response_wrapper(
+ live.list_resources,
+ )
+ self.list_sources = to_raw_response_wrapper(
+ live.list_sources,
+ )
+ self.search = to_raw_response_wrapper(
+ live.search,
+ )
+
+
+class AsyncLiveResourceWithRawResponse:
+ def __init__(self, live: AsyncLiveResource) -> None:
+ self._live = live
+
+ self.get_resource = async_to_raw_response_wrapper(
+ live.get_resource,
+ )
+ self.list_resources = async_to_raw_response_wrapper(
+ live.list_resources,
+ )
+ self.list_sources = async_to_raw_response_wrapper(
+ live.list_sources,
+ )
+ self.search = async_to_raw_response_wrapper(
+ live.search,
+ )
+
+
+class LiveResourceWithStreamingResponse:
+ def __init__(self, live: LiveResource) -> None:
+ self._live = live
+
+ self.get_resource = to_streamed_response_wrapper(
+ live.get_resource,
+ )
+ self.list_resources = to_streamed_response_wrapper(
+ live.list_resources,
+ )
+ self.list_sources = to_streamed_response_wrapper(
+ live.list_sources,
+ )
+ self.search = to_streamed_response_wrapper(
+ live.search,
+ )
+
+
+class AsyncLiveResourceWithStreamingResponse:
+ def __init__(self, live: AsyncLiveResource) -> None:
+ self._live = live
+
+ self.get_resource = async_to_streamed_response_wrapper(
+ live.get_resource,
+ )
+ self.list_resources = async_to_streamed_response_wrapper(
+ live.list_resources,
+ )
+ self.list_sources = async_to_streamed_response_wrapper(
+ live.list_sources,
+ )
+ self.search = async_to_streamed_response_wrapper(
+ live.search,
+ )
diff --git a/src/hyperspell/types/__init__.py b/src/hyperspell/types/__init__.py
index 9f55fd0e..d07c5a5c 100644
--- a/src/hyperspell/types/__init__.py
+++ b/src/hyperspell/types/__init__.py
@@ -2,7 +2,14 @@
from __future__ import annotations
-from . import shared, memory_get_response, memory_list_response
+from . import (
+ shared,
+ memory_get_response,
+ live_search_response,
+ memory_list_response,
+ live_get_resource_response,
+ live_list_resources_response,
+)
from .. import _compat
from .token import Token as Token
from .shared import (
@@ -57,21 +64,29 @@
from .memory_add_params import MemoryAddParams as MemoryAddParams
from .memory_get_params import MemoryGetParams as MemoryGetParams
from .vault_list_params import VaultListParams as VaultListParams
+from .entity_list_params import EntityListParams as EntityListParams
from .folder_list_params import FolderListParams as FolderListParams
+from .live_search_params import LiveSearchParams as LiveSearchParams
from .memory_list_params import MemoryListParams as MemoryListParams
from .session_add_params import SessionAddParams as SessionAddParams
+from .entity_get_response import EntityGetResponse as EntityGetResponse
from .memory_get_response import MemoryGetResponse as MemoryGetResponse
from .vault_list_response import VaultListResponse as VaultListResponse
+from .entity_list_response import EntityListResponse as EntityListResponse
+from .entity_search_params import EntitySearchParams as EntitySearchParams
from .folder_list_response import FolderListResponse as FolderListResponse
+from .live_search_response import LiveSearchResponse as LiveSearchResponse
from .memory_list_response import MemoryListResponse as MemoryListResponse
from .memory_search_params import MemorySearchParams as MemorySearchParams
from .memory_update_params import MemoryUpdateParams as MemoryUpdateParams
from .memory_upload_params import MemoryUploadParams as MemoryUploadParams
from .auth_user_token_params import AuthUserTokenParams as AuthUserTokenParams
+from .entity_search_response import EntitySearchResponse as EntitySearchResponse
from .memory_add_bulk_params import MemoryAddBulkParams as MemoryAddBulkParams
from .memory_delete_response import MemoryDeleteResponse as MemoryDeleteResponse
from .memory_status_response import MemoryStatusResponse as MemoryStatusResponse
from .connection_list_response import ConnectionListResponse as ConnectionListResponse
+from .live_get_resource_params import LiveGetResourceParams as LiveGetResourceParams
from .memory_add_bulk_response import MemoryAddBulkResponse as MemoryAddBulkResponse
from .auth_delete_user_response import AuthDeleteUserResponse as AuthDeleteUserResponse
from .integration_list_response import IntegrationListResponse as IntegrationListResponse
@@ -80,30 +95,44 @@
from .connection_revoke_response import ConnectionRevokeResponse as ConnectionRevokeResponse
from .folder_set_policies_params import FolderSetPoliciesParams as FolderSetPoliciesParams
from .integration_connect_params import IntegrationConnectParams as IntegrationConnectParams
+from .live_get_resource_response import LiveGetResourceResponse as LiveGetResourceResponse
+from .live_list_resources_params import LiveListResourcesParams as LiveListResourcesParams
+from .live_list_sources_response import LiveListSourcesResponse as LiveListSourcesResponse
from .evaluate_score_query_params import EvaluateScoreQueryParams as EvaluateScoreQueryParams
from .action_add_reaction_response import ActionAddReactionResponse as ActionAddReactionResponse
from .action_send_message_response import ActionSendMessageResponse as ActionSendMessageResponse
-from .context_document_list_params import ContextDocumentListParams as ContextDocumentListParams
from .evaluate_list_queries_params import EvaluateListQueriesParams as EvaluateListQueriesParams
from .folder_set_policies_response import FolderSetPoliciesResponse as FolderSetPoliciesResponse
from .integration_connect_response import IntegrationConnectResponse as IntegrationConnectResponse
-from .context_document_get_response import ContextDocumentGetResponse as ContextDocumentGetResponse
+from .live_list_resources_response import LiveListResourcesResponse as LiveListResourcesResponse
from .evaluate_score_query_response import EvaluateScoreQueryResponse as EvaluateScoreQueryResponse
from .folder_delete_policy_response import FolderDeletePolicyResponse as FolderDeletePolicyResponse
from .folder_list_policies_response import FolderListPoliciesResponse as FolderListPoliciesResponse
-from .context_document_list_response import ContextDocumentListResponse as ContextDocumentListResponse
from .evaluate_list_queries_response import EvaluateListQueriesResponse as EvaluateListQueriesResponse
from .evaluate_score_highlight_params import EvaluateScoreHighlightParams as EvaluateScoreHighlightParams
-from .context_document_generate_params import ContextDocumentGenerateParams as ContextDocumentGenerateParams
from .evaluate_score_highlight_response import EvaluateScoreHighlightResponse as EvaluateScoreHighlightResponse
-from .context_document_generate_response import ContextDocumentGenerateResponse as ContextDocumentGenerateResponse
# Rebuild cyclical models only after all modules are imported.
# This ensures that, when building the deferred (due to cyclical references) model schema,
# Pydantic can resolve the necessary references.
# See: https://github.com/pydantic/pydantic/issues/11250 for more context.
if _compat.PYDANTIC_V1:
+ live_get_resource_response.DocumentDocumentInvoice.update_forward_refs() # type: ignore
+ live_get_resource_response.DocumentChunk.update_forward_refs() # type: ignore
+ live_get_resource_response.Document.update_forward_refs() # type: ignore
+ live_get_resource_response.LiveGetResourceResponse.update_forward_refs() # type: ignore
+ live_list_resources_response.DocumentInvoice.update_forward_refs() # type: ignore
+ live_list_resources_response.Chunk.update_forward_refs() # type: ignore
+ live_list_resources_response.LiveListResourcesResponse.update_forward_refs() # type: ignore
+ live_search_response.DocumentDocumentInvoice.update_forward_refs() # type: ignore
+ live_search_response.DocumentChunk.update_forward_refs() # type: ignore
+ live_search_response.Document.update_forward_refs() # type: ignore
+ live_search_response.LiveSearchResponse.update_forward_refs() # type: ignore
+ memory_list_response.DocumentInvoice.update_forward_refs() # type: ignore
+ memory_list_response.Chunk.update_forward_refs() # type: ignore
memory_list_response.MemoryListResponse.update_forward_refs() # type: ignore
+ memory_get_response.DocumentInvoice.update_forward_refs() # type: ignore
+ memory_get_response.Chunk.update_forward_refs() # type: ignore
memory_get_response.MemoryGetResponse.update_forward_refs() # type: ignore
shared.callout.Callout.update_forward_refs() # type: ignore
shared.chunk.Chunk.update_forward_refs() # type: ignore
@@ -124,6 +153,8 @@
shared.person.Person.update_forward_refs() # type: ignore
shared.query_result.QueryResult.update_forward_refs() # type: ignore
shared.quote.Quote.update_forward_refs() # type: ignore
+ shared.scored_document_response.DocumentInvoice.update_forward_refs() # type: ignore
+ shared.scored_document_response.Chunk.update_forward_refs() # type: ignore
shared.scored_document_response.ScoredDocumentResponse.update_forward_refs() # type: ignore
shared.table.Table.update_forward_refs() # type: ignore
shared.table_cell.TableCell.update_forward_refs() # type: ignore
@@ -134,7 +165,22 @@
shared.utterance.Utterance.update_forward_refs() # type: ignore
shared.website.Website.update_forward_refs() # type: ignore
else:
+ live_get_resource_response.DocumentDocumentInvoice.model_rebuild(_parent_namespace_depth=0)
+ live_get_resource_response.DocumentChunk.model_rebuild(_parent_namespace_depth=0)
+ live_get_resource_response.Document.model_rebuild(_parent_namespace_depth=0)
+ live_get_resource_response.LiveGetResourceResponse.model_rebuild(_parent_namespace_depth=0)
+ live_list_resources_response.DocumentInvoice.model_rebuild(_parent_namespace_depth=0)
+ live_list_resources_response.Chunk.model_rebuild(_parent_namespace_depth=0)
+ live_list_resources_response.LiveListResourcesResponse.model_rebuild(_parent_namespace_depth=0)
+ live_search_response.DocumentDocumentInvoice.model_rebuild(_parent_namespace_depth=0)
+ live_search_response.DocumentChunk.model_rebuild(_parent_namespace_depth=0)
+ live_search_response.Document.model_rebuild(_parent_namespace_depth=0)
+ live_search_response.LiveSearchResponse.model_rebuild(_parent_namespace_depth=0)
+ memory_list_response.DocumentInvoice.model_rebuild(_parent_namespace_depth=0)
+ memory_list_response.Chunk.model_rebuild(_parent_namespace_depth=0)
memory_list_response.MemoryListResponse.model_rebuild(_parent_namespace_depth=0)
+ memory_get_response.DocumentInvoice.model_rebuild(_parent_namespace_depth=0)
+ memory_get_response.Chunk.model_rebuild(_parent_namespace_depth=0)
memory_get_response.MemoryGetResponse.model_rebuild(_parent_namespace_depth=0)
shared.callout.Callout.model_rebuild(_parent_namespace_depth=0)
shared.chunk.Chunk.model_rebuild(_parent_namespace_depth=0)
@@ -155,6 +201,8 @@
shared.person.Person.model_rebuild(_parent_namespace_depth=0)
shared.query_result.QueryResult.model_rebuild(_parent_namespace_depth=0)
shared.quote.Quote.model_rebuild(_parent_namespace_depth=0)
+ shared.scored_document_response.DocumentInvoice.model_rebuild(_parent_namespace_depth=0)
+ shared.scored_document_response.Chunk.model_rebuild(_parent_namespace_depth=0)
shared.scored_document_response.ScoredDocumentResponse.model_rebuild(_parent_namespace_depth=0)
shared.table.Table.model_rebuild(_parent_namespace_depth=0)
shared.table_cell.TableCell.model_rebuild(_parent_namespace_depth=0)
diff --git a/src/hyperspell/types/context_document_generate_params.py b/src/hyperspell/types/context_document_generate_params.py
deleted file mode 100644
index 196ed0a4..00000000
--- a/src/hyperspell/types/context_document_generate_params.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Optional
-from typing_extensions import TypedDict
-
-from .._types import SequenceNotStr
-
-__all__ = ["ContextDocumentGenerateParams"]
-
-
-class ContextDocumentGenerateParams(TypedDict, total=False):
- model: str
- """Model used for final synthesis."""
-
- prompt: Optional[str]
- """Custom prompt template. Replaces the standard summary prompt."""
-
- sources: Optional[SequenceNotStr[str]]
- """Integration sources to include (e.g., ['gmail', 'slack']).
-
- Defaults to all connected integrations.
- """
-
- user_id: Optional[str]
- """Scope generation to a specific user's data."""
diff --git a/src/hyperspell/types/context_document_generate_response.py b/src/hyperspell/types/context_document_generate_response.py
deleted file mode 100644
index 7dd7059b..00000000
--- a/src/hyperspell/types/context_document_generate_response.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from datetime import datetime
-
-from .._models import BaseModel
-
-__all__ = ["ContextDocumentGenerateResponse"]
-
-
-class ContextDocumentGenerateResponse(BaseModel):
- created_at: datetime
-
- document_id: str
-
- status: str
diff --git a/src/hyperspell/types/context_document_get_response.py b/src/hyperspell/types/context_document_get_response.py
deleted file mode 100644
index bc43de69..00000000
--- a/src/hyperspell/types/context_document_get_response.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import Dict, List, Optional
-from datetime import datetime
-
-from .._models import BaseModel
-
-__all__ = ["ContextDocumentGetResponse"]
-
-
-class ContextDocumentGetResponse(BaseModel):
- completed_at: Optional[datetime] = None
-
- content: Optional[str] = None
-
- created_at: datetime
-
- document_id: str
-
- error: Optional[str] = None
-
- metadata: Dict[str, object]
-
- model: str
-
- prompt: Optional[str] = None
-
- sources: List[str]
-
- status: str
-
- token_usage: Optional[Dict[str, object]] = None
-
- user_id: Optional[str] = None
diff --git a/src/hyperspell/types/context_document_list_params.py b/src/hyperspell/types/context_document_list_params.py
deleted file mode 100644
index ebc6f13b..00000000
--- a/src/hyperspell/types/context_document_list_params.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Optional
-from typing_extensions import Literal, TypedDict
-
-__all__ = ["ContextDocumentListParams"]
-
-
-class ContextDocumentListParams(TypedDict, total=False):
- cursor: Optional[str]
-
- limit: int
-
- status: Optional[Literal["processing", "completed", "failed"]]
diff --git a/src/hyperspell/types/context_document_list_response.py b/src/hyperspell/types/context_document_list_response.py
deleted file mode 100644
index 97cf9372..00000000
--- a/src/hyperspell/types/context_document_list_response.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import List, Optional
-from datetime import datetime
-
-from .._models import BaseModel
-
-__all__ = ["ContextDocumentListResponse"]
-
-
-class ContextDocumentListResponse(BaseModel):
- completed_at: Optional[datetime] = None
-
- created_at: datetime
-
- document_id: str
-
- model: str
-
- sources: List[str]
-
- status: str
-
- token_count: Optional[int] = None
-
- error: Optional[str] = None
diff --git a/src/hyperspell/types/context_documents/__init__.py b/src/hyperspell/types/context_documents/__init__.py
deleted file mode 100644
index 869a58d2..00000000
--- a/src/hyperspell/types/context_documents/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from .tree_get_response import TreeGetResponse as TreeGetResponse
-from .digest_list_params import DigestListParams as DigestListParams
-from .config_get_response import ConfigGetResponse as ConfigGetResponse
-from .config_update_params import ConfigUpdateParams as ConfigUpdateParams
-from .digest_list_response import DigestListResponse as DigestListResponse
-from .tree_generate_params import TreeGenerateParams as TreeGenerateParams
-from .config_reset_response import ConfigResetResponse as ConfigResetResponse
-from .config_update_response import ConfigUpdateResponse as ConfigUpdateResponse
-from .digest_generate_params import DigestGenerateParams as DigestGenerateParams
-from .tree_generate_response import TreeGenerateResponse as TreeGenerateResponse
-from .tree_get_latest_params import TreeGetLatestParams as TreeGetLatestParams
-from .tree_progress_response import TreeProgressResponse as TreeProgressResponse
-from .digest_generate_response import DigestGenerateResponse as DigestGenerateResponse
-from .tree_get_latest_response import TreeGetLatestResponse as TreeGetLatestResponse
diff --git a/src/hyperspell/types/context_documents/config_get_response.py b/src/hyperspell/types/context_documents/config_get_response.py
deleted file mode 100644
index ca56060d..00000000
--- a/src/hyperspell/types/context_documents/config_get_response.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import Dict, Optional
-
-from ..._models import BaseModel
-
-__all__ = ["ConfigGetResponse"]
-
-
-class ConfigGetResponse(BaseModel):
- """Brain-generation settings that customers can view and edit."""
-
- prompts: Dict[str, object]
-
- source_weights: Dict[str, str]
-
- structure: Dict[str, object]
-
- detected_domain: Optional[str] = None
-
- domain: Optional[str] = None
diff --git a/src/hyperspell/types/context_documents/config_reset_response.py b/src/hyperspell/types/context_documents/config_reset_response.py
deleted file mode 100644
index 9dcb234c..00000000
--- a/src/hyperspell/types/context_documents/config_reset_response.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import Dict, Optional
-
-from ..._models import BaseModel
-
-__all__ = ["ConfigResetResponse"]
-
-
-class ConfigResetResponse(BaseModel):
- """Brain-generation settings that customers can view and edit."""
-
- prompts: Dict[str, object]
-
- source_weights: Dict[str, str]
-
- structure: Dict[str, object]
-
- detected_domain: Optional[str] = None
-
- domain: Optional[str] = None
diff --git a/src/hyperspell/types/context_documents/config_update_params.py b/src/hyperspell/types/context_documents/config_update_params.py
deleted file mode 100644
index 0acda28e..00000000
--- a/src/hyperspell/types/context_documents/config_update_params.py
+++ /dev/null
@@ -1,63 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Dict, Iterable, Optional
-from typing_extensions import Required, TypedDict
-
-from ..._types import SequenceNotStr
-
-__all__ = ["ConfigUpdateParams", "Structure", "StructureCompany", "StructureWorkstream"]
-
-
-class ConfigUpdateParams(TypedDict, total=False):
- company_prompts: Optional[Dict[str, str]]
-
- detection_prompt: Optional[str]
-
- domain: Optional[str]
-
- personal_prompt: Optional[str]
-
- source_weights: Optional[Dict[str, str]]
-
- structure: Optional[Structure]
- """Per-tier document definitions for custom generation."""
-
- workstream_prompts: Optional[Dict[str, str]]
-
-
-class StructureCompany(TypedDict, total=False):
- """
- One document in a context-tree tier: what to generate and how to retrieve for it.
- """
-
- filename: Required[str]
-
- key: Required[str]
-
- prompt: Required[str]
-
- search_queries: Required[SequenceNotStr[str]]
-
-
-class StructureWorkstream(TypedDict, total=False):
- """
- One document in a context-tree tier: what to generate and how to retrieve for it.
- """
-
- filename: Required[str]
-
- key: Required[str]
-
- prompt: Required[str]
-
- search_queries: Required[SequenceNotStr[str]]
-
-
-class Structure(TypedDict, total=False):
- """Per-tier document definitions for custom generation."""
-
- company: Optional[Iterable[StructureCompany]]
-
- workstream: Optional[Iterable[StructureWorkstream]]
diff --git a/src/hyperspell/types/context_documents/config_update_response.py b/src/hyperspell/types/context_documents/config_update_response.py
deleted file mode 100644
index 3d4a6c32..00000000
--- a/src/hyperspell/types/context_documents/config_update_response.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import Dict, Optional
-
-from ..._models import BaseModel
-
-__all__ = ["ConfigUpdateResponse"]
-
-
-class ConfigUpdateResponse(BaseModel):
- """Brain-generation settings that customers can view and edit."""
-
- prompts: Dict[str, object]
-
- source_weights: Dict[str, str]
-
- structure: Dict[str, object]
-
- detected_domain: Optional[str] = None
-
- domain: Optional[str] = None
diff --git a/src/hyperspell/types/context_documents/digest_generate_params.py b/src/hyperspell/types/context_documents/digest_generate_params.py
deleted file mode 100644
index f44ef839..00000000
--- a/src/hyperspell/types/context_documents/digest_generate_params.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Union, Optional
-from datetime import datetime
-from typing_extensions import Annotated, TypedDict
-
-from ..._types import SequenceNotStr
-from ..._utils import PropertyInfo
-
-__all__ = ["DigestGenerateParams"]
-
-
-class DigestGenerateParams(TypedDict, total=False):
- period: str
- """Digest cadence: 'daily' or 'weekly'.
-
- Sets the default window when none is given.
- """
-
- sources: Optional[SequenceNotStr[str]]
- """Integration sources to include (e.g., ['slack', 'github']). Defaults to all."""
-
- window_end: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
- """Exclusive upper bound of the digest window. Defaults to now."""
-
- window_start: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
- """Inclusive lower bound of the digest window.
-
- Defaults to midnight UTC today (paired with window_end=now) when omitted. Both
- bounds must be supplied together.
- """
diff --git a/src/hyperspell/types/context_documents/digest_generate_response.py b/src/hyperspell/types/context_documents/digest_generate_response.py
deleted file mode 100644
index d3112463..00000000
--- a/src/hyperspell/types/context_documents/digest_generate_response.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from datetime import datetime
-
-from ..._models import BaseModel
-
-__all__ = ["DigestGenerateResponse"]
-
-
-class DigestGenerateResponse(BaseModel):
- created_at: datetime
-
- status: str
-
- tree_id: str
diff --git a/src/hyperspell/types/context_documents/digest_list_params.py b/src/hyperspell/types/context_documents/digest_list_params.py
deleted file mode 100644
index 79f076e3..00000000
--- a/src/hyperspell/types/context_documents/digest_list_params.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 Optional
-from typing_extensions import TypedDict
-
-__all__ = ["DigestListParams"]
-
-
-class DigestListParams(TypedDict, total=False):
- limit: int
-
- period: Optional[str]
diff --git a/src/hyperspell/types/context_documents/digest_list_response.py b/src/hyperspell/types/context_documents/digest_list_response.py
deleted file mode 100644
index a55ab243..00000000
--- a/src/hyperspell/types/context_documents/digest_list_response.py
+++ /dev/null
@@ -1,30 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import List, Optional
-from datetime import datetime
-
-from ..._models import BaseModel
-
-__all__ = ["DigestListResponse", "Digest"]
-
-
-class Digest(BaseModel):
- """A digest summary. Fetch the full content through the tree-by-ID endpoint."""
-
- completed_at: Optional[datetime] = None
-
- created_at: datetime
-
- period: Optional[str] = None
-
- status: str
-
- tree_id: str
-
- window_end: Optional[datetime] = None
-
- window_start: Optional[datetime] = None
-
-
-class DigestListResponse(BaseModel):
- digests: List[Digest]
diff --git a/src/hyperspell/types/context_documents/tree_generate_params.py b/src/hyperspell/types/context_documents/tree_generate_params.py
deleted file mode 100644
index 18b51da6..00000000
--- a/src/hyperspell/types/context_documents/tree_generate_params.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Optional
-from typing_extensions import TypedDict
-
-from ..._types import SequenceNotStr
-
-__all__ = ["TreeGenerateParams"]
-
-
-class TreeGenerateParams(TypedDict, total=False):
- sources: Optional[SequenceNotStr[str]]
- """Integration sources to include (e.g., ['gmail', 'slack']). Defaults to all."""
-
- user_id: Optional[str]
- """User ID for personal tier scoping.
-
- When set, personal/context.md is generated from this user's data only. Company
- and workstream tiers still use all data.
- """
-
- workstream_name: Optional[str]
- """Generate docs for this workstream only (skip auto-detection)."""
diff --git a/src/hyperspell/types/context_documents/tree_generate_response.py b/src/hyperspell/types/context_documents/tree_generate_response.py
deleted file mode 100644
index 8c1e6906..00000000
--- a/src/hyperspell/types/context_documents/tree_generate_response.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from datetime import datetime
-
-from ..._models import BaseModel
-
-__all__ = ["TreeGenerateResponse"]
-
-
-class TreeGenerateResponse(BaseModel):
- created_at: datetime
-
- status: str
-
- tree_id: str
diff --git a/src/hyperspell/types/context_documents/tree_get_latest_params.py b/src/hyperspell/types/context_documents/tree_get_latest_params.py
deleted file mode 100644
index 81893150..00000000
--- a/src/hyperspell/types/context_documents/tree_get_latest_params.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Optional
-from typing_extensions import TypedDict
-
-__all__ = ["TreeGetLatestParams"]
-
-
-class TreeGetLatestParams(TypedDict, total=False):
- status: Optional[str]
diff --git a/src/hyperspell/types/context_documents/tree_get_latest_response.py b/src/hyperspell/types/context_documents/tree_get_latest_response.py
deleted file mode 100644
index 75d993ad..00000000
--- a/src/hyperspell/types/context_documents/tree_get_latest_response.py
+++ /dev/null
@@ -1,70 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import Dict, List, Optional
-from datetime import datetime
-from typing_extensions import Literal
-
-from ..._models import BaseModel
-
-__all__ = ["TreeGetLatestResponse", "File", "Generating"]
-
-
-class File(BaseModel):
- content: str
-
- path: str
-
- team: Optional[str] = None
-
- tier: str
-
- updated_at: str
-
- error: Optional[str] = None
-
- provenance: Optional[Dict[str, object]] = None
-
- status: Optional[str] = None
-
-
-class Generating(BaseModel):
- """Status of a newer generation that is processing or recently failed.
-
- This can accompany the last ready tree so clients can report progress while
- continuing to use ready content.
- """
-
- created_at: datetime
-
- status: Literal["processing", "failed"]
-
- tree_id: str
-
- error: Optional[str] = None
-
- progress: Optional[Dict[str, object]] = None
-
-
-class TreeGetLatestResponse(BaseModel):
- completed_at: Optional[datetime] = None
-
- created_at: datetime
-
- error: Optional[str] = None
-
- files: Optional[List[File]] = None
-
- meta: Dict[str, object]
-
- status: str
-
- tree_id: str
-
- version: int
-
- generating: Optional[Generating] = None
- """Status of a newer generation that is processing or recently failed.
-
- This can accompany the last ready tree so clients can report progress while
- continuing to use ready content.
- """
diff --git a/src/hyperspell/types/context_documents/tree_get_response.py b/src/hyperspell/types/context_documents/tree_get_response.py
deleted file mode 100644
index 99db09be..00000000
--- a/src/hyperspell/types/context_documents/tree_get_response.py
+++ /dev/null
@@ -1,70 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import Dict, List, Optional
-from datetime import datetime
-from typing_extensions import Literal
-
-from ..._models import BaseModel
-
-__all__ = ["TreeGetResponse", "File", "Generating"]
-
-
-class File(BaseModel):
- content: str
-
- path: str
-
- team: Optional[str] = None
-
- tier: str
-
- updated_at: str
-
- error: Optional[str] = None
-
- provenance: Optional[Dict[str, object]] = None
-
- status: Optional[str] = None
-
-
-class Generating(BaseModel):
- """Status of a newer generation that is processing or recently failed.
-
- This can accompany the last ready tree so clients can report progress while
- continuing to use ready content.
- """
-
- created_at: datetime
-
- status: Literal["processing", "failed"]
-
- tree_id: str
-
- error: Optional[str] = None
-
- progress: Optional[Dict[str, object]] = None
-
-
-class TreeGetResponse(BaseModel):
- completed_at: Optional[datetime] = None
-
- created_at: datetime
-
- error: Optional[str] = None
-
- files: Optional[List[File]] = None
-
- meta: Dict[str, object]
-
- status: str
-
- tree_id: str
-
- version: int
-
- generating: Optional[Generating] = None
- """Status of a newer generation that is processing or recently failed.
-
- This can accompany the last ready tree so clients can report progress while
- continuing to use ready content.
- """
diff --git a/src/hyperspell/types/context_documents/tree_progress_response.py b/src/hyperspell/types/context_documents/tree_progress_response.py
deleted file mode 100644
index 95add82d..00000000
--- a/src/hyperspell/types/context_documents/tree_progress_response.py
+++ /dev/null
@@ -1,30 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import List, Optional
-
-from ..._models import BaseModel
-
-__all__ = ["TreeProgressResponse"]
-
-
-class TreeProgressResponse(BaseModel):
- """Response shape for GET /context-documents/tree/{tree_id}/progress."""
-
- status: str
-
- tree_id: str
-
- completed_docs: Optional[int] = None
-
- failed_docs: Optional[int] = None
-
- failed_keys: Optional[List[str]] = None
-
- phase: Optional[str] = None
- """Generation phase.
-
- Values: discover, search, select, synthesize, finalize, personal, done. Null
- when detailed progress is unavailable.
- """
-
- total_docs: Optional[int] = None
diff --git a/src/hyperspell/types/entity_get_response.py b/src/hyperspell/types/entity_get_response.py
new file mode 100644
index 00000000..81c69450
--- /dev/null
+++ b/src/hyperspell/types/entity_get_response.py
@@ -0,0 +1,40 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Dict, Optional
+from datetime import datetime
+from typing_extensions import Literal
+
+from .._models import BaseModel
+
+__all__ = ["EntityGetResponse"]
+
+
+class EntityGetResponse(BaseModel):
+ id: str
+
+ created_at: datetime
+
+ name: str
+
+ status: Literal["provisional", "confirmed"]
+ """How strongly the entity's current identity has been established."""
+
+ type: str
+
+ updated_at: datetime
+
+ attributes: Optional[Dict[str, object]] = None
+
+ description: Optional[str] = None
+
+ hard_linked_mention_count: Optional[int] = None
+
+ prominence_calculated_at: Optional[datetime] = None
+
+ prominence_version: Optional[str] = None
+
+ record_count: Optional[int] = None
+
+ supporting_document_count: Optional[int] = None
+
+ supporting_scope_count: Optional[int] = None
diff --git a/src/hyperspell/types/entity_list_params.py b/src/hyperspell/types/entity_list_params.py
new file mode 100644
index 00000000..5964c0b7
--- /dev/null
+++ b/src/hyperspell/types/entity_list_params.py
@@ -0,0 +1,29 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Optional
+from typing_extensions import Literal, TypedDict
+
+__all__ = ["EntityListParams"]
+
+
+class EntityListParams(TypedDict, total=False):
+ cursor: Optional[str]
+
+ limit: int
+
+ min_supporting_documents: Optional[int]
+
+ name_prefix: Optional[str]
+
+ search: Optional[str]
+
+ sort_by: Literal["id", "name", "type", "prominence"]
+
+ sort_dir: Literal["asc", "desc"]
+
+ status: Optional[Literal["provisional", "confirmed"]]
+ """How strongly the entity's current identity has been established."""
+
+ type: Optional[str]
diff --git a/src/hyperspell/types/entity_list_response.py b/src/hyperspell/types/entity_list_response.py
new file mode 100644
index 00000000..03db93f6
--- /dev/null
+++ b/src/hyperspell/types/entity_list_response.py
@@ -0,0 +1,40 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Dict, Optional
+from datetime import datetime
+from typing_extensions import Literal
+
+from .._models import BaseModel
+
+__all__ = ["EntityListResponse"]
+
+
+class EntityListResponse(BaseModel):
+ id: str
+
+ created_at: datetime
+
+ name: str
+
+ status: Literal["provisional", "confirmed"]
+ """How strongly the entity's current identity has been established."""
+
+ type: str
+
+ updated_at: datetime
+
+ attributes: Optional[Dict[str, object]] = None
+
+ description: Optional[str] = None
+
+ hard_linked_mention_count: Optional[int] = None
+
+ prominence_calculated_at: Optional[datetime] = None
+
+ prominence_version: Optional[str] = None
+
+ record_count: Optional[int] = None
+
+ supporting_document_count: Optional[int] = None
+
+ supporting_scope_count: Optional[int] = None
diff --git a/src/hyperspell/types/entity_search_params.py b/src/hyperspell/types/entity_search_params.py
new file mode 100644
index 00000000..4a2f7406
--- /dev/null
+++ b/src/hyperspell/types/entity_search_params.py
@@ -0,0 +1,16 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Optional
+from typing_extensions import Required, TypedDict
+
+__all__ = ["EntitySearchParams"]
+
+
+class EntitySearchParams(TypedDict, total=False):
+ query: Required[str]
+
+ limit: int
+
+ type: Optional[str]
diff --git a/src/hyperspell/types/entity_search_response.py b/src/hyperspell/types/entity_search_response.py
new file mode 100644
index 00000000..a837a1d9
--- /dev/null
+++ b/src/hyperspell/types/entity_search_response.py
@@ -0,0 +1,46 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Dict, List, Optional
+from datetime import datetime
+from typing_extensions import Literal
+
+from .._models import BaseModel
+
+__all__ = ["EntitySearchResponse", "Item"]
+
+
+class Item(BaseModel):
+ id: str
+
+ created_at: datetime
+
+ name: str
+
+ similarity: float
+
+ status: Literal["provisional", "confirmed"]
+ """How strongly the entity's current identity has been established."""
+
+ type: str
+
+ updated_at: datetime
+
+ attributes: Optional[Dict[str, object]] = None
+
+ description: Optional[str] = None
+
+ hard_linked_mention_count: Optional[int] = None
+
+ prominence_calculated_at: Optional[datetime] = None
+
+ prominence_version: Optional[str] = None
+
+ record_count: Optional[int] = None
+
+ supporting_document_count: Optional[int] = None
+
+ supporting_scope_count: Optional[int] = None
+
+
+class EntitySearchResponse(BaseModel):
+ items: List[Item]
diff --git a/src/hyperspell/types/live_get_resource_params.py b/src/hyperspell/types/live_get_resource_params.py
new file mode 100644
index 00000000..1309935d
--- /dev/null
+++ b/src/hyperspell/types/live_get_resource_params.py
@@ -0,0 +1,56 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Optional
+from typing_extensions import Literal, Required, TypedDict
+
+__all__ = ["LiveGetResourceParams"]
+
+
+class LiveGetResourceParams(TypedDict, total=False):
+ source: Required[
+ Literal[
+ "reddit",
+ "notion",
+ "slack",
+ "google_calendar",
+ "google_mail",
+ "imap",
+ "google_meet",
+ "box",
+ "dropbox",
+ "github",
+ "gitlab",
+ "google_drive",
+ "vault",
+ "web_crawler",
+ "trace",
+ "microsoft_outlook",
+ "microsoft_teams",
+ "granola",
+ "fathom",
+ "fireflies",
+ "figma",
+ "linear",
+ "hubspot",
+ "salesforce",
+ "coda",
+ "confluence",
+ "jira",
+ "metabase",
+ "gong",
+ "clickup",
+ "lightfield",
+ "pylon",
+ "fellow",
+ "odoo",
+ "external_mcp",
+ ]
+ ]
+
+ connection_id: Optional[str]
+ """Specific connection id."""
+
+ index: bool
+ """Also queue this resource for indexing."""
diff --git a/src/hyperspell/types/live_get_resource_response.py b/src/hyperspell/types/live_get_resource_response.py
new file mode 100644
index 00000000..e1889705
--- /dev/null
+++ b/src/hyperspell/types/live_get_resource_response.py
@@ -0,0 +1,282 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Dict, List as TypingList, Union, Optional
+from datetime import datetime
+from typing_extensions import Literal, Annotated, TypeAlias
+
+from .._utils import PropertyInfo
+from .._models import BaseModel
+from .shared.blob import Blob
+from .shared.code import Code
+from .shared.link import Link
+from .shared.text import Text
+from .shared.image import Image
+from .shared.trace import Trace
+from .shared.comment import Comment
+from .shared.divider import Divider
+from .shared.metadata import Metadata
+from .shared.tool_call import ToolCall
+from .shared.line_break import LineBreak
+from .shared.tool_result import ToolResult
+from .shared.trace_message import TraceMessage
+
+__all__ = [
+ "LiveGetResourceResponse",
+ "Document",
+ "DocumentDocument",
+ "DocumentDocumentInvoice",
+ "DocumentDocumentInvoiceChild",
+ "DocumentChunk",
+]
+
+DocumentDocumentInvoiceChild: TypeAlias = Annotated[
+ Union[
+ Blob,
+ "Callout",
+ "Chunk",
+ Code,
+ Comment,
+ Divider,
+ "Equation",
+ "Footnote",
+ "Heading",
+ Image,
+ Link,
+ LineBreak,
+ "SharedList",
+ "ListItem",
+ "Page",
+ "Paragraph",
+ "Quote",
+ "Table",
+ "TableCell",
+ "TableRow",
+ Text,
+ "ToDo",
+ ToolCall,
+ ToolResult,
+ TraceMessage,
+ "Utterance",
+ ],
+ PropertyInfo(discriminator="type"),
+]
+
+
+class DocumentDocumentInvoice(BaseModel):
+ """A customer invoice, vendor bill, or credit memo.
+
+ Line items are included in ``children``.
+ """
+
+ id: Optional[str] = None
+
+ attachment_names: Optional[TypingList[str]] = None
+
+ balance_amount: Optional[float] = None
+
+ cancelled_at: Optional[datetime] = None
+
+ children: Optional[TypingList[DocumentDocumentInvoiceChild]] = None
+
+ contact_id: Optional[str] = None
+
+ contact_name: Optional[str] = None
+
+ currency: Optional[str] = None
+
+ due_at: Optional[datetime] = None
+
+ invoice_type: Optional[str] = None
+
+ metadata: Optional[Metadata] = None
+ """Optional annotations carried by a hyperdoc node.
+
+ Includes source provenance and human edit attribution. Unset metadata is omitted
+ from serialized responses.
+ """
+
+ notes: Optional[str] = None
+
+ number: Optional[str] = None
+
+ organization_id: Optional[str] = None
+
+ paid_amount: Optional[float] = None
+
+ paid_at: Optional[datetime] = None
+
+ posted_at: Optional[datetime] = None
+
+ reference: Optional[str] = None
+
+ refund_amount: Optional[float] = None
+
+ refund_reason: Optional[str] = None
+
+ refunded_at: Optional[datetime] = None
+
+ status: Optional[str] = None
+
+ tax_amount: Optional[float] = None
+
+ text: Optional[str] = None
+
+ total_amount: Optional[float] = None
+
+ type: Optional[Literal["invoice"]] = None
+
+
+DocumentDocument: TypeAlias = Annotated[
+ Union[
+ "document.Document",
+ "Website",
+ "Task",
+ "Person",
+ "Message",
+ "Event",
+ "File",
+ "Conversation",
+ Trace,
+ "Transcript",
+ "Company",
+ "Deal",
+ DocumentDocumentInvoice,
+ ],
+ PropertyInfo(discriminator="type"),
+]
+
+
+class DocumentChunk(BaseModel):
+ """A searchable chunk extracted from a document during ingestion.
+
+ `summary` is null when no summary was generated for the chunk.
+ """
+
+ chunk_id: str
+ """Stable identifier of the chunk."""
+
+ summary: Optional[str] = None
+ """LLM-generated summary of the chunk, if one was produced."""
+
+
+class Document(BaseModel):
+ """A document-shaped API response containing the hyperdoc tree."""
+
+ document: DocumentDocument
+ """The full hyperdoc tree.
+
+ Switch on `type` for the document frame and recurse through `children` for the
+ body.
+ """
+
+ resource_id: str
+
+ source: Literal[
+ "reddit",
+ "notion",
+ "slack",
+ "google_calendar",
+ "google_mail",
+ "imap",
+ "google_meet",
+ "box",
+ "dropbox",
+ "github",
+ "gitlab",
+ "google_drive",
+ "vault",
+ "web_crawler",
+ "trace",
+ "microsoft_outlook",
+ "microsoft_teams",
+ "granola",
+ "fathom",
+ "fireflies",
+ "figma",
+ "linear",
+ "hubspot",
+ "salesforce",
+ "coda",
+ "confluence",
+ "jira",
+ "metabase",
+ "gong",
+ "clickup",
+ "lightfield",
+ "pylon",
+ "fellow",
+ "odoo",
+ "external_mcp",
+ ]
+
+ type: str
+ """Hyperdoc document type discriminator (document, message, file, event, ...)."""
+
+ chunks: Optional[TypingList[DocumentChunk]] = None
+ """Extracted memories (chunks with summaries) for this document, in document order.
+
+ Present only when explicitly requested via `include_chunks`; omitted otherwise.
+ """
+
+ collection: Optional[str] = None
+ """The document's collection, if any."""
+
+ document_date: Optional[datetime] = None
+ """The document's own date (e.g. email sent date, event date)."""
+
+ ingested_at: Optional[datetime] = None
+ """When Hyperspell first indexed the document."""
+
+ last_modified_at: Optional[datetime] = None
+ """When the source document was last modified, if supplied by the source."""
+
+ metadata: Optional[Dict[str, object]] = None
+ """Filterable custom metadata attached to the document."""
+
+ status: Optional[
+ Literal["pending", "processing", "completed", "failed", "pending_review", "skipped", "filtered", "cancelled"]
+ ] = None
+ """Indexing status of the document."""
+
+ title: Optional[str] = None
+ """Human-readable document title."""
+
+
+class LiveGetResourceResponse(BaseModel):
+ """A fetch/search result: the live documents plus what happened to them."""
+
+ documents: TypingList[Document]
+
+ indexed: Optional[bool] = None
+
+ notes: Optional[TypingList[str]] = None
+
+
+from .shared import document
+from .shared.deal import Deal
+from .shared.file import File
+from .shared.list import List as SharedList
+from .shared.page import Page
+from .shared.task import Task
+from .shared.chunk import Chunk
+from .shared.event import Event
+from .shared.quote import Quote
+from .shared.table import Table
+from .shared.to_do import ToDo
+from .shared.person import Person
+from .shared.callout import Callout
+from .shared.company import Company
+from .shared.heading import Heading
+from .shared.message import Message
+from .shared.website import Website
+from .shared.equation import Equation
+from .shared.footnote import Footnote
+from .shared.list_item import ListItem
+from .shared.paragraph import Paragraph
+from .shared.table_row import TableRow
+from .shared.utterance import Utterance
+from .shared.table_cell import TableCell
+from .shared.transcript import Transcript
+from .shared.conversation import Conversation
diff --git a/src/hyperspell/types/live_list_resources_params.py b/src/hyperspell/types/live_list_resources_params.py
new file mode 100644
index 00000000..ce85b74d
--- /dev/null
+++ b/src/hyperspell/types/live_list_resources_params.py
@@ -0,0 +1,17 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Optional
+from typing_extensions import TypedDict
+
+__all__ = ["LiveListResourcesParams"]
+
+
+class LiveListResourcesParams(TypedDict, total=False):
+ connection_id: Optional[str]
+ """Specific connection id."""
+
+ cursor: Optional[str]
+
+ size: int
diff --git a/src/hyperspell/types/live_list_resources_response.py b/src/hyperspell/types/live_list_resources_response.py
new file mode 100644
index 00000000..9dd705fe
--- /dev/null
+++ b/src/hyperspell/types/live_list_resources_response.py
@@ -0,0 +1,264 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Dict, List as TypingList, Union, Optional
+from datetime import datetime
+from typing_extensions import Literal, Annotated, TypeAlias
+
+from .._utils import PropertyInfo
+from .._models import BaseModel
+from .shared.blob import Blob
+from .shared.code import Code
+from .shared.link import Link
+from .shared.text import Text
+from .shared.image import Image
+from .shared.trace import Trace
+from .shared.comment import Comment
+from .shared.divider import Divider
+from .shared.metadata import Metadata
+from .shared.tool_call import ToolCall
+from .shared.line_break import LineBreak
+from .shared.tool_result import ToolResult
+from .shared.trace_message import TraceMessage
+
+__all__ = ["LiveListResourcesResponse", "Document", "DocumentInvoice", "DocumentInvoiceChild", "Chunk"]
+
+DocumentInvoiceChild: TypeAlias = Annotated[
+ Union[
+ Blob,
+ "Callout",
+ "chunk.Chunk",
+ Code,
+ Comment,
+ Divider,
+ "Equation",
+ "Footnote",
+ "Heading",
+ Image,
+ Link,
+ LineBreak,
+ "SharedList",
+ "ListItem",
+ "Page",
+ "Paragraph",
+ "Quote",
+ "Table",
+ "TableCell",
+ "TableRow",
+ Text,
+ "ToDo",
+ ToolCall,
+ ToolResult,
+ TraceMessage,
+ "Utterance",
+ ],
+ PropertyInfo(discriminator="type"),
+]
+
+
+class DocumentInvoice(BaseModel):
+ """A customer invoice, vendor bill, or credit memo.
+
+ Line items are included in ``children``.
+ """
+
+ id: Optional[str] = None
+
+ attachment_names: Optional[TypingList[str]] = None
+
+ balance_amount: Optional[float] = None
+
+ cancelled_at: Optional[datetime] = None
+
+ children: Optional[TypingList[DocumentInvoiceChild]] = None
+
+ contact_id: Optional[str] = None
+
+ contact_name: Optional[str] = None
+
+ currency: Optional[str] = None
+
+ due_at: Optional[datetime] = None
+
+ invoice_type: Optional[str] = None
+
+ metadata: Optional[Metadata] = None
+ """Optional annotations carried by a hyperdoc node.
+
+ Includes source provenance and human edit attribution. Unset metadata is omitted
+ from serialized responses.
+ """
+
+ notes: Optional[str] = None
+
+ number: Optional[str] = None
+
+ organization_id: Optional[str] = None
+
+ paid_amount: Optional[float] = None
+
+ paid_at: Optional[datetime] = None
+
+ posted_at: Optional[datetime] = None
+
+ reference: Optional[str] = None
+
+ refund_amount: Optional[float] = None
+
+ refund_reason: Optional[str] = None
+
+ refunded_at: Optional[datetime] = None
+
+ status: Optional[str] = None
+
+ tax_amount: Optional[float] = None
+
+ text: Optional[str] = None
+
+ total_amount: Optional[float] = None
+
+ type: Optional[Literal["invoice"]] = None
+
+
+Document: TypeAlias = Annotated[
+ Union[
+ "document.Document",
+ "Website",
+ "Task",
+ "Person",
+ "Message",
+ "Event",
+ "File",
+ "Conversation",
+ Trace,
+ "Transcript",
+ "Company",
+ "Deal",
+ DocumentInvoice,
+ ],
+ PropertyInfo(discriminator="type"),
+]
+
+
+class Chunk(BaseModel):
+ """A searchable chunk extracted from a document during ingestion.
+
+ `summary` is null when no summary was generated for the chunk.
+ """
+
+ chunk_id: str
+ """Stable identifier of the chunk."""
+
+ summary: Optional[str] = None
+ """LLM-generated summary of the chunk, if one was produced."""
+
+
+class LiveListResourcesResponse(BaseModel):
+ """A document-shaped API response containing the hyperdoc tree."""
+
+ document: Document
+ """The full hyperdoc tree.
+
+ Switch on `type` for the document frame and recurse through `children` for the
+ body.
+ """
+
+ resource_id: str
+
+ source: Literal[
+ "reddit",
+ "notion",
+ "slack",
+ "google_calendar",
+ "google_mail",
+ "imap",
+ "google_meet",
+ "box",
+ "dropbox",
+ "github",
+ "gitlab",
+ "google_drive",
+ "vault",
+ "web_crawler",
+ "trace",
+ "microsoft_outlook",
+ "microsoft_teams",
+ "granola",
+ "fathom",
+ "fireflies",
+ "figma",
+ "linear",
+ "hubspot",
+ "salesforce",
+ "coda",
+ "confluence",
+ "jira",
+ "metabase",
+ "gong",
+ "clickup",
+ "lightfield",
+ "pylon",
+ "fellow",
+ "odoo",
+ "external_mcp",
+ ]
+
+ type: str
+ """Hyperdoc document type discriminator (document, message, file, event, ...)."""
+
+ chunks: Optional[TypingList[Chunk]] = None
+ """Extracted memories (chunks with summaries) for this document, in document order.
+
+ Present only when explicitly requested via `include_chunks`; omitted otherwise.
+ """
+
+ collection: Optional[str] = None
+ """The document's collection, if any."""
+
+ document_date: Optional[datetime] = None
+ """The document's own date (e.g. email sent date, event date)."""
+
+ ingested_at: Optional[datetime] = None
+ """When Hyperspell first indexed the document."""
+
+ last_modified_at: Optional[datetime] = None
+ """When the source document was last modified, if supplied by the source."""
+
+ metadata: Optional[Dict[str, object]] = None
+ """Filterable custom metadata attached to the document."""
+
+ status: Optional[
+ Literal["pending", "processing", "completed", "failed", "pending_review", "skipped", "filtered", "cancelled"]
+ ] = None
+ """Indexing status of the document."""
+
+ title: Optional[str] = None
+ """Human-readable document title."""
+
+
+from .shared import chunk, document
+from .shared.deal import Deal
+from .shared.file import File
+from .shared.list import List as SharedList
+from .shared.page import Page
+from .shared.task import Task
+from .shared.event import Event
+from .shared.quote import Quote
+from .shared.table import Table
+from .shared.to_do import ToDo
+from .shared.person import Person
+from .shared.callout import Callout
+from .shared.company import Company
+from .shared.heading import Heading
+from .shared.message import Message
+from .shared.website import Website
+from .shared.equation import Equation
+from .shared.footnote import Footnote
+from .shared.list_item import ListItem
+from .shared.paragraph import Paragraph
+from .shared.table_row import TableRow
+from .shared.utterance import Utterance
+from .shared.table_cell import TableCell
+from .shared.transcript import Transcript
+from .shared.conversation import Conversation
diff --git a/src/hyperspell/types/live_list_sources_response.py b/src/hyperspell/types/live_list_sources_response.py
new file mode 100644
index 00000000..2507b899
--- /dev/null
+++ b/src/hyperspell/types/live_list_sources_response.py
@@ -0,0 +1,61 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Union
+from typing_extensions import Literal
+
+from .._models import BaseModel
+
+__all__ = ["LiveListSourcesResponse", "Source"]
+
+
+class Source(BaseModel):
+ auth_provider: Literal["nango", "unified", "whitelabel"]
+
+ capabilities: List[
+ Literal["list_resources", "fetch_resource", "search_live", "passthrough", "resolve", "query_structured"]
+ ]
+
+ source: Union[
+ Literal[
+ "reddit",
+ "notion",
+ "slack",
+ "google_calendar",
+ "google_mail",
+ "imap",
+ "google_meet",
+ "box",
+ "dropbox",
+ "github",
+ "gitlab",
+ "google_drive",
+ "vault",
+ "web_crawler",
+ "trace",
+ "microsoft_outlook",
+ "microsoft_teams",
+ "granola",
+ "fathom",
+ "fireflies",
+ "figma",
+ "linear",
+ "hubspot",
+ "salesforce",
+ "coda",
+ "confluence",
+ "jira",
+ "metabase",
+ "gong",
+ "clickup",
+ "lightfield",
+ "pylon",
+ "fellow",
+ "odoo",
+ "external_mcp",
+ ],
+ str,
+ ]
+
+
+class LiveListSourcesResponse(BaseModel):
+ sources: List[Source]
diff --git a/src/hyperspell/types/live_search_params.py b/src/hyperspell/types/live_search_params.py
new file mode 100644
index 00000000..cfb05b07
--- /dev/null
+++ b/src/hyperspell/types/live_search_params.py
@@ -0,0 +1,19 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Optional
+from typing_extensions import Required, TypedDict
+
+__all__ = ["LiveSearchParams"]
+
+
+class LiveSearchParams(TypedDict, total=False):
+ query: Required[str]
+ """Live search query."""
+
+ connection_id: Optional[str]
+ """Specific connection id when the user has multiple for this source."""
+
+ index: bool
+ """If true, queue each hit for indexing so it's on-hand next time."""
diff --git a/src/hyperspell/types/live_search_response.py b/src/hyperspell/types/live_search_response.py
new file mode 100644
index 00000000..85161682
--- /dev/null
+++ b/src/hyperspell/types/live_search_response.py
@@ -0,0 +1,282 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Dict, List as TypingList, Union, Optional
+from datetime import datetime
+from typing_extensions import Literal, Annotated, TypeAlias
+
+from .._utils import PropertyInfo
+from .._models import BaseModel
+from .shared.blob import Blob
+from .shared.code import Code
+from .shared.link import Link
+from .shared.text import Text
+from .shared.image import Image
+from .shared.trace import Trace
+from .shared.comment import Comment
+from .shared.divider import Divider
+from .shared.metadata import Metadata
+from .shared.tool_call import ToolCall
+from .shared.line_break import LineBreak
+from .shared.tool_result import ToolResult
+from .shared.trace_message import TraceMessage
+
+__all__ = [
+ "LiveSearchResponse",
+ "Document",
+ "DocumentDocument",
+ "DocumentDocumentInvoice",
+ "DocumentDocumentInvoiceChild",
+ "DocumentChunk",
+]
+
+DocumentDocumentInvoiceChild: TypeAlias = Annotated[
+ Union[
+ Blob,
+ "Callout",
+ "Chunk",
+ Code,
+ Comment,
+ Divider,
+ "Equation",
+ "Footnote",
+ "Heading",
+ Image,
+ Link,
+ LineBreak,
+ "SharedList",
+ "ListItem",
+ "Page",
+ "Paragraph",
+ "Quote",
+ "Table",
+ "TableCell",
+ "TableRow",
+ Text,
+ "ToDo",
+ ToolCall,
+ ToolResult,
+ TraceMessage,
+ "Utterance",
+ ],
+ PropertyInfo(discriminator="type"),
+]
+
+
+class DocumentDocumentInvoice(BaseModel):
+ """A customer invoice, vendor bill, or credit memo.
+
+ Line items are included in ``children``.
+ """
+
+ id: Optional[str] = None
+
+ attachment_names: Optional[TypingList[str]] = None
+
+ balance_amount: Optional[float] = None
+
+ cancelled_at: Optional[datetime] = None
+
+ children: Optional[TypingList[DocumentDocumentInvoiceChild]] = None
+
+ contact_id: Optional[str] = None
+
+ contact_name: Optional[str] = None
+
+ currency: Optional[str] = None
+
+ due_at: Optional[datetime] = None
+
+ invoice_type: Optional[str] = None
+
+ metadata: Optional[Metadata] = None
+ """Optional annotations carried by a hyperdoc node.
+
+ Includes source provenance and human edit attribution. Unset metadata is omitted
+ from serialized responses.
+ """
+
+ notes: Optional[str] = None
+
+ number: Optional[str] = None
+
+ organization_id: Optional[str] = None
+
+ paid_amount: Optional[float] = None
+
+ paid_at: Optional[datetime] = None
+
+ posted_at: Optional[datetime] = None
+
+ reference: Optional[str] = None
+
+ refund_amount: Optional[float] = None
+
+ refund_reason: Optional[str] = None
+
+ refunded_at: Optional[datetime] = None
+
+ status: Optional[str] = None
+
+ tax_amount: Optional[float] = None
+
+ text: Optional[str] = None
+
+ total_amount: Optional[float] = None
+
+ type: Optional[Literal["invoice"]] = None
+
+
+DocumentDocument: TypeAlias = Annotated[
+ Union[
+ "document.Document",
+ "Website",
+ "Task",
+ "Person",
+ "Message",
+ "Event",
+ "File",
+ "Conversation",
+ Trace,
+ "Transcript",
+ "Company",
+ "Deal",
+ DocumentDocumentInvoice,
+ ],
+ PropertyInfo(discriminator="type"),
+]
+
+
+class DocumentChunk(BaseModel):
+ """A searchable chunk extracted from a document during ingestion.
+
+ `summary` is null when no summary was generated for the chunk.
+ """
+
+ chunk_id: str
+ """Stable identifier of the chunk."""
+
+ summary: Optional[str] = None
+ """LLM-generated summary of the chunk, if one was produced."""
+
+
+class Document(BaseModel):
+ """A document-shaped API response containing the hyperdoc tree."""
+
+ document: DocumentDocument
+ """The full hyperdoc tree.
+
+ Switch on `type` for the document frame and recurse through `children` for the
+ body.
+ """
+
+ resource_id: str
+
+ source: Literal[
+ "reddit",
+ "notion",
+ "slack",
+ "google_calendar",
+ "google_mail",
+ "imap",
+ "google_meet",
+ "box",
+ "dropbox",
+ "github",
+ "gitlab",
+ "google_drive",
+ "vault",
+ "web_crawler",
+ "trace",
+ "microsoft_outlook",
+ "microsoft_teams",
+ "granola",
+ "fathom",
+ "fireflies",
+ "figma",
+ "linear",
+ "hubspot",
+ "salesforce",
+ "coda",
+ "confluence",
+ "jira",
+ "metabase",
+ "gong",
+ "clickup",
+ "lightfield",
+ "pylon",
+ "fellow",
+ "odoo",
+ "external_mcp",
+ ]
+
+ type: str
+ """Hyperdoc document type discriminator (document, message, file, event, ...)."""
+
+ chunks: Optional[TypingList[DocumentChunk]] = None
+ """Extracted memories (chunks with summaries) for this document, in document order.
+
+ Present only when explicitly requested via `include_chunks`; omitted otherwise.
+ """
+
+ collection: Optional[str] = None
+ """The document's collection, if any."""
+
+ document_date: Optional[datetime] = None
+ """The document's own date (e.g. email sent date, event date)."""
+
+ ingested_at: Optional[datetime] = None
+ """When Hyperspell first indexed the document."""
+
+ last_modified_at: Optional[datetime] = None
+ """When the source document was last modified, if supplied by the source."""
+
+ metadata: Optional[Dict[str, object]] = None
+ """Filterable custom metadata attached to the document."""
+
+ status: Optional[
+ Literal["pending", "processing", "completed", "failed", "pending_review", "skipped", "filtered", "cancelled"]
+ ] = None
+ """Indexing status of the document."""
+
+ title: Optional[str] = None
+ """Human-readable document title."""
+
+
+class LiveSearchResponse(BaseModel):
+ """A fetch/search result: the live documents plus what happened to them."""
+
+ documents: TypingList[Document]
+
+ indexed: Optional[bool] = None
+
+ notes: Optional[TypingList[str]] = None
+
+
+from .shared import document
+from .shared.deal import Deal
+from .shared.file import File
+from .shared.list import List as SharedList
+from .shared.page import Page
+from .shared.task import Task
+from .shared.chunk import Chunk
+from .shared.event import Event
+from .shared.quote import Quote
+from .shared.table import Table
+from .shared.to_do import ToDo
+from .shared.person import Person
+from .shared.callout import Callout
+from .shared.company import Company
+from .shared.heading import Heading
+from .shared.message import Message
+from .shared.website import Website
+from .shared.equation import Equation
+from .shared.footnote import Footnote
+from .shared.list_item import ListItem
+from .shared.paragraph import Paragraph
+from .shared.table_row import TableRow
+from .shared.utterance import Utterance
+from .shared.table_cell import TableCell
+from .shared.transcript import Transcript
+from .shared.conversation import Conversation
diff --git a/tests/api_resources/context_documents/__init__.py b/tests/api_resources/context_documents/__init__.py
deleted file mode 100644
index fd8019a9..00000000
--- a/tests/api_resources/context_documents/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
diff --git a/tests/api_resources/context_documents/test_config.py b/tests/api_resources/context_documents/test_config.py
deleted file mode 100644
index 1ba55a06..00000000
--- a/tests/api_resources/context_documents/test_config.py
+++ /dev/null
@@ -1,238 +0,0 @@
-# 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 hyperspell import Hyperspell, AsyncHyperspell
-from tests.utils import assert_matches_type
-from hyperspell.types.context_documents import (
- ConfigGetResponse,
- ConfigResetResponse,
- ConfigUpdateResponse,
-)
-
-base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
-
-
-class TestConfig:
- parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
-
- @parametrize
- def test_method_update(self, client: Hyperspell) -> None:
- config = client.context_documents.config.update()
- assert_matches_type(ConfigUpdateResponse, config, path=["response"])
-
- @parametrize
- def test_method_update_with_all_params(self, client: Hyperspell) -> None:
- config = client.context_documents.config.update(
- company_prompts={"foo": "string"},
- detection_prompt="detection_prompt",
- domain="domain",
- personal_prompt="personal_prompt",
- source_weights={"foo": "string"},
- structure={
- "company": [
- {
- "filename": "filename",
- "key": "key",
- "prompt": "prompt",
- "search_queries": ["string"],
- }
- ],
- "workstream": [
- {
- "filename": "filename",
- "key": "key",
- "prompt": "prompt",
- "search_queries": ["string"],
- }
- ],
- },
- workstream_prompts={"foo": "string"},
- )
- assert_matches_type(ConfigUpdateResponse, config, path=["response"])
-
- @parametrize
- def test_raw_response_update(self, client: Hyperspell) -> None:
- response = client.context_documents.config.with_raw_response.update()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- config = response.parse()
- assert_matches_type(ConfigUpdateResponse, config, path=["response"])
-
- @parametrize
- def test_streaming_response_update(self, client: Hyperspell) -> None:
- with client.context_documents.config.with_streaming_response.update() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- config = response.parse()
- assert_matches_type(ConfigUpdateResponse, config, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @parametrize
- def test_method_get(self, client: Hyperspell) -> None:
- config = client.context_documents.config.get()
- assert_matches_type(ConfigGetResponse, config, path=["response"])
-
- @parametrize
- def test_raw_response_get(self, client: Hyperspell) -> None:
- response = client.context_documents.config.with_raw_response.get()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- config = response.parse()
- assert_matches_type(ConfigGetResponse, config, path=["response"])
-
- @parametrize
- def test_streaming_response_get(self, client: Hyperspell) -> None:
- with client.context_documents.config.with_streaming_response.get() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- config = response.parse()
- assert_matches_type(ConfigGetResponse, config, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @parametrize
- def test_method_reset(self, client: Hyperspell) -> None:
- config = client.context_documents.config.reset()
- assert_matches_type(ConfigResetResponse, config, path=["response"])
-
- @parametrize
- def test_raw_response_reset(self, client: Hyperspell) -> None:
- response = client.context_documents.config.with_raw_response.reset()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- config = response.parse()
- assert_matches_type(ConfigResetResponse, config, path=["response"])
-
- @parametrize
- def test_streaming_response_reset(self, client: Hyperspell) -> None:
- with client.context_documents.config.with_streaming_response.reset() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- config = response.parse()
- assert_matches_type(ConfigResetResponse, config, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
-
-class TestAsyncConfig:
- parametrize = pytest.mark.parametrize(
- "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
- )
-
- @parametrize
- async def test_method_update(self, async_client: AsyncHyperspell) -> None:
- config = await async_client.context_documents.config.update()
- assert_matches_type(ConfigUpdateResponse, config, path=["response"])
-
- @parametrize
- async def test_method_update_with_all_params(self, async_client: AsyncHyperspell) -> None:
- config = await async_client.context_documents.config.update(
- company_prompts={"foo": "string"},
- detection_prompt="detection_prompt",
- domain="domain",
- personal_prompt="personal_prompt",
- source_weights={"foo": "string"},
- structure={
- "company": [
- {
- "filename": "filename",
- "key": "key",
- "prompt": "prompt",
- "search_queries": ["string"],
- }
- ],
- "workstream": [
- {
- "filename": "filename",
- "key": "key",
- "prompt": "prompt",
- "search_queries": ["string"],
- }
- ],
- },
- workstream_prompts={"foo": "string"},
- )
- assert_matches_type(ConfigUpdateResponse, config, path=["response"])
-
- @parametrize
- async def test_raw_response_update(self, async_client: AsyncHyperspell) -> None:
- response = await async_client.context_documents.config.with_raw_response.update()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- config = await response.parse()
- assert_matches_type(ConfigUpdateResponse, config, path=["response"])
-
- @parametrize
- async def test_streaming_response_update(self, async_client: AsyncHyperspell) -> None:
- async with async_client.context_documents.config.with_streaming_response.update() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- config = await response.parse()
- assert_matches_type(ConfigUpdateResponse, config, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @parametrize
- async def test_method_get(self, async_client: AsyncHyperspell) -> None:
- config = await async_client.context_documents.config.get()
- assert_matches_type(ConfigGetResponse, config, path=["response"])
-
- @parametrize
- async def test_raw_response_get(self, async_client: AsyncHyperspell) -> None:
- response = await async_client.context_documents.config.with_raw_response.get()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- config = await response.parse()
- assert_matches_type(ConfigGetResponse, config, path=["response"])
-
- @parametrize
- async def test_streaming_response_get(self, async_client: AsyncHyperspell) -> None:
- async with async_client.context_documents.config.with_streaming_response.get() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- config = await response.parse()
- assert_matches_type(ConfigGetResponse, config, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @parametrize
- async def test_method_reset(self, async_client: AsyncHyperspell) -> None:
- config = await async_client.context_documents.config.reset()
- assert_matches_type(ConfigResetResponse, config, path=["response"])
-
- @parametrize
- async def test_raw_response_reset(self, async_client: AsyncHyperspell) -> None:
- response = await async_client.context_documents.config.with_raw_response.reset()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- config = await response.parse()
- assert_matches_type(ConfigResetResponse, config, path=["response"])
-
- @parametrize
- async def test_streaming_response_reset(self, async_client: AsyncHyperspell) -> None:
- async with async_client.context_documents.config.with_streaming_response.reset() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- config = await response.parse()
- assert_matches_type(ConfigResetResponse, config, path=["response"])
-
- assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/context_documents/test_digests.py b/tests/api_resources/context_documents/test_digests.py
deleted file mode 100644
index c895de3e..00000000
--- a/tests/api_resources/context_documents/test_digests.py
+++ /dev/null
@@ -1,164 +0,0 @@
-# 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 hyperspell import Hyperspell, AsyncHyperspell
-from tests.utils import assert_matches_type
-from hyperspell._utils import parse_datetime
-from hyperspell.types.context_documents import (
- DigestListResponse,
- DigestGenerateResponse,
-)
-
-base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
-
-
-class TestDigests:
- parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
-
- @parametrize
- def test_method_list(self, client: Hyperspell) -> None:
- digest = client.context_documents.digests.list()
- assert_matches_type(DigestListResponse, digest, path=["response"])
-
- @parametrize
- def test_method_list_with_all_params(self, client: Hyperspell) -> None:
- digest = client.context_documents.digests.list(
- limit=0,
- period="period",
- )
- assert_matches_type(DigestListResponse, digest, path=["response"])
-
- @parametrize
- def test_raw_response_list(self, client: Hyperspell) -> None:
- response = client.context_documents.digests.with_raw_response.list()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- digest = response.parse()
- assert_matches_type(DigestListResponse, digest, path=["response"])
-
- @parametrize
- def test_streaming_response_list(self, client: Hyperspell) -> None:
- with client.context_documents.digests.with_streaming_response.list() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- digest = response.parse()
- assert_matches_type(DigestListResponse, digest, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @parametrize
- def test_method_generate(self, client: Hyperspell) -> None:
- digest = client.context_documents.digests.generate()
- assert_matches_type(DigestGenerateResponse, digest, path=["response"])
-
- @parametrize
- def test_method_generate_with_all_params(self, client: Hyperspell) -> None:
- digest = client.context_documents.digests.generate(
- period="period",
- sources=["string"],
- window_end=parse_datetime("2019-12-27T18:11:19.117Z"),
- window_start=parse_datetime("2019-12-27T18:11:19.117Z"),
- )
- assert_matches_type(DigestGenerateResponse, digest, path=["response"])
-
- @parametrize
- def test_raw_response_generate(self, client: Hyperspell) -> None:
- response = client.context_documents.digests.with_raw_response.generate()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- digest = response.parse()
- assert_matches_type(DigestGenerateResponse, digest, path=["response"])
-
- @parametrize
- def test_streaming_response_generate(self, client: Hyperspell) -> None:
- with client.context_documents.digests.with_streaming_response.generate() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- digest = response.parse()
- assert_matches_type(DigestGenerateResponse, digest, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
-
-class TestAsyncDigests:
- parametrize = pytest.mark.parametrize(
- "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
- )
-
- @parametrize
- async def test_method_list(self, async_client: AsyncHyperspell) -> None:
- digest = await async_client.context_documents.digests.list()
- assert_matches_type(DigestListResponse, digest, path=["response"])
-
- @parametrize
- async def test_method_list_with_all_params(self, async_client: AsyncHyperspell) -> None:
- digest = await async_client.context_documents.digests.list(
- limit=0,
- period="period",
- )
- assert_matches_type(DigestListResponse, digest, path=["response"])
-
- @parametrize
- async def test_raw_response_list(self, async_client: AsyncHyperspell) -> None:
- response = await async_client.context_documents.digests.with_raw_response.list()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- digest = await response.parse()
- assert_matches_type(DigestListResponse, digest, path=["response"])
-
- @parametrize
- async def test_streaming_response_list(self, async_client: AsyncHyperspell) -> None:
- async with async_client.context_documents.digests.with_streaming_response.list() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- digest = await response.parse()
- assert_matches_type(DigestListResponse, digest, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @parametrize
- async def test_method_generate(self, async_client: AsyncHyperspell) -> None:
- digest = await async_client.context_documents.digests.generate()
- assert_matches_type(DigestGenerateResponse, digest, path=["response"])
-
- @parametrize
- async def test_method_generate_with_all_params(self, async_client: AsyncHyperspell) -> None:
- digest = await async_client.context_documents.digests.generate(
- period="period",
- sources=["string"],
- window_end=parse_datetime("2019-12-27T18:11:19.117Z"),
- window_start=parse_datetime("2019-12-27T18:11:19.117Z"),
- )
- assert_matches_type(DigestGenerateResponse, digest, path=["response"])
-
- @parametrize
- async def test_raw_response_generate(self, async_client: AsyncHyperspell) -> None:
- response = await async_client.context_documents.digests.with_raw_response.generate()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- digest = await response.parse()
- assert_matches_type(DigestGenerateResponse, digest, path=["response"])
-
- @parametrize
- async def test_streaming_response_generate(self, async_client: AsyncHyperspell) -> None:
- async with async_client.context_documents.digests.with_streaming_response.generate() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- digest = await response.parse()
- assert_matches_type(DigestGenerateResponse, digest, path=["response"])
-
- assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/context_documents/test_trees.py b/tests/api_resources/context_documents/test_trees.py
deleted file mode 100644
index 835953ec..00000000
--- a/tests/api_resources/context_documents/test_trees.py
+++ /dev/null
@@ -1,313 +0,0 @@
-# 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 hyperspell import Hyperspell, AsyncHyperspell
-from tests.utils import assert_matches_type
-from hyperspell.types.context_documents import (
- TreeGetResponse,
- TreeGenerateResponse,
- TreeProgressResponse,
- TreeGetLatestResponse,
-)
-
-base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
-
-
-class TestTrees:
- parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
-
- @parametrize
- def test_method_generate(self, client: Hyperspell) -> None:
- tree = client.context_documents.trees.generate()
- assert_matches_type(TreeGenerateResponse, tree, path=["response"])
-
- @parametrize
- def test_method_generate_with_all_params(self, client: Hyperspell) -> None:
- tree = client.context_documents.trees.generate(
- sources=["string"],
- user_id="user_id",
- workstream_name="workstream_name",
- )
- assert_matches_type(TreeGenerateResponse, tree, path=["response"])
-
- @parametrize
- def test_raw_response_generate(self, client: Hyperspell) -> None:
- response = client.context_documents.trees.with_raw_response.generate()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- tree = response.parse()
- assert_matches_type(TreeGenerateResponse, tree, path=["response"])
-
- @parametrize
- def test_streaming_response_generate(self, client: Hyperspell) -> None:
- with client.context_documents.trees.with_streaming_response.generate() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- tree = response.parse()
- assert_matches_type(TreeGenerateResponse, tree, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @parametrize
- def test_method_get(self, client: Hyperspell) -> None:
- tree = client.context_documents.trees.get(
- "tree_id",
- )
- assert_matches_type(TreeGetResponse, tree, path=["response"])
-
- @parametrize
- def test_raw_response_get(self, client: Hyperspell) -> None:
- response = client.context_documents.trees.with_raw_response.get(
- "tree_id",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- tree = response.parse()
- assert_matches_type(TreeGetResponse, tree, path=["response"])
-
- @parametrize
- def test_streaming_response_get(self, client: Hyperspell) -> None:
- with client.context_documents.trees.with_streaming_response.get(
- "tree_id",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- tree = response.parse()
- assert_matches_type(TreeGetResponse, tree, 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 `tree_id` but received ''"):
- client.context_documents.trees.with_raw_response.get(
- "",
- )
-
- @parametrize
- def test_method_get_latest(self, client: Hyperspell) -> None:
- tree = client.context_documents.trees.get_latest()
- assert_matches_type(TreeGetLatestResponse, tree, path=["response"])
-
- @parametrize
- def test_method_get_latest_with_all_params(self, client: Hyperspell) -> None:
- tree = client.context_documents.trees.get_latest(
- status="status",
- )
- assert_matches_type(TreeGetLatestResponse, tree, path=["response"])
-
- @parametrize
- def test_raw_response_get_latest(self, client: Hyperspell) -> None:
- response = client.context_documents.trees.with_raw_response.get_latest()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- tree = response.parse()
- assert_matches_type(TreeGetLatestResponse, tree, path=["response"])
-
- @parametrize
- def test_streaming_response_get_latest(self, client: Hyperspell) -> None:
- with client.context_documents.trees.with_streaming_response.get_latest() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- tree = response.parse()
- assert_matches_type(TreeGetLatestResponse, tree, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @parametrize
- def test_method_progress(self, client: Hyperspell) -> None:
- tree = client.context_documents.trees.progress(
- "tree_id",
- )
- assert_matches_type(TreeProgressResponse, tree, path=["response"])
-
- @parametrize
- def test_raw_response_progress(self, client: Hyperspell) -> None:
- response = client.context_documents.trees.with_raw_response.progress(
- "tree_id",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- tree = response.parse()
- assert_matches_type(TreeProgressResponse, tree, path=["response"])
-
- @parametrize
- def test_streaming_response_progress(self, client: Hyperspell) -> None:
- with client.context_documents.trees.with_streaming_response.progress(
- "tree_id",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- tree = response.parse()
- assert_matches_type(TreeProgressResponse, tree, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @parametrize
- def test_path_params_progress(self, client: Hyperspell) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `tree_id` but received ''"):
- client.context_documents.trees.with_raw_response.progress(
- "",
- )
-
-
-class TestAsyncTrees:
- parametrize = pytest.mark.parametrize(
- "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
- )
-
- @parametrize
- async def test_method_generate(self, async_client: AsyncHyperspell) -> None:
- tree = await async_client.context_documents.trees.generate()
- assert_matches_type(TreeGenerateResponse, tree, path=["response"])
-
- @parametrize
- async def test_method_generate_with_all_params(self, async_client: AsyncHyperspell) -> None:
- tree = await async_client.context_documents.trees.generate(
- sources=["string"],
- user_id="user_id",
- workstream_name="workstream_name",
- )
- assert_matches_type(TreeGenerateResponse, tree, path=["response"])
-
- @parametrize
- async def test_raw_response_generate(self, async_client: AsyncHyperspell) -> None:
- response = await async_client.context_documents.trees.with_raw_response.generate()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- tree = await response.parse()
- assert_matches_type(TreeGenerateResponse, tree, path=["response"])
-
- @parametrize
- async def test_streaming_response_generate(self, async_client: AsyncHyperspell) -> None:
- async with async_client.context_documents.trees.with_streaming_response.generate() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- tree = await response.parse()
- assert_matches_type(TreeGenerateResponse, tree, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @parametrize
- async def test_method_get(self, async_client: AsyncHyperspell) -> None:
- tree = await async_client.context_documents.trees.get(
- "tree_id",
- )
- assert_matches_type(TreeGetResponse, tree, path=["response"])
-
- @parametrize
- async def test_raw_response_get(self, async_client: AsyncHyperspell) -> None:
- response = await async_client.context_documents.trees.with_raw_response.get(
- "tree_id",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- tree = await response.parse()
- assert_matches_type(TreeGetResponse, tree, path=["response"])
-
- @parametrize
- async def test_streaming_response_get(self, async_client: AsyncHyperspell) -> None:
- async with async_client.context_documents.trees.with_streaming_response.get(
- "tree_id",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- tree = await response.parse()
- assert_matches_type(TreeGetResponse, tree, 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 `tree_id` but received ''"):
- await async_client.context_documents.trees.with_raw_response.get(
- "",
- )
-
- @parametrize
- async def test_method_get_latest(self, async_client: AsyncHyperspell) -> None:
- tree = await async_client.context_documents.trees.get_latest()
- assert_matches_type(TreeGetLatestResponse, tree, path=["response"])
-
- @parametrize
- async def test_method_get_latest_with_all_params(self, async_client: AsyncHyperspell) -> None:
- tree = await async_client.context_documents.trees.get_latest(
- status="status",
- )
- assert_matches_type(TreeGetLatestResponse, tree, path=["response"])
-
- @parametrize
- async def test_raw_response_get_latest(self, async_client: AsyncHyperspell) -> None:
- response = await async_client.context_documents.trees.with_raw_response.get_latest()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- tree = await response.parse()
- assert_matches_type(TreeGetLatestResponse, tree, path=["response"])
-
- @parametrize
- async def test_streaming_response_get_latest(self, async_client: AsyncHyperspell) -> None:
- async with async_client.context_documents.trees.with_streaming_response.get_latest() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- tree = await response.parse()
- assert_matches_type(TreeGetLatestResponse, tree, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @parametrize
- async def test_method_progress(self, async_client: AsyncHyperspell) -> None:
- tree = await async_client.context_documents.trees.progress(
- "tree_id",
- )
- assert_matches_type(TreeProgressResponse, tree, path=["response"])
-
- @parametrize
- async def test_raw_response_progress(self, async_client: AsyncHyperspell) -> None:
- response = await async_client.context_documents.trees.with_raw_response.progress(
- "tree_id",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- tree = await response.parse()
- assert_matches_type(TreeProgressResponse, tree, path=["response"])
-
- @parametrize
- async def test_streaming_response_progress(self, async_client: AsyncHyperspell) -> None:
- async with async_client.context_documents.trees.with_streaming_response.progress(
- "tree_id",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- tree = await response.parse()
- assert_matches_type(TreeProgressResponse, tree, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @parametrize
- async def test_path_params_progress(self, async_client: AsyncHyperspell) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `tree_id` but received ''"):
- await async_client.context_documents.trees.with_raw_response.progress(
- "",
- )
diff --git a/tests/api_resources/test_context_documents.py b/tests/api_resources/test_context_documents.py
deleted file mode 100644
index f22e9c93..00000000
--- a/tests/api_resources/test_context_documents.py
+++ /dev/null
@@ -1,259 +0,0 @@
-# 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 hyperspell import Hyperspell, AsyncHyperspell
-from tests.utils import assert_matches_type
-from hyperspell.types import (
- ContextDocumentGetResponse,
- ContextDocumentListResponse,
- ContextDocumentGenerateResponse,
-)
-from hyperspell.pagination import SyncContextDocumentsCursorPage, AsyncContextDocumentsCursorPage
-
-base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
-
-
-class TestContextDocuments:
- parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
-
- @parametrize
- def test_method_list(self, client: Hyperspell) -> None:
- context_document = client.context_documents.list()
- assert_matches_type(
- SyncContextDocumentsCursorPage[ContextDocumentListResponse], context_document, path=["response"]
- )
-
- @parametrize
- def test_method_list_with_all_params(self, client: Hyperspell) -> None:
- context_document = client.context_documents.list(
- cursor="cursor",
- limit=0,
- status="processing",
- )
- assert_matches_type(
- SyncContextDocumentsCursorPage[ContextDocumentListResponse], context_document, path=["response"]
- )
-
- @parametrize
- def test_raw_response_list(self, client: Hyperspell) -> None:
- response = client.context_documents.with_raw_response.list()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- context_document = response.parse()
- assert_matches_type(
- SyncContextDocumentsCursorPage[ContextDocumentListResponse], context_document, path=["response"]
- )
-
- @parametrize
- def test_streaming_response_list(self, client: Hyperspell) -> None:
- with client.context_documents.with_streaming_response.list() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- context_document = response.parse()
- assert_matches_type(
- SyncContextDocumentsCursorPage[ContextDocumentListResponse], context_document, path=["response"]
- )
-
- assert cast(Any, response.is_closed) is True
-
- @parametrize
- def test_method_generate(self, client: Hyperspell) -> None:
- context_document = client.context_documents.generate()
- assert_matches_type(ContextDocumentGenerateResponse, context_document, path=["response"])
-
- @parametrize
- def test_method_generate_with_all_params(self, client: Hyperspell) -> None:
- context_document = client.context_documents.generate(
- model="model",
- prompt="prompt",
- sources=["string"],
- user_id="user_id",
- )
- assert_matches_type(ContextDocumentGenerateResponse, context_document, path=["response"])
-
- @parametrize
- def test_raw_response_generate(self, client: Hyperspell) -> None:
- response = client.context_documents.with_raw_response.generate()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- context_document = response.parse()
- assert_matches_type(ContextDocumentGenerateResponse, context_document, path=["response"])
-
- @parametrize
- def test_streaming_response_generate(self, client: Hyperspell) -> None:
- with client.context_documents.with_streaming_response.generate() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- context_document = response.parse()
- assert_matches_type(ContextDocumentGenerateResponse, context_document, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @parametrize
- def test_method_get(self, client: Hyperspell) -> None:
- context_document = client.context_documents.get(
- "document_id",
- )
- assert_matches_type(ContextDocumentGetResponse, context_document, path=["response"])
-
- @parametrize
- def test_raw_response_get(self, client: Hyperspell) -> None:
- response = client.context_documents.with_raw_response.get(
- "document_id",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- context_document = response.parse()
- assert_matches_type(ContextDocumentGetResponse, context_document, path=["response"])
-
- @parametrize
- def test_streaming_response_get(self, client: Hyperspell) -> None:
- with client.context_documents.with_streaming_response.get(
- "document_id",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- context_document = response.parse()
- assert_matches_type(ContextDocumentGetResponse, context_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 `document_id` but received ''"):
- client.context_documents.with_raw_response.get(
- "",
- )
-
-
-class TestAsyncContextDocuments:
- parametrize = pytest.mark.parametrize(
- "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
- )
-
- @parametrize
- async def test_method_list(self, async_client: AsyncHyperspell) -> None:
- context_document = await async_client.context_documents.list()
- assert_matches_type(
- AsyncContextDocumentsCursorPage[ContextDocumentListResponse], context_document, path=["response"]
- )
-
- @parametrize
- async def test_method_list_with_all_params(self, async_client: AsyncHyperspell) -> None:
- context_document = await async_client.context_documents.list(
- cursor="cursor",
- limit=0,
- status="processing",
- )
- assert_matches_type(
- AsyncContextDocumentsCursorPage[ContextDocumentListResponse], context_document, path=["response"]
- )
-
- @parametrize
- async def test_raw_response_list(self, async_client: AsyncHyperspell) -> None:
- response = await async_client.context_documents.with_raw_response.list()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- context_document = await response.parse()
- assert_matches_type(
- AsyncContextDocumentsCursorPage[ContextDocumentListResponse], context_document, path=["response"]
- )
-
- @parametrize
- async def test_streaming_response_list(self, async_client: AsyncHyperspell) -> None:
- async with async_client.context_documents.with_streaming_response.list() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- context_document = await response.parse()
- assert_matches_type(
- AsyncContextDocumentsCursorPage[ContextDocumentListResponse], context_document, path=["response"]
- )
-
- assert cast(Any, response.is_closed) is True
-
- @parametrize
- async def test_method_generate(self, async_client: AsyncHyperspell) -> None:
- context_document = await async_client.context_documents.generate()
- assert_matches_type(ContextDocumentGenerateResponse, context_document, path=["response"])
-
- @parametrize
- async def test_method_generate_with_all_params(self, async_client: AsyncHyperspell) -> None:
- context_document = await async_client.context_documents.generate(
- model="model",
- prompt="prompt",
- sources=["string"],
- user_id="user_id",
- )
- assert_matches_type(ContextDocumentGenerateResponse, context_document, path=["response"])
-
- @parametrize
- async def test_raw_response_generate(self, async_client: AsyncHyperspell) -> None:
- response = await async_client.context_documents.with_raw_response.generate()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- context_document = await response.parse()
- assert_matches_type(ContextDocumentGenerateResponse, context_document, path=["response"])
-
- @parametrize
- async def test_streaming_response_generate(self, async_client: AsyncHyperspell) -> None:
- async with async_client.context_documents.with_streaming_response.generate() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- context_document = await response.parse()
- assert_matches_type(ContextDocumentGenerateResponse, context_document, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @parametrize
- async def test_method_get(self, async_client: AsyncHyperspell) -> None:
- context_document = await async_client.context_documents.get(
- "document_id",
- )
- assert_matches_type(ContextDocumentGetResponse, context_document, path=["response"])
-
- @parametrize
- async def test_raw_response_get(self, async_client: AsyncHyperspell) -> None:
- response = await async_client.context_documents.with_raw_response.get(
- "document_id",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- context_document = await response.parse()
- assert_matches_type(ContextDocumentGetResponse, context_document, path=["response"])
-
- @parametrize
- async def test_streaming_response_get(self, async_client: AsyncHyperspell) -> None:
- async with async_client.context_documents.with_streaming_response.get(
- "document_id",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- context_document = await response.parse()
- assert_matches_type(ContextDocumentGetResponse, context_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 `document_id` but received ''"):
- await async_client.context_documents.with_raw_response.get(
- "",
- )
diff --git a/tests/api_resources/test_entities.py b/tests/api_resources/test_entities.py
new file mode 100644
index 00000000..61c0f4f9
--- /dev/null
+++ b/tests/api_resources/test_entities.py
@@ -0,0 +1,265 @@
+# 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 hyperspell import Hyperspell, AsyncHyperspell
+from tests.utils import assert_matches_type
+from hyperspell.types import (
+ EntityGetResponse,
+ EntityListResponse,
+ EntitySearchResponse,
+)
+from hyperspell.pagination import SyncEntityCursorPage, AsyncEntityCursorPage
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestEntities:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @parametrize
+ def test_method_list(self, client: Hyperspell) -> None:
+ entity = client.entities.list()
+ assert_matches_type(SyncEntityCursorPage[EntityListResponse], entity, path=["response"])
+
+ @parametrize
+ def test_method_list_with_all_params(self, client: Hyperspell) -> None:
+ entity = client.entities.list(
+ cursor="cursor",
+ limit=1,
+ min_supporting_documents=0,
+ name_prefix="name_prefix",
+ search="search",
+ sort_by="id",
+ sort_dir="asc",
+ status="provisional",
+ type="type",
+ )
+ assert_matches_type(SyncEntityCursorPage[EntityListResponse], entity, path=["response"])
+
+ @parametrize
+ def test_raw_response_list(self, client: Hyperspell) -> None:
+ response = client.entities.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ entity = response.parse()
+ assert_matches_type(SyncEntityCursorPage[EntityListResponse], entity, path=["response"])
+
+ @parametrize
+ def test_streaming_response_list(self, client: Hyperspell) -> None:
+ with client.entities.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ entity = response.parse()
+ assert_matches_type(SyncEntityCursorPage[EntityListResponse], entity, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_method_get(self, client: Hyperspell) -> None:
+ entity = client.entities.get(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(EntityGetResponse, entity, path=["response"])
+
+ @parametrize
+ def test_raw_response_get(self, client: Hyperspell) -> None:
+ response = client.entities.with_raw_response.get(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ entity = response.parse()
+ assert_matches_type(EntityGetResponse, entity, path=["response"])
+
+ @parametrize
+ def test_streaming_response_get(self, client: Hyperspell) -> None:
+ with client.entities.with_streaming_response.get(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ entity = response.parse()
+ assert_matches_type(EntityGetResponse, entity, 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 `entity_id` but received ''"):
+ client.entities.with_raw_response.get(
+ "",
+ )
+
+ @parametrize
+ def test_method_search(self, client: Hyperspell) -> None:
+ entity = client.entities.search(
+ query="query",
+ )
+ assert_matches_type(EntitySearchResponse, entity, path=["response"])
+
+ @parametrize
+ def test_method_search_with_all_params(self, client: Hyperspell) -> None:
+ entity = client.entities.search(
+ query="query",
+ limit=1,
+ type="type",
+ )
+ assert_matches_type(EntitySearchResponse, entity, path=["response"])
+
+ @parametrize
+ def test_raw_response_search(self, client: Hyperspell) -> None:
+ response = client.entities.with_raw_response.search(
+ query="query",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ entity = response.parse()
+ assert_matches_type(EntitySearchResponse, entity, path=["response"])
+
+ @parametrize
+ def test_streaming_response_search(self, client: Hyperspell) -> None:
+ with client.entities.with_streaming_response.search(
+ query="query",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ entity = response.parse()
+ assert_matches_type(EntitySearchResponse, entity, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncEntities:
+ parametrize = pytest.mark.parametrize(
+ "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
+ )
+
+ @parametrize
+ async def test_method_list(self, async_client: AsyncHyperspell) -> None:
+ entity = await async_client.entities.list()
+ assert_matches_type(AsyncEntityCursorPage[EntityListResponse], entity, path=["response"])
+
+ @parametrize
+ async def test_method_list_with_all_params(self, async_client: AsyncHyperspell) -> None:
+ entity = await async_client.entities.list(
+ cursor="cursor",
+ limit=1,
+ min_supporting_documents=0,
+ name_prefix="name_prefix",
+ search="search",
+ sort_by="id",
+ sort_dir="asc",
+ status="provisional",
+ type="type",
+ )
+ assert_matches_type(AsyncEntityCursorPage[EntityListResponse], entity, path=["response"])
+
+ @parametrize
+ async def test_raw_response_list(self, async_client: AsyncHyperspell) -> None:
+ response = await async_client.entities.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ entity = await response.parse()
+ assert_matches_type(AsyncEntityCursorPage[EntityListResponse], entity, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_list(self, async_client: AsyncHyperspell) -> None:
+ async with async_client.entities.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ entity = await response.parse()
+ assert_matches_type(AsyncEntityCursorPage[EntityListResponse], entity, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_method_get(self, async_client: AsyncHyperspell) -> None:
+ entity = await async_client.entities.get(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(EntityGetResponse, entity, path=["response"])
+
+ @parametrize
+ async def test_raw_response_get(self, async_client: AsyncHyperspell) -> None:
+ response = await async_client.entities.with_raw_response.get(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ entity = await response.parse()
+ assert_matches_type(EntityGetResponse, entity, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_get(self, async_client: AsyncHyperspell) -> None:
+ async with async_client.entities.with_streaming_response.get(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ entity = await response.parse()
+ assert_matches_type(EntityGetResponse, entity, 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 `entity_id` but received ''"):
+ await async_client.entities.with_raw_response.get(
+ "",
+ )
+
+ @parametrize
+ async def test_method_search(self, async_client: AsyncHyperspell) -> None:
+ entity = await async_client.entities.search(
+ query="query",
+ )
+ assert_matches_type(EntitySearchResponse, entity, path=["response"])
+
+ @parametrize
+ async def test_method_search_with_all_params(self, async_client: AsyncHyperspell) -> None:
+ entity = await async_client.entities.search(
+ query="query",
+ limit=1,
+ type="type",
+ )
+ assert_matches_type(EntitySearchResponse, entity, path=["response"])
+
+ @parametrize
+ async def test_raw_response_search(self, async_client: AsyncHyperspell) -> None:
+ response = await async_client.entities.with_raw_response.search(
+ query="query",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ entity = await response.parse()
+ assert_matches_type(EntitySearchResponse, entity, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_search(self, async_client: AsyncHyperspell) -> None:
+ async with async_client.entities.with_streaming_response.search(
+ query="query",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ entity = await response.parse()
+ assert_matches_type(EntitySearchResponse, entity, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_live.py b/tests/api_resources/test_live.py
new file mode 100644
index 00000000..07d226a7
--- /dev/null
+++ b/tests/api_resources/test_live.py
@@ -0,0 +1,354 @@
+# 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 hyperspell import Hyperspell, AsyncHyperspell
+from tests.utils import assert_matches_type
+from hyperspell.types import (
+ LiveSearchResponse,
+ LiveGetResourceResponse,
+ LiveListSourcesResponse,
+ LiveListResourcesResponse,
+)
+from hyperspell.pagination import SyncCursorPage, AsyncCursorPage
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestLive:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @parametrize
+ def test_method_get_resource(self, client: Hyperspell) -> None:
+ live = client.live.get_resource(
+ resource_id="resource_id",
+ source="reddit",
+ )
+ assert_matches_type(LiveGetResourceResponse, live, path=["response"])
+
+ @parametrize
+ def test_method_get_resource_with_all_params(self, client: Hyperspell) -> None:
+ live = client.live.get_resource(
+ resource_id="resource_id",
+ source="reddit",
+ connection_id="connection_id",
+ index=True,
+ )
+ assert_matches_type(LiveGetResourceResponse, live, path=["response"])
+
+ @parametrize
+ def test_raw_response_get_resource(self, client: Hyperspell) -> None:
+ response = client.live.with_raw_response.get_resource(
+ resource_id="resource_id",
+ source="reddit",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ live = response.parse()
+ assert_matches_type(LiveGetResourceResponse, live, path=["response"])
+
+ @parametrize
+ def test_streaming_response_get_resource(self, client: Hyperspell) -> None:
+ with client.live.with_streaming_response.get_resource(
+ resource_id="resource_id",
+ source="reddit",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ live = response.parse()
+ assert_matches_type(LiveGetResourceResponse, live, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_get_resource(self, client: Hyperspell) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `resource_id` but received ''"):
+ client.live.with_raw_response.get_resource(
+ resource_id="",
+ source="reddit",
+ )
+
+ @parametrize
+ def test_method_list_resources(self, client: Hyperspell) -> None:
+ live = client.live.list_resources(
+ source="reddit",
+ )
+ assert_matches_type(SyncCursorPage[LiveListResourcesResponse], live, path=["response"])
+
+ @parametrize
+ def test_method_list_resources_with_all_params(self, client: Hyperspell) -> None:
+ live = client.live.list_resources(
+ source="reddit",
+ connection_id="connection_id",
+ cursor="cursor",
+ size=0,
+ )
+ assert_matches_type(SyncCursorPage[LiveListResourcesResponse], live, path=["response"])
+
+ @parametrize
+ def test_raw_response_list_resources(self, client: Hyperspell) -> None:
+ response = client.live.with_raw_response.list_resources(
+ source="reddit",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ live = response.parse()
+ assert_matches_type(SyncCursorPage[LiveListResourcesResponse], live, path=["response"])
+
+ @parametrize
+ def test_streaming_response_list_resources(self, client: Hyperspell) -> None:
+ with client.live.with_streaming_response.list_resources(
+ source="reddit",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ live = response.parse()
+ assert_matches_type(SyncCursorPage[LiveListResourcesResponse], live, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_method_list_sources(self, client: Hyperspell) -> None:
+ live = client.live.list_sources()
+ assert_matches_type(LiveListSourcesResponse, live, path=["response"])
+
+ @parametrize
+ def test_raw_response_list_sources(self, client: Hyperspell) -> None:
+ response = client.live.with_raw_response.list_sources()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ live = response.parse()
+ assert_matches_type(LiveListSourcesResponse, live, path=["response"])
+
+ @parametrize
+ def test_streaming_response_list_sources(self, client: Hyperspell) -> None:
+ with client.live.with_streaming_response.list_sources() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ live = response.parse()
+ assert_matches_type(LiveListSourcesResponse, live, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_method_search(self, client: Hyperspell) -> None:
+ live = client.live.search(
+ source="reddit",
+ query="query",
+ )
+ assert_matches_type(LiveSearchResponse, live, path=["response"])
+
+ @parametrize
+ def test_method_search_with_all_params(self, client: Hyperspell) -> None:
+ live = client.live.search(
+ source="reddit",
+ query="query",
+ connection_id="connection_id",
+ index=True,
+ )
+ assert_matches_type(LiveSearchResponse, live, path=["response"])
+
+ @parametrize
+ def test_raw_response_search(self, client: Hyperspell) -> None:
+ response = client.live.with_raw_response.search(
+ source="reddit",
+ query="query",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ live = response.parse()
+ assert_matches_type(LiveSearchResponse, live, path=["response"])
+
+ @parametrize
+ def test_streaming_response_search(self, client: Hyperspell) -> None:
+ with client.live.with_streaming_response.search(
+ source="reddit",
+ query="query",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ live = response.parse()
+ assert_matches_type(LiveSearchResponse, live, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncLive:
+ parametrize = pytest.mark.parametrize(
+ "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
+ )
+
+ @parametrize
+ async def test_method_get_resource(self, async_client: AsyncHyperspell) -> None:
+ live = await async_client.live.get_resource(
+ resource_id="resource_id",
+ source="reddit",
+ )
+ assert_matches_type(LiveGetResourceResponse, live, path=["response"])
+
+ @parametrize
+ async def test_method_get_resource_with_all_params(self, async_client: AsyncHyperspell) -> None:
+ live = await async_client.live.get_resource(
+ resource_id="resource_id",
+ source="reddit",
+ connection_id="connection_id",
+ index=True,
+ )
+ assert_matches_type(LiveGetResourceResponse, live, path=["response"])
+
+ @parametrize
+ async def test_raw_response_get_resource(self, async_client: AsyncHyperspell) -> None:
+ response = await async_client.live.with_raw_response.get_resource(
+ resource_id="resource_id",
+ source="reddit",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ live = await response.parse()
+ assert_matches_type(LiveGetResourceResponse, live, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_get_resource(self, async_client: AsyncHyperspell) -> None:
+ async with async_client.live.with_streaming_response.get_resource(
+ resource_id="resource_id",
+ source="reddit",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ live = await response.parse()
+ assert_matches_type(LiveGetResourceResponse, live, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_get_resource(self, async_client: AsyncHyperspell) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `resource_id` but received ''"):
+ await async_client.live.with_raw_response.get_resource(
+ resource_id="",
+ source="reddit",
+ )
+
+ @parametrize
+ async def test_method_list_resources(self, async_client: AsyncHyperspell) -> None:
+ live = await async_client.live.list_resources(
+ source="reddit",
+ )
+ assert_matches_type(AsyncCursorPage[LiveListResourcesResponse], live, path=["response"])
+
+ @parametrize
+ async def test_method_list_resources_with_all_params(self, async_client: AsyncHyperspell) -> None:
+ live = await async_client.live.list_resources(
+ source="reddit",
+ connection_id="connection_id",
+ cursor="cursor",
+ size=0,
+ )
+ assert_matches_type(AsyncCursorPage[LiveListResourcesResponse], live, path=["response"])
+
+ @parametrize
+ async def test_raw_response_list_resources(self, async_client: AsyncHyperspell) -> None:
+ response = await async_client.live.with_raw_response.list_resources(
+ source="reddit",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ live = await response.parse()
+ assert_matches_type(AsyncCursorPage[LiveListResourcesResponse], live, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_list_resources(self, async_client: AsyncHyperspell) -> None:
+ async with async_client.live.with_streaming_response.list_resources(
+ source="reddit",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ live = await response.parse()
+ assert_matches_type(AsyncCursorPage[LiveListResourcesResponse], live, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_method_list_sources(self, async_client: AsyncHyperspell) -> None:
+ live = await async_client.live.list_sources()
+ assert_matches_type(LiveListSourcesResponse, live, path=["response"])
+
+ @parametrize
+ async def test_raw_response_list_sources(self, async_client: AsyncHyperspell) -> None:
+ response = await async_client.live.with_raw_response.list_sources()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ live = await response.parse()
+ assert_matches_type(LiveListSourcesResponse, live, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_list_sources(self, async_client: AsyncHyperspell) -> None:
+ async with async_client.live.with_streaming_response.list_sources() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ live = await response.parse()
+ assert_matches_type(LiveListSourcesResponse, live, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_method_search(self, async_client: AsyncHyperspell) -> None:
+ live = await async_client.live.search(
+ source="reddit",
+ query="query",
+ )
+ assert_matches_type(LiveSearchResponse, live, path=["response"])
+
+ @parametrize
+ async def test_method_search_with_all_params(self, async_client: AsyncHyperspell) -> None:
+ live = await async_client.live.search(
+ source="reddit",
+ query="query",
+ connection_id="connection_id",
+ index=True,
+ )
+ assert_matches_type(LiveSearchResponse, live, path=["response"])
+
+ @parametrize
+ async def test_raw_response_search(self, async_client: AsyncHyperspell) -> None:
+ response = await async_client.live.with_raw_response.search(
+ source="reddit",
+ query="query",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ live = await response.parse()
+ assert_matches_type(LiveSearchResponse, live, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_search(self, async_client: AsyncHyperspell) -> None:
+ async with async_client.live.with_streaming_response.search(
+ source="reddit",
+ query="query",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ live = await response.parse()
+ assert_matches_type(LiveSearchResponse, live, path=["response"])
+
+ assert cast(Any, response.is_closed) is True