Skip to content

Commit 29298e2

Browse files
committed
Add 3.0.0 migration guidance and release checks
1 parent 74e6b14 commit 29298e2

9 files changed

Lines changed: 513 additions & 358 deletions

File tree

‎.fernignore‎

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@
22

33
.github/workflows/sdk-release-pr-notification.yml
44
README.md
5-
src/vapi/assistants/types/update_assistant_dto_server_messages_item.py
6-
src/vapi/types/assistant_overrides_server_messages_item.py
7-
src/vapi/types/assistant_server_messages_item.py
8-
src/vapi/types/create_assistant_dto_server_messages_item.py
95

106
changelog.md
117
.fern/replay.lock
128
.fern/replay.yml
139
.gitattributes
10+
11+
# Release checks and regression tests maintained in this repository
12+
.github/workflows/ci.yml
13+
tests/custom/test_structured_output_run.py
14+
tests/custom/test_vapi_managed_model.py
15+
tests/custom/test_tool_variants.py
16+
tests/custom/test_model_deprecation_notice.py

‎.github/workflows/ci.yml‎

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: ci
2-
on: [push]
2+
on: [push, pull_request, workflow_dispatch]
33

44
concurrency:
55
group: ${{ github.workflow }}-${{ github.ref }}
@@ -12,7 +12,7 @@ jobs:
1212
- name: Checkout repo
1313
uses: actions/checkout@v4
1414
- name: Set up python
15-
uses: actions/setup-python@v4
15+
uses: actions/setup-python@v7
1616
with:
1717
python-version: "3.10"
1818
- name: Bootstrap poetry
@@ -24,27 +24,51 @@ jobs:
2424
run: poetry run mypy .
2525
test:
2626
runs-on: ubuntu-latest
27+
strategy:
28+
fail-fast: false
29+
matrix:
30+
python: ["3.10", "3.11", "3.12", "3.13", "3.14"]
31+
pydantic: [">=2,<3"]
32+
include:
33+
- python: "3.10"
34+
pydantic: ">=1.10.26,<2"
35+
- python: "3.12"
36+
pydantic: ">=1.10.26,<2"
2737
steps:
2838
- name: Checkout repo
2939
uses: actions/checkout@v4
3040
- name: Set up python
31-
uses: actions/setup-python@v4
41+
uses: actions/setup-python@v7
3242
with:
33-
python-version: "3.10"
34-
- name: Bootstrap poetry
43+
python-version: ${{ matrix.python }}
44+
- name: Build and install wheel
45+
env:
46+
PYDANTIC_REQUIREMENT: ${{ matrix.pydantic }}
3547
run: |
36-
curl -sSL https://install.python-poetry.org | python - -y --version 1.5.1
37-
- name: Install dependencies
38-
run: poetry install
48+
python -m pip wheel --no-deps --wheel-dir dist .
49+
python -m pip install dist/*.whl "pydantic$PYDANTIC_REQUIREMENT" "pytest>=8.2,<9" "pytest-asyncio>=1,<2" "pytest-xdist>=3.6.1,<4" "python-dateutil>=2.9,<3"
50+
python -m pip check
3951
4052
- name: Test
41-
run: poetry run pytest -rP -n auto .
53+
run: python -m pytest -rP -n auto tests
4254

4355
- name: Install aiohttp extra
44-
run: poetry install --extras aiohttp
56+
run: python -m pip install "$(find dist -name '*.whl')[aiohttp]"
4557

4658
- name: Test (aiohttp)
47-
run: poetry run pytest -rP -n auto -m aiohttp .
59+
run: python -m pytest -rP -n auto -m aiohttp tests
60+
61+
- name: Verify installed package version and request headers
62+
run: |
63+
python - <<'PY'
64+
import importlib.metadata
65+
from vapi.core.client_wrapper import BaseClientWrapper
66+
67+
version = importlib.metadata.version("vapi_server_sdk")
68+
headers = BaseClientWrapper(token="ci-test", base_url="https://api.vapi.ai").get_headers()
69+
assert headers["X-Fern-SDK-Version"] == version
70+
assert headers["User-Agent"] == f"vapi_server_sdk/{version}"
71+
PY
4872
4973
publish:
5074
needs: [compile, test]
@@ -54,14 +78,23 @@ jobs:
5478
- name: Checkout repo
5579
uses: actions/checkout@v4
5680
- name: Set up python
57-
uses: actions/setup-python@v4
81+
uses: actions/setup-python@v7
5882
with:
5983
python-version: "3.10"
6084
- name: Bootstrap poetry
6185
run: |
6286
curl -sSL https://install.python-poetry.org | python - -y --version 1.5.1
6387
- name: Install dependencies
6488
run: poetry install
89+
- name: Verify tag matches package version
90+
env:
91+
RELEASE_TAG: ${{ github.ref_name }}
92+
run: |
93+
version="$(poetry version --short)"
94+
if [ "$RELEASE_TAG" != "$version" ] && [ "$RELEASE_TAG" != "v$version" ]; then
95+
echo "Tag $RELEASE_TAG does not match package version $version"
96+
exit 1
97+
fi
6598
- name: Publish to pypi
6699
run: |
67100
poetry config repositories.remote https://upload.pypi.org/legacy/

‎README.md‎

Lines changed: 62 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -7,138 +7,131 @@ The Vapi Python library provides convenient access to the Vapi API from Python.
77

88
## Installation
99

10-
```sh
11-
pip install vapi_server_sdk
10+
This release supports Python 3.10 through 3.14.
11+
12+
```bash
13+
python -m pip install vapi_server_sdk
14+
```
15+
16+
Install the optional async transport:
17+
18+
```bash
19+
python -m pip install "vapi_server_sdk[aiohttp]"
20+
```
21+
22+
## Upgrade to 3.0.0
23+
24+
Version 3.0.0 updates the generated types to the current Vapi API definition. Review the [3.0.0 migration notes](./changelog.md) before upgrading from 1.x. Public helper imports, declared model fields, and structured-output run response types have changed.
25+
26+
```bash
27+
python -m pip install --upgrade "vapi_server_sdk>=3.0.0,<4"
1228
```
1329

1430
## Reference
1531

16-
A full reference for this library is available [here](./reference.md).
32+
See the [Python SDK reference](./reference.md) for methods, parameters, and response types.
1733

1834
## Usage
1935

20-
Instantiate and use the client with the following:
36+
Set the `VAPI_API_KEY` environment variable to your Vapi private API key. Create a client and list up to 10 assistants in your organization:
2137

2238
```python
39+
import os
40+
2341
from vapi import Vapi
2442

25-
client = Vapi(
26-
token="YOUR_TOKEN",
27-
)
28-
client.calls.create()
43+
client = Vapi(token=os.environ["VAPI_API_KEY"])
44+
assistants = client.assistants.list(limit=10)
45+
for assistant in assistants:
46+
print(assistant.id)
2947
```
3048

3149
## Async Client
3250

33-
The SDK also exports an `async` client so that you can make non-blocking calls to our API.
51+
Use `AsyncVapi` to await API requests:
3452

3553
```python
3654
import asyncio
55+
import os
3756

3857
from vapi import AsyncVapi
3958

40-
client = AsyncVapi(
41-
token="YOUR_TOKEN",
42-
)
43-
4459

4560
async def main() -> None:
46-
await client.calls.create()
61+
client = AsyncVapi(token=os.environ["VAPI_API_KEY"])
62+
assistants = await client.assistants.list(limit=10)
63+
for assistant in assistants:
64+
print(assistant.id)
4765

4866

4967
asyncio.run(main())
5068
```
5169

5270
## Exception Handling
5371

54-
When the API returns a non-success status code (4xx or 5xx response), a subclass of the following error
55-
will be thrown.
72+
Catch `ApiError` to inspect an unsuccessful API response:
5673

5774
```python
75+
import os
76+
77+
from vapi import Vapi
5878
from vapi.core.api_error import ApiError
5979

80+
client = Vapi(token=os.environ["VAPI_API_KEY"])
6081
try:
61-
client.calls.create(...)
62-
except ApiError as e:
63-
print(e.status_code)
64-
print(e.body)
82+
client.assistants.list(limit=10)
83+
except ApiError as error:
84+
print(error.status_code)
85+
print(error.body)
6586
```
6687

67-
## Pagination
88+
## List Resources
6889

69-
Paginated requests will return a `SyncPager` or `AsyncPager`, which can be used as generators for the underlying object.
70-
71-
```python
72-
from vapi import Vapi
73-
74-
client = Vapi(
75-
token="YOUR_TOKEN",
76-
)
77-
response = client.logs.get()
78-
for item in response:
79-
yield item
80-
# alternatively, you can paginate page-by-page
81-
for page in response.iter_pages():
82-
yield page
83-
```
90+
`client.assistants.list()` returns a Python list. Use its `limit` and timestamp filters to select results. Other endpoints have their own response types and pagination parameters; consult the [SDK reference](./reference.md) for the endpoint you use.
8491

8592
## Advanced
8693

8794
### Retries
8895

89-
The SDK is instrumented with automatic retries with exponential backoff. A request will be retried as long
90-
as the request is deemed retriable and the number of retry attempts has not grown larger than the configured
91-
retry limit (default: 2).
92-
93-
A request is deemed retriable when any of the following HTTP status codes is returned:
96+
The SDK retries HTTP 408, 409, 429, and 5xx responses with backoff. The default maximum is two retries. Set `max_retries` for an individual request:
9497

95-
- [408](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/408) (Timeout)
96-
- [429](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429) (Too Many Requests)
97-
- [5XX](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/500) (Internal Server Errors)
98+
```python
99+
import os
98100

99-
Use the `max_retries` request option to configure this behavior.
101+
from vapi import Vapi
100102

101-
```python
102-
client.calls.create(..., request_options={
103-
"max_retries": 1
104-
})
103+
client = Vapi(token=os.environ["VAPI_API_KEY"])
104+
client.assistants.list(limit=10, request_options={"max_retries": 1})
105105
```
106106

107107
### Timeouts
108108

109-
The SDK defaults to a 60 second timeout. You can configure this with a timeout option at the client or request level.
109+
The default client timeout is 60 seconds. Set `timeout` when creating the client or override it with `timeout_in_seconds` for a request. When you supply a custom HTTPX client, its read timeout becomes the default unless you set `timeout` explicitly.
110110

111111
```python
112+
import os
112113

113114
from vapi import Vapi
114115

115-
client = Vapi(
116-
...,
117-
timeout=20.0,
118-
)
119-
120-
121-
# Override timeout for a specific method
122-
client.calls.create(..., request_options={
123-
"timeout_in_seconds": 1
124-
})
116+
client = Vapi(token=os.environ["VAPI_API_KEY"], timeout=20.0)
117+
client.assistants.list(limit=10, request_options={"timeout_in_seconds": 1})
125118
```
126119

127120
### Custom Client
128121

129-
You can override the `httpx` client to customize it for your use-case. Some common use-cases include support for proxies
130-
and transports.
122+
Pass an HTTPX client to configure its transport. This example sets `HTTPTransport.local_address` and closes the custom client when the block finishes:
123+
131124
```python
125+
import os
126+
132127
import httpx
133128
from vapi import Vapi
134129

135-
client = Vapi(
136-
...,
137-
httpx_client=httpx.Client(
138-
proxies="http://my.test.proxy.example.com",
139-
transport=httpx.HTTPTransport(local_address="0.0.0.0"),
140-
),
141-
)
130+
with httpx.Client(transport=httpx.HTTPTransport(local_address="0.0.0.0")) as http:
131+
client = Vapi(token=os.environ["VAPI_API_KEY"], httpx_client=http)
132+
assistants = client.assistants.list(limit=10)
133+
for assistant in assistants:
134+
print(assistant.id)
142135
```
143136

144137
## Contributing

0 commit comments

Comments
 (0)