Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
c0845dc
feat(client): add support for aiohttp
stainless-app[bot] Jun 21, 2025
bd59464
codegen metadata
stainless-app[bot] Jun 23, 2025
9eebf62
chore(tests): skip some failing tests on the latest python versions
stainless-app[bot] Jun 24, 2025
a7c06e2
codegen metadata
stainless-app[bot] Jun 26, 2025
8d7eb87
codegen metadata
stainless-app[bot] Jun 26, 2025
afa72fa
codegen metadata
stainless-app[bot] Jun 26, 2025
dafd3ca
codegen metadata
stainless-app[bot] Jun 26, 2025
79e762d
codegen metadata
stainless-app[bot] Jun 26, 2025
5ca3c2c
codegen metadata
stainless-app[bot] Jun 26, 2025
446d601
codegen metadata
stainless-app[bot] Jun 26, 2025
b0c4541
codegen metadata
stainless-app[bot] Jun 26, 2025
3a7f5f6
codegen metadata
stainless-app[bot] Jun 26, 2025
ba24d4c
codegen metadata
stainless-app[bot] Jun 26, 2025
6ddb78b
fix(ci): release-doctor — report correct token name
stainless-app[bot] Jun 27, 2025
991d685
chore(ci): only run for pushes and fork pull requests
stainless-app[bot] Jun 28, 2025
5995a5a
codegen metadata
stainless-app[bot] Jun 28, 2025
980b910
fix(ci): correct conditional
stainless-app[bot] Jun 30, 2025
c01d519
chore(ci): change upload type
stainless-app[bot] Jul 2, 2025
f7cd6c7
chore(internal): codegen related update
stainless-app[bot] Jul 8, 2025
1ce5781
chore(internal): bump pinned h11 dep
stainless-app[bot] Jul 9, 2025
b04d1e6
chore(package): mark python 3.13 as supported
stainless-app[bot] Jul 9, 2025
f4e309d
fix(parsing): correctly handle nested discriminated unions
stainless-app[bot] Jul 10, 2025
a109225
chore(readme): fix version rendering on pypi
stainless-app[bot] Jul 11, 2025
f7a04b5
fix(client): don't send Content-Type header on GET requests
stainless-app[bot] Jul 12, 2025
e99844e
feat: clean up environment call outs
stainless-app[bot] Jul 15, 2025
7248ff5
feat(api): api update
stainless-app[bot] Jul 17, 2025
e4edf05
feat(api): api update
stainless-app[bot] Jul 17, 2025
82ee242
codegen metadata
stainless-app[bot] Jul 18, 2025
bf294db
feat(api): update via SDK Studio
stainless-app[bot] Jul 18, 2025
21036b0
feat(api): update via SDK Studio
stainless-app[bot] Jul 18, 2025
1e53d21
codegen metadata
stainless-app[bot] Jul 18, 2025
20bf1bb
feat(api): update via SDK Studio
stainless-app[bot] Jul 18, 2025
0b78ebf
release: 0.19.0
stainless-app[bot] Jul 18, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ jobs:
timeout-minutes: 10
name: lint
runs-on: ${{ github.repository == 'stainless-sdks/hyperspell-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
steps:
- uses: actions/checkout@v4

Expand All @@ -34,17 +35,31 @@ jobs:
- name: Run lints
run: ./scripts/lint

upload:
if: github.repository == 'stainless-sdks/hyperspell-python'
build:
if: github.repository == 'stainless-sdks/hyperspell-python' && (github.event_name == 'push' || github.event.pull_request.head.repo.fork)
timeout-minutes: 10
name: upload
name: build
permissions:
contents: read
id-token: write
runs-on: depot-ubuntu-24.04
steps:
- uses: actions/checkout@v4

- name: Install Rye
run: |
curl -sSf https://rye.astral.sh/get | bash
echo "$HOME/.rye/shims" >> $GITHUB_PATH
env:
RYE_VERSION: '0.44.0'
RYE_INSTALL_OPTION: '--yes'

- name: Install dependencies
run: rye sync --all-features

- name: Run build
run: rye build

- name: Get GitHub OIDC Token
id: github-oidc
uses: actions/github-script@v6
Expand All @@ -62,6 +77,7 @@ jobs:
timeout-minutes: 10
name: test
runs-on: ${{ github.repository == 'stainless-sdks/hyperspell-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
steps:
- uses: actions/checkout@v4

Expand Down
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.18.0"
".": "0.19.0"
}
6 changes: 3 additions & 3 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 12
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/hyperspell%2Fhyperspell-e89c764e4c847e7825e07bdb7e927a99b29548a8864069365d50974e8d4518fe.yml
openapi_spec_hash: fadd50b9f0b9675cbf5c16c318feef2f
config_hash: 32d007e1683b1936cd145cd41982ebb6
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/hyperspell%2Fhyperspell-4bfa5ab6a0021f526d6f6f622f1872f2ec3467b6d1bd51acfc17bfc6f399f915.yml
openapi_spec_hash: 5b51df5010bab70a1f3f884552ce25c3
config_hash: c894437241b21cedd2d01854f1c7a8ef
33 changes: 33 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,38 @@
# Changelog

## 0.19.0 (2025-07-18)

Full Changelog: [v0.18.0...v0.19.0](https://github.com/hyperspell/python-sdk/compare/v0.18.0...v0.19.0)

### Features

* **api:** api update ([e4edf05](https://github.com/hyperspell/python-sdk/commit/e4edf05d2e2700fef1e70250204aee103ac54686))
* **api:** api update ([7248ff5](https://github.com/hyperspell/python-sdk/commit/7248ff5db8bbc8708f8dfe8afb78d519401ee7f2))
* **api:** update via SDK Studio ([20bf1bb](https://github.com/hyperspell/python-sdk/commit/20bf1bbf36b4b5aa984cd6f405eb98fb6a743dba))
* **api:** update via SDK Studio ([21036b0](https://github.com/hyperspell/python-sdk/commit/21036b0a3b626fa41925b58b24616484158b9361))
* **api:** update via SDK Studio ([bf294db](https://github.com/hyperspell/python-sdk/commit/bf294db204ddb25338ab2370d78d6c378c78686a))
* clean up environment call outs ([e99844e](https://github.com/hyperspell/python-sdk/commit/e99844ee29928beeed51cd47d53e3ababe33e608))
* **client:** add support for aiohttp ([c0845dc](https://github.com/hyperspell/python-sdk/commit/c0845dc8133eb74e72f18651e9da53102609d833))


### Bug Fixes

* **ci:** correct conditional ([980b910](https://github.com/hyperspell/python-sdk/commit/980b910eaa78cf84de10c0521e4ed2f142689ae0))
* **ci:** release-doctor — report correct token name ([6ddb78b](https://github.com/hyperspell/python-sdk/commit/6ddb78b355f8e36a85fcfaf1592618bae5c67473))
* **client:** don't send Content-Type header on GET requests ([f7a04b5](https://github.com/hyperspell/python-sdk/commit/f7a04b5a47aa9a6fc338498a34db4074824c198e))
* **parsing:** correctly handle nested discriminated unions ([f4e309d](https://github.com/hyperspell/python-sdk/commit/f4e309d6a8d85f5aa0cb3fee3e41bf9c6487b5b1))


### Chores

* **ci:** change upload type ([c01d519](https://github.com/hyperspell/python-sdk/commit/c01d519131a2c4620c9454c4e634c2e39053b00c))
* **ci:** only run for pushes and fork pull requests ([991d685](https://github.com/hyperspell/python-sdk/commit/991d6859286e86aa022eb83aab8ecc6e337798f4))
* **internal:** bump pinned h11 dep ([1ce5781](https://github.com/hyperspell/python-sdk/commit/1ce57814e1d392b0c6a51b75c1dd92550f9399c3))
* **internal:** codegen related update ([f7cd6c7](https://github.com/hyperspell/python-sdk/commit/f7cd6c7b1feafef059ecdf6be0bb9adbd5f28929))
* **package:** mark python 3.13 as supported ([b04d1e6](https://github.com/hyperspell/python-sdk/commit/b04d1e6c7d2dbd8852963ee8f08596ed332e04ec))
* **readme:** fix version rendering on pypi ([a109225](https://github.com/hyperspell/python-sdk/commit/a1092259c98715d17ce95259420baf3c3d325db8))
* **tests:** skip some failing tests on the latest python versions ([9eebf62](https://github.com/hyperspell/python-sdk/commit/9eebf628b254b4f463ea7b899dcef53af5362228))

## 0.18.0 (2025-06-19)

Full Changelog: [v0.16.0...v0.18.0](https://github.com/hyperspell/python-sdk/compare/v0.16.0...v0.18.0)
Expand Down
88 changes: 61 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Hyperspell Python API library

[![PyPI version](<https://img.shields.io/pypi/v/hyperspell.svg?label=pypi%20(stable)>)](https://pypi.org/project/hyperspell/)
<!-- prettier-ignore -->
[![PyPI version](https://img.shields.io/pypi/v/hyperspell.svg?label=pypi%20(stable))](https://pypi.org/project/hyperspell/)

The Hyperspell Python library provides convenient access to the Hyperspell REST API from any Python 3.8+
application. The library includes type definitions for all request params and response fields,
Expand Down Expand Up @@ -31,10 +32,10 @@ client = Hyperspell(
api_key=os.environ.get("HYPERSPELL_TOKEN"), # This is the default and can be omitted
)

document_status = client.documents.add(
memory_status = client.memories.add(
text="text",
)
print(document_status.id)
print(memory_status.id)
```

While you can provide an `api_key` keyword argument,
Expand All @@ -57,17 +58,50 @@ client = AsyncHyperspell(


async def main() -> None:
document_status = await client.documents.add(
memory_status = await client.memories.add(
text="text",
)
print(document_status.id)
print(memory_status.id)


asyncio.run(main())
```

Functionality between the synchronous and asynchronous clients is otherwise identical.

### With aiohttp

By default, the async client uses `httpx` for HTTP requests. However, for improved concurrency performance you may also use `aiohttp` as the HTTP backend.

You can enable this by installing `aiohttp`:

```sh
# install from PyPI
pip install hyperspell[aiohttp]
```

Then you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`:

```python
import asyncio
from hyperspell import DefaultAioHttpClient
from hyperspell import AsyncHyperspell


async def main() -> None:
async with AsyncHyperspell(
api_key="My API Key",
http_client=DefaultAioHttpClient(),
) as client:
memory_status = await client.memories.add(
text="text",
)
print(memory_status.id)


asyncio.run(main())
```

## Using types

Nested request parameters are [TypedDicts](https://docs.python.org/3/library/typing.html#typing.TypedDict). Responses are [Pydantic models](https://docs.pydantic.dev) which also provide helper methods for things like:
Expand All @@ -88,14 +122,14 @@ from hyperspell import Hyperspell

client = Hyperspell()

all_documents = []
all_memories = []
# Automatically fetches more pages as needed.
for document in client.documents.list(
for memory in client.memories.list(
collection="REPLACE_ME",
):
# Do something with document here
all_documents.append(document)
print(all_documents)
# Do something with memory here
all_memories.append(memory)
print(all_memories)
```

Or, asynchronously:
Expand All @@ -108,13 +142,13 @@ client = AsyncHyperspell()


async def main() -> None:
all_documents = []
all_memories = []
# Iterate through items across all pages, issuing requests as needed.
async for document in client.documents.list(
async for memory in client.memories.list(
collection="REPLACE_ME",
):
all_documents.append(document)
print(all_documents)
all_memories.append(memory)
print(all_memories)


asyncio.run(main())
Expand All @@ -123,7 +157,7 @@ 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.documents.list(
first_page = await client.memories.list(
collection="REPLACE_ME",
)
if first_page.has_next_page():
Expand All @@ -137,13 +171,13 @@ if first_page.has_next_page():
Or just work directly with the returned data:

```python
first_page = await client.documents.list(
first_page = await client.memories.list(
collection="REPLACE_ME",
)

print(f"next page cursor: {first_page.next_cursor}") # => "next page cursor: ..."
for document in first_page.items:
print(document.resource_id)
for memory in first_page.items:
print(memory.resource_id)

# Remove `await` for non-async usage.
```
Expand All @@ -157,7 +191,7 @@ from hyperspell import Hyperspell

client = Hyperspell()

response = client.query.search(
response = client.memories.search(
query="query",
filter={},
)
Expand All @@ -174,7 +208,7 @@ from hyperspell import Hyperspell

client = Hyperspell()

client.documents.upload(
client.memories.upload(
file=Path("/path/to/file"),
)
```
Expand All @@ -197,7 +231,7 @@ from hyperspell import Hyperspell
client = Hyperspell()

try:
client.documents.add(
client.memories.add(
text="text",
)
except hyperspell.APIConnectionError as e:
Expand Down Expand Up @@ -242,7 +276,7 @@ client = Hyperspell(
)

# Or, configure per-request:
client.with_options(max_retries=5).documents.add(
client.with_options(max_retries=5).memories.add(
text="text",
)
```
Expand All @@ -267,7 +301,7 @@ client = Hyperspell(
)

# Override per-request:
client.with_options(timeout=5.0).documents.add(
client.with_options(timeout=5.0).memories.add(
text="text",
)
```
Expand Down Expand Up @@ -310,13 +344,13 @@ The "raw" Response object can be accessed by prefixing `.with_raw_response.` to
from hyperspell import Hyperspell

client = Hyperspell()
response = client.documents.with_raw_response.add(
response = client.memories.with_raw_response.add(
text="text",
)
print(response.headers.get('X-My-Header'))

document = response.parse() # get the object that `documents.add()` would have returned
print(document.id)
memory = response.parse() # get the object that `memories.add()` would have returned
print(memory.id)
```

These methods return an [`APIResponse`](https://github.com/hyperspell/python-sdk/tree/main/src/hyperspell/_response.py) object.
Expand All @@ -330,7 +364,7 @@ The above interface eagerly reads the full response body when you make the reque
To stream the response body, use `.with_streaming_response` instead, which requires a context manager and only reads the response body once you call `.read()`, `.text()`, `.json()`, `.iter_bytes()`, `.iter_text()`, `.iter_lines()` or `.parse()`. In the async client, these are async methods.

```python
with client.documents.with_streaming_response.add(
with client.memories.with_streaming_response.add(
text="text",
) as response:
print(response.headers.get("X-My-Header"))
Expand Down
33 changes: 11 additions & 22 deletions api.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,45 +34,34 @@ Methods:

- <code title="get /integrations/web_crawler/index">client.integrations.web_crawler.<a href="./src/hyperspell/resources/integrations/web_crawler.py">index</a>(\*\*<a href="src/hyperspell/types/integrations/web_crawler_index_params.py">params</a>) -> <a href="./src/hyperspell/types/integrations/web_crawler_index_response.py">WebCrawlerIndexResponse</a></code>

# Documents
# Memories

Types:

```python
from hyperspell.types import Document, DocumentStatus, DocumentStatusResponse
from hyperspell.types import Memory, MemoryStatus, MemorySearchResponse, MemoryStatusResponse
```

Methods:

- <code title="get /documents/list">client.documents.<a href="./src/hyperspell/resources/documents.py">list</a>(\*\*<a href="src/hyperspell/types/document_list_params.py">params</a>) -> <a href="./src/hyperspell/types/document.py">SyncCursorPage[Document]</a></code>
- <code title="post /documents/add">client.documents.<a href="./src/hyperspell/resources/documents.py">add</a>(\*\*<a href="src/hyperspell/types/document_add_params.py">params</a>) -> <a href="./src/hyperspell/types/document_status.py">DocumentStatus</a></code>
- <code title="get /documents/get/{source}/{resource_id}">client.documents.<a href="./src/hyperspell/resources/documents.py">get</a>(resource_id, \*, source) -> <a href="./src/hyperspell/types/document.py">Document</a></code>
- <code title="get /documents/status">client.documents.<a href="./src/hyperspell/resources/documents.py">status</a>() -> <a href="./src/hyperspell/types/document_status_response.py">DocumentStatusResponse</a></code>
- <code title="post /documents/upload">client.documents.<a href="./src/hyperspell/resources/documents.py">upload</a>(\*\*<a href="src/hyperspell/types/document_upload_params.py">params</a>) -> <a href="./src/hyperspell/types/document_status.py">DocumentStatus</a></code>
- <code title="get /memories/list">client.memories.<a href="./src/hyperspell/resources/memories.py">list</a>(\*\*<a href="src/hyperspell/types/memory_list_params.py">params</a>) -> <a href="./src/hyperspell/types/memory.py">SyncCursorPage[Memory]</a></code>
- <code title="post /memories/add">client.memories.<a href="./src/hyperspell/resources/memories.py">add</a>(\*\*<a href="src/hyperspell/types/memory_add_params.py">params</a>) -> <a href="./src/hyperspell/types/memory_status.py">MemoryStatus</a></code>
- <code title="get /memories/get/{source}/{resource_id}">client.memories.<a href="./src/hyperspell/resources/memories.py">get</a>(resource_id, \*, source) -> <a href="./src/hyperspell/types/memory.py">Memory</a></code>
- <code title="post /memories/query">client.memories.<a href="./src/hyperspell/resources/memories.py">search</a>(\*\*<a href="src/hyperspell/types/memory_search_params.py">params</a>) -> <a href="./src/hyperspell/types/memory_search_response.py">MemorySearchResponse</a></code>
- <code title="get /memories/status">client.memories.<a href="./src/hyperspell/resources/memories.py">status</a>() -> <a href="./src/hyperspell/types/memory_status_response.py">MemoryStatusResponse</a></code>
- <code title="post /memories/upload">client.memories.<a href="./src/hyperspell/resources/memories.py">upload</a>(\*\*<a href="src/hyperspell/types/memory_upload_params.py">params</a>) -> <a href="./src/hyperspell/types/memory_status.py">MemoryStatus</a></code>

# Collections
# Vaults

Types:

```python
from hyperspell.types import CollectionListResponse
from hyperspell.types import VaultListResponse
```

Methods:

- <code title="get /collections/list">client.collections.<a href="./src/hyperspell/resources/collections.py">list</a>(\*\*<a href="src/hyperspell/types/collection_list_params.py">params</a>) -> <a href="./src/hyperspell/types/collection_list_response.py">SyncCursorPage[CollectionListResponse]</a></code>

# Query

Types:

```python
from hyperspell.types import QuerySearchResponse
```

Methods:

- <code title="post /query">client.query.<a href="./src/hyperspell/resources/query.py">search</a>(\*\*<a href="src/hyperspell/types/query_search_params.py">params</a>) -> <a href="./src/hyperspell/types/query_search_response.py">QuerySearchResponse</a></code>
- <code title="get /vault/list">client.vaults.<a href="./src/hyperspell/resources/vaults.py">list</a>(\*\*<a href="src/hyperspell/types/vault_list_params.py">params</a>) -> <a href="./src/hyperspell/types/vault_list_response.py">SyncCursorPage[VaultListResponse]</a></code>

# Auth

Expand Down
2 changes: 1 addition & 1 deletion bin/check-release-environment
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
errors=()

if [ -z "${PYPI_TOKEN}" ]; then
errors+=("The HYPERSPELL_PYPI_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets.")
errors+=("The PYPI_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets.")
fi

lenErrors=${#errors[@]}
Expand Down
Loading