wavespeed 1.0.13__tar.gz → 2.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. wavespeed-2.0.0/.github/workflows/tests.yml +39 -0
  2. wavespeed-2.0.0/CHANGELOG.md +53 -0
  3. wavespeed-2.0.0/CLAUDE.md +57 -0
  4. {wavespeed-1.0.13/src/wavespeed.egg-info → wavespeed-2.0.0}/PKG-INFO +2 -143
  5. {wavespeed-1.0.13 → wavespeed-2.0.0}/README.md +0 -139
  6. {wavespeed-1.0.13 → wavespeed-2.0.0}/pyproject.toml +1 -3
  7. {wavespeed-1.0.13 → wavespeed-2.0.0}/src/wavespeed/__init__.py +6 -6
  8. {wavespeed-1.0.13 → wavespeed-2.0.0}/src/wavespeed/_version.py +1 -1
  9. {wavespeed-1.0.13 → wavespeed-2.0.0}/src/wavespeed/api/__init__.py +25 -1
  10. {wavespeed-1.0.13 → wavespeed-2.0.0}/src/wavespeed/api/client.py +20 -0
  11. wavespeed-2.0.0/src/wavespeed/config.py +42 -0
  12. {wavespeed-1.0.13 → wavespeed-2.0.0/src/wavespeed.egg-info}/PKG-INFO +2 -143
  13. wavespeed-2.0.0/src/wavespeed.egg-info/SOURCES.txt +36 -0
  14. wavespeed-2.0.0/src/wavespeed.egg-info/requires.txt +5 -0
  15. wavespeed-2.0.0/src/wavespeed.egg-info/scm_file_list.json +31 -0
  16. {wavespeed-1.0.13 → wavespeed-2.0.0}/src/wavespeed.egg-info/scm_version.json +2 -2
  17. {wavespeed-1.0.13 → wavespeed-2.0.0}/tests/test_api.py +27 -0
  18. wavespeed-2.0.0/tests/test_config.py +62 -0
  19. wavespeed-1.0.13/.dockerignore +0 -12
  20. wavespeed-1.0.13/CLAUDE.md +0 -86
  21. wavespeed-1.0.13/images/build_and_push.sh +0 -113
  22. wavespeed-1.0.13/images/test_worker/Dockerfile +0 -32
  23. wavespeed-1.0.13/images/test_worker/build_and_test.sh +0 -18
  24. wavespeed-1.0.13/images/test_worker/handler.py +0 -101
  25. wavespeed-1.0.13/images/test_worker/requirements.txt +0 -1
  26. wavespeed-1.0.13/images/test_worker/test_input.json +0 -8
  27. wavespeed-1.0.13/src/wavespeed/config.py +0 -274
  28. wavespeed-1.0.13/src/wavespeed/serverless/__init__.py +0 -176
  29. wavespeed-1.0.13/src/wavespeed/serverless/modules/__init__.py +0 -54
  30. wavespeed-1.0.13/src/wavespeed/serverless/modules/fastapi.py +0 -450
  31. wavespeed-1.0.13/src/wavespeed/serverless/modules/handler.py +0 -74
  32. wavespeed-1.0.13/src/wavespeed/serverless/modules/health.py +0 -61
  33. wavespeed-1.0.13/src/wavespeed/serverless/modules/heartbeat.py +0 -140
  34. wavespeed-1.0.13/src/wavespeed/serverless/modules/http.py +0 -247
  35. wavespeed-1.0.13/src/wavespeed/serverless/modules/job.py +0 -236
  36. wavespeed-1.0.13/src/wavespeed/serverless/modules/local.py +0 -147
  37. wavespeed-1.0.13/src/wavespeed/serverless/modules/logger.py +0 -205
  38. wavespeed-1.0.13/src/wavespeed/serverless/modules/progress.py +0 -141
  39. wavespeed-1.0.13/src/wavespeed/serverless/modules/scaler.py +0 -266
  40. wavespeed-1.0.13/src/wavespeed/serverless/modules/state.py +0 -185
  41. wavespeed-1.0.13/src/wavespeed/serverless/utils/__init__.py +0 -23
  42. wavespeed-1.0.13/src/wavespeed/serverless/utils/boto3_utils.py +0 -365
  43. wavespeed-1.0.13/src/wavespeed/serverless/utils/validator.py +0 -173
  44. wavespeed-1.0.13/src/wavespeed/serverless/worker.py +0 -74
  45. wavespeed-1.0.13/src/wavespeed.egg-info/SOURCES.txt +0 -72
  46. wavespeed-1.0.13/src/wavespeed.egg-info/requires.txt +0 -7
  47. wavespeed-1.0.13/src/wavespeed.egg-info/scm_file_list.json +0 -67
  48. wavespeed-1.0.13/tests/test_config.py +0 -82
  49. wavespeed-1.0.13/tests/test_serverless/__init__.py +0 -1
  50. wavespeed-1.0.13/tests/test_serverless/test_modules/__init__.py +0 -1
  51. wavespeed-1.0.13/tests/test_serverless/test_modules/test_fastapi.py +0 -449
  52. wavespeed-1.0.13/tests/test_serverless/test_modules/test_handler.py +0 -195
  53. wavespeed-1.0.13/tests/test_serverless/test_modules/test_http.py +0 -320
  54. wavespeed-1.0.13/tests/test_serverless/test_modules/test_job.py +0 -394
  55. wavespeed-1.0.13/tests/test_serverless/test_modules/test_local.py +0 -246
  56. wavespeed-1.0.13/tests/test_serverless/test_modules/test_logger.py +0 -216
  57. wavespeed-1.0.13/tests/test_serverless/test_modules/test_progress.py +0 -181
  58. wavespeed-1.0.13/tests/test_serverless/test_modules/test_scaler.py +0 -239
  59. wavespeed-1.0.13/tests/test_serverless/test_modules/test_state.py +0 -222
  60. wavespeed-1.0.13/tests/test_serverless/test_utils/__init__.py +0 -1
  61. wavespeed-1.0.13/tests/test_serverless/test_utils/test_validator.py +0 -282
  62. wavespeed-1.0.13/tests/test_serverless/test_worker.py +0 -175
  63. {wavespeed-1.0.13 → wavespeed-2.0.0}/.github/workflows/claude.yml +0 -0
  64. {wavespeed-1.0.13 → wavespeed-2.0.0}/.github/workflows/pre-commit.yml +0 -0
  65. {wavespeed-1.0.13 → wavespeed-2.0.0}/.github/workflows/python-packages.yml +0 -0
  66. {wavespeed-1.0.13 → wavespeed-2.0.0}/.github/workflows/python-publish.yml +0 -0
  67. {wavespeed-1.0.13 → wavespeed-2.0.0}/.gitignore +0 -0
  68. {wavespeed-1.0.13 → wavespeed-2.0.0}/.pre-commit-config.yaml +0 -0
  69. {wavespeed-1.0.13 → wavespeed-2.0.0}/LICENSE +0 -0
  70. {wavespeed-1.0.13 → wavespeed-2.0.0}/MANIFEST.in +0 -0
  71. {wavespeed-1.0.13 → wavespeed-2.0.0}/VERSIONING.md +0 -0
  72. {wavespeed-1.0.13 → wavespeed-2.0.0}/assets/wavespeed-logo-dark.svg +0 -0
  73. {wavespeed-1.0.13 → wavespeed-2.0.0}/assets/wavespeed-logo-light.svg +0 -0
  74. {wavespeed-1.0.13 → wavespeed-2.0.0}/pytest.ini +0 -0
  75. {wavespeed-1.0.13 → wavespeed-2.0.0}/setup.cfg +0 -0
  76. {wavespeed-1.0.13 → wavespeed-2.0.0}/src/wavespeed/_config_module.py +0 -0
  77. {wavespeed-1.0.13 → wavespeed-2.0.0}/src/wavespeed.egg-info/dependency_links.txt +0 -0
  78. {wavespeed-1.0.13 → wavespeed-2.0.0}/src/wavespeed.egg-info/not-zip-safe +0 -0
  79. {wavespeed-1.0.13 → wavespeed-2.0.0}/src/wavespeed.egg-info/top_level.txt +0 -0
  80. {wavespeed-1.0.13 → wavespeed-2.0.0}/tests/__init__.py +0 -0
  81. {wavespeed-1.0.13 → wavespeed-2.0.0}/tests/conftest.py +0 -0
@@ -0,0 +1,39 @@
1
+ name: tests
2
+
3
+ on:
4
+ pull_request:
5
+ branches:
6
+ - main
7
+ push:
8
+ branches:
9
+ - main
10
+ tags:
11
+ - "v[0-9]+*"
12
+ workflow_dispatch:
13
+
14
+ permissions:
15
+ contents: read
16
+
17
+ jobs:
18
+ # The package advertises Python >=3.8, so every advertised version is tested.
19
+ # PEP 604 syntax is only legal at runtime on 3.10+, which is why the modules
20
+ # carrying annotations import `from __future__ import annotations`; this
21
+ # matrix is what keeps that from silently regressing.
22
+ test:
23
+ runs-on: ubuntu-latest
24
+ strategy:
25
+ fail-fast: false
26
+ matrix:
27
+ python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
28
+ steps:
29
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
30
+ with:
31
+ fetch-depth: 0
32
+ persist-credentials: false
33
+ - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
34
+ with:
35
+ python-version: ${{ matrix.python-version }}
36
+ - run: python -m pip install --upgrade pip
37
+ - run: pip install -e . pytest
38
+ - run: python -c "import wavespeed; print(wavespeed.__version__)"
39
+ - run: python -m pytest -q
@@ -0,0 +1,53 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here.
4
+
5
+ Versions are derived from Git tags via `setuptools_scm` — see [VERSIONING.md](VERSIONING.md).
6
+
7
+ ## 2.0.0
8
+
9
+ ### Removed — BREAKING
10
+
11
+ **The serverless worker implementation has been removed from the SDK.**
12
+
13
+ WaveSpeed no longer offers serverless as an external product, so shipping a serverless worker in
14
+ the public SDK was misleading: it advertised a capability customers cannot buy. Everything below is
15
+ gone as of 2.0.0 and will not be restored.
16
+
17
+ - `wavespeed.serverless` — the entire package, including `serverless.start()`, the job scaler, the
18
+ handler-type dispatcher, the worker HTTP layer, the FastAPI local dev server, local test mode,
19
+ worker/job state tracking, heartbeat and progress reporting, the S3 (`boto3`) upload helpers, and
20
+ `wavespeed.serverless.utils.validate`.
21
+ - `wavespeed.config.serverless` — the serverless config namespace and its import-time environment
22
+ auto-detection (`RUNPOD_*` and `WAVERLESS_*` variables are no longer read by this package).
23
+ - `images/` — the `test_worker` Docker image and its build/push scripts, which existed only to
24
+ build and exercise the worker.
25
+
26
+ Anyone building workers against this package should pin `wavespeed<2` and plan to migrate.
27
+
28
+ ### Fixed
29
+
30
+ - **Python 3.8 and 3.9 support is now real rather than aspirational.** `api/__init__.py` carried a
31
+ module-level PEP 604 annotation (`Client | None`) with no `__future__` import, so the package
32
+ could not be imported on 3.8 or 3.9 despite `requires-python = ">=3.8"`. CI now runs the suite on
33
+ 3.8 through 3.12 so the claim stays honest.
34
+ - `typing_extensions` is now a declared dependency. It was imported at module scope but only
35
+ reached the environment transitively through `boto3`/`aiohttp` — removing those would have
36
+ produced an `ImportError` on a clean install.
37
+
38
+ ### Changed
39
+
40
+ - Dependencies trimmed to what the API client actually needs. `aiohttp`, `aiohttp[speedups]`,
41
+ `aiohttp-retry`, and `boto3` are no longer installed; `typing_extensions` is now declared
42
+ explicitly (it was already imported by `wavespeed._config_module`).
43
+ - README and CLAUDE.md rewritten to describe an API-client-only SDK.
44
+
45
+ ### Unchanged
46
+
47
+ The API client surface is untouched: `wavespeed.run`, `wavespeed.run_no_throw`,
48
+ `wavespeed.get_result`, `wavespeed.upload`, `wavespeed.Client`, `wavespeed.config.api`, and the
49
+ channel-attribution request headers all behave exactly as they did in 1.0.x.
50
+
51
+ ## 1.0.14 and earlier
52
+
53
+ See the Git history and GitHub releases.
@@ -0,0 +1,57 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ WaveSpeed Python SDK - Official Python SDK for the WaveSpeedAI inference platform. It is an API
8
+ client only: it submits jobs to the hosted WaveSpeed API, polls for results, and uploads files.
9
+
10
+ > As of v2.0.0 the SDK no longer ships a serverless worker implementation. WaveSpeed does not offer
11
+ > serverless as an external product, so that code was removed rather than left in the public SDK.
12
+
13
+ ## Commands
14
+
15
+ ### Testing
16
+ ```bash
17
+ # Run all tests
18
+ python -m pytest
19
+
20
+ # Run a single test file
21
+ python -m pytest tests/test_api.py
22
+
23
+ # Run a specific test
24
+ python -m pytest tests/test_api.py::TestClient::test_run_success -v
25
+ ```
26
+
27
+ ### Linting
28
+ ```bash
29
+ pre-commit run --all-files
30
+ ```
31
+
32
+ ### Local Development
33
+ ```bash
34
+ # Install in editable mode
35
+ pip install -e .
36
+ ```
37
+
38
+ ## Architecture
39
+
40
+ ### API client (`src/wavespeed/api/`)
41
+
42
+ - `client.py` - `Client`, the only transport. Synchronous, built on `requests`. Handles job
43
+ submission, result polling, terminal-status handling, file upload, and the channel-attribution
44
+ headers (`X-Client-Name`, etc.).
45
+ - `__init__.py` - module-level convenience wrappers over a lazily created default `Client`:
46
+ `run`, `run_no_throw`, `get_result`, `upload`.
47
+
48
+ `run` raises on failure; `run_no_throw` returns `{"status", "outputs", "task_id", "error"}` instead,
49
+ mirroring the JavaScript SDK. `get_result` recovers a task whose local wait timed out.
50
+
51
+ ### Configuration (`src/wavespeed/config.py`)
52
+
53
+ A single `api` config class, installed as a config module by `_config_module.py` (the PyTorch-style
54
+ `install_config_module` shim). This gives `wavespeed.config.patch(...)` as a context manager /
55
+ decorator for tests. `Client` reads its defaults from `wavespeed.config.api`.
56
+
57
+ `WAVESPEED_API_KEY` seeds `config.api.api_key` at import time.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wavespeed
3
- Version: 1.0.13
3
+ Version: 2.0.0
4
4
  Summary: WaveSpeed Python Client — Official Python SDK for the WaveSpeed inference platform
5
5
  Author-email: WaveSpeedAI <support@wavespeed.ai>
6
6
  License: MIT
@@ -19,10 +19,8 @@ Classifier: Programming Language :: Python :: 3.12
19
19
  Requires-Python: >=3.8
20
20
  Description-Content-Type: text/markdown
21
21
  License-File: LICENSE
22
- Requires-Dist: aiohttp[speedups]>=3.9.3
23
- Requires-Dist: aiohttp-retry>=2.8.3
24
22
  Requires-Dist: requests>=2.25.0
25
- Requires-Dist: boto3>=1.26.165
23
+ Requires-Dist: typing_extensions>=4.5.0
26
24
  Provides-Extra: test
27
25
  Requires-Dist: pytest; extra == "test"
28
26
  Dynamic: license-file
@@ -142,106 +140,8 @@ url = wavespeed.upload("/path/to/image.png")
142
140
  print(url)
143
141
  ```
144
142
 
145
- ## Serverless Worker
146
-
147
- Build serverless workers for the WaveSpeed platform.
148
-
149
- ### Basic Handler
150
-
151
- ```python
152
- import wavespeed.serverless as serverless
153
-
154
- def handler(job):
155
- job_input = job["input"]
156
- result = job_input.get("prompt", "").upper()
157
- return {"output": result}
158
-
159
- serverless.start({"handler": handler})
160
- ```
161
-
162
- ### Async Handler
163
-
164
- ```python
165
- import wavespeed.serverless as serverless
166
-
167
- async def handler(job):
168
- job_input = job["input"]
169
- result = await process_async(job_input)
170
- return {"output": result}
171
-
172
- serverless.start({"handler": handler})
173
- ```
174
-
175
- ### Generator Handler (Streaming)
176
-
177
- ```python
178
- import wavespeed.serverless as serverless
179
-
180
- def handler(job):
181
- for i in range(10):
182
- yield {"progress": i, "partial": f"chunk-{i}"}
183
-
184
- serverless.start({"handler": handler})
185
- ```
186
-
187
- ### Input Validation
188
-
189
- ```python
190
- from wavespeed.serverless.utils import validate
191
-
192
- INPUT_SCHEMA = {
193
- "prompt": {"type": str, "required": True},
194
- "max_tokens": {"type": int, "required": False, "default": 100},
195
- "temperature": {
196
- "type": float,
197
- "required": False,
198
- "default": 0.7,
199
- "constraints": lambda x: 0 <= x <= 2,
200
- },
201
- }
202
-
203
- def handler(job):
204
- result = validate(job["input"], INPUT_SCHEMA)
205
- if "errors" in result:
206
- return {"error": result["errors"]}
207
-
208
- validated = result["validated_input"]
209
- # process with validated input...
210
- return {"output": "done"}
211
- ```
212
-
213
- ### Concurrent Execution
214
-
215
- Enable concurrent job processing with `concurrency_modifier`:
216
-
217
- ```python
218
- import wavespeed.serverless as serverless
219
-
220
- def handler(job):
221
- return {"output": job["input"]["data"]}
222
-
223
- def concurrency_modifier(current_concurrency):
224
- return 2 # Process 2 jobs concurrently
225
-
226
- serverless.start({
227
- "handler": handler,
228
- "concurrency_modifier": concurrency_modifier
229
- })
230
- ```
231
-
232
143
  ## Local Development
233
144
 
234
- ### Test with JSON Input
235
-
236
- ```bash
237
- # Using CLI argument
238
- python handler.py --test_input '{"input": {"prompt": "hello"}}'
239
-
240
- # Using test_input.json file (auto-detected)
241
- echo '{"input": {"prompt": "hello"}}' > test_input.json
242
- python handler.py
243
- ```
244
-
245
145
  ### Running Tests
246
146
 
247
147
  ```bash
@@ -255,54 +155,13 @@ python -m pytest tests/test_api.py
255
155
  python -m pytest tests/test_api.py::TestClient::test_run_success -v
256
156
  ```
257
157
 
258
- ### FastAPI Development Server
259
-
260
- ```bash
261
- python handler.py --waverless_serve_api --waverless_api_port 8000
262
- ```
263
-
264
- Then use the interactive Swagger UI at `http://localhost:8000/` or make requests:
265
-
266
- ```bash
267
- # Synchronous execution
268
- curl -X POST http://localhost:8000/runsync \
269
- -H "Content-Type: application/json" \
270
- -d '{"input": {"prompt": "hello"}}'
271
-
272
- # Async execution
273
- curl -X POST http://localhost:8000/run \
274
- -H "Content-Type: application/json" \
275
- -d '{"input": {"prompt": "hello"}}'
276
- ```
277
-
278
- ## CLI Options
279
-
280
- | Option | Description |
281
- |--------|-------------|
282
- | `--test_input JSON` | Run locally with JSON test input |
283
- | `--waverless_serve_api` | Start FastAPI development server |
284
- | `--waverless_api_host HOST` | API server host (default: localhost) |
285
- | `--waverless_api_port PORT` | API server port (default: 8000) |
286
- | `--waverless_log_level LEVEL` | Log level (DEBUG, INFO, WARN, ERROR) |
287
-
288
158
  ## Environment Variables
289
159
 
290
- ### API Client
291
-
292
160
  | Variable | Description |
293
161
  |----------|-------------|
294
162
  | `WAVESPEED_API_KEY` | WaveSpeed API key |
295
163
  | `WAVESPEED_CLIENT_NAME` | Channel-attribution name sent as the `X-Client-Name` header (overrides the `client_name` parameter; defaults to `wavespeed-python`) |
296
164
 
297
- ### Serverless Worker
298
-
299
- | Variable | Description |
300
- |----------|-------------|
301
- | `WAVERLESS_POD_ID` | Worker/pod identifier |
302
- | `WAVERLESS_API_KEY` | API authentication key |
303
- | `WAVERLESS_WEBHOOK_GET_JOB` | Job fetch endpoint |
304
- | `WAVERLESS_WEBHOOK_POST_OUTPUT` | Result submission endpoint |
305
-
306
165
  ## License
307
166
 
308
167
  MIT
@@ -113,106 +113,8 @@ url = wavespeed.upload("/path/to/image.png")
113
113
  print(url)
114
114
  ```
115
115
 
116
- ## Serverless Worker
117
-
118
- Build serverless workers for the WaveSpeed platform.
119
-
120
- ### Basic Handler
121
-
122
- ```python
123
- import wavespeed.serverless as serverless
124
-
125
- def handler(job):
126
- job_input = job["input"]
127
- result = job_input.get("prompt", "").upper()
128
- return {"output": result}
129
-
130
- serverless.start({"handler": handler})
131
- ```
132
-
133
- ### Async Handler
134
-
135
- ```python
136
- import wavespeed.serverless as serverless
137
-
138
- async def handler(job):
139
- job_input = job["input"]
140
- result = await process_async(job_input)
141
- return {"output": result}
142
-
143
- serverless.start({"handler": handler})
144
- ```
145
-
146
- ### Generator Handler (Streaming)
147
-
148
- ```python
149
- import wavespeed.serverless as serverless
150
-
151
- def handler(job):
152
- for i in range(10):
153
- yield {"progress": i, "partial": f"chunk-{i}"}
154
-
155
- serverless.start({"handler": handler})
156
- ```
157
-
158
- ### Input Validation
159
-
160
- ```python
161
- from wavespeed.serverless.utils import validate
162
-
163
- INPUT_SCHEMA = {
164
- "prompt": {"type": str, "required": True},
165
- "max_tokens": {"type": int, "required": False, "default": 100},
166
- "temperature": {
167
- "type": float,
168
- "required": False,
169
- "default": 0.7,
170
- "constraints": lambda x: 0 <= x <= 2,
171
- },
172
- }
173
-
174
- def handler(job):
175
- result = validate(job["input"], INPUT_SCHEMA)
176
- if "errors" in result:
177
- return {"error": result["errors"]}
178
-
179
- validated = result["validated_input"]
180
- # process with validated input...
181
- return {"output": "done"}
182
- ```
183
-
184
- ### Concurrent Execution
185
-
186
- Enable concurrent job processing with `concurrency_modifier`:
187
-
188
- ```python
189
- import wavespeed.serverless as serverless
190
-
191
- def handler(job):
192
- return {"output": job["input"]["data"]}
193
-
194
- def concurrency_modifier(current_concurrency):
195
- return 2 # Process 2 jobs concurrently
196
-
197
- serverless.start({
198
- "handler": handler,
199
- "concurrency_modifier": concurrency_modifier
200
- })
201
- ```
202
-
203
116
  ## Local Development
204
117
 
205
- ### Test with JSON Input
206
-
207
- ```bash
208
- # Using CLI argument
209
- python handler.py --test_input '{"input": {"prompt": "hello"}}'
210
-
211
- # Using test_input.json file (auto-detected)
212
- echo '{"input": {"prompt": "hello"}}' > test_input.json
213
- python handler.py
214
- ```
215
-
216
118
  ### Running Tests
217
119
 
218
120
  ```bash
@@ -226,54 +128,13 @@ python -m pytest tests/test_api.py
226
128
  python -m pytest tests/test_api.py::TestClient::test_run_success -v
227
129
  ```
228
130
 
229
- ### FastAPI Development Server
230
-
231
- ```bash
232
- python handler.py --waverless_serve_api --waverless_api_port 8000
233
- ```
234
-
235
- Then use the interactive Swagger UI at `http://localhost:8000/` or make requests:
236
-
237
- ```bash
238
- # Synchronous execution
239
- curl -X POST http://localhost:8000/runsync \
240
- -H "Content-Type: application/json" \
241
- -d '{"input": {"prompt": "hello"}}'
242
-
243
- # Async execution
244
- curl -X POST http://localhost:8000/run \
245
- -H "Content-Type: application/json" \
246
- -d '{"input": {"prompt": "hello"}}'
247
- ```
248
-
249
- ## CLI Options
250
-
251
- | Option | Description |
252
- |--------|-------------|
253
- | `--test_input JSON` | Run locally with JSON test input |
254
- | `--waverless_serve_api` | Start FastAPI development server |
255
- | `--waverless_api_host HOST` | API server host (default: localhost) |
256
- | `--waverless_api_port PORT` | API server port (default: 8000) |
257
- | `--waverless_log_level LEVEL` | Log level (DEBUG, INFO, WARN, ERROR) |
258
-
259
131
  ## Environment Variables
260
132
 
261
- ### API Client
262
-
263
133
  | Variable | Description |
264
134
  |----------|-------------|
265
135
  | `WAVESPEED_API_KEY` | WaveSpeed API key |
266
136
  | `WAVESPEED_CLIENT_NAME` | Channel-attribution name sent as the `X-Client-Name` header (overrides the `client_name` parameter; defaults to `wavespeed-python`) |
267
137
 
268
- ### Serverless Worker
269
-
270
- | Variable | Description |
271
- |----------|-------------|
272
- | `WAVERLESS_POD_ID` | Worker/pod identifier |
273
- | `WAVERLESS_API_KEY` | API authentication key |
274
- | `WAVERLESS_WEBHOOK_GET_JOB` | Job fetch endpoint |
275
- | `WAVERLESS_WEBHOOK_POST_OUTPUT` | Result submission endpoint |
276
-
277
138
  ## License
278
139
 
279
140
  MIT
@@ -25,10 +25,8 @@ classifiers = [
25
25
  dynamic = ["version"]
26
26
 
27
27
  dependencies = [
28
- "aiohttp[speedups]>=3.9.3",
29
- "aiohttp-retry>=2.8.3",
30
28
  "requests>=2.25.0",
31
- "boto3>=1.26.165",
29
+ "typing_extensions>=4.5.0",
32
30
  ]
33
31
 
34
32
  [project.urls]
@@ -1,9 +1,9 @@
1
1
  """
2
2
  WaveSpeedAI Python Client — Official Python SDK for WaveSpeedAI inference platform.
3
3
 
4
- This library provides a clean, unified, and high-performance API and serverless
5
- integration layer for your applications. Effortlessly connect to all
6
- WaveSpeedAI models and inference services with zero infrastructure overhead.
4
+ This library provides a clean, unified, and high-performance API client for
5
+ your applications. Effortlessly connect to all WaveSpeedAI models and
6
+ inference services with zero infrastructure overhead.
7
7
 
8
8
  Example usage:
9
9
  import wavespeed
@@ -21,10 +21,10 @@ except ImportError:
21
21
  # Version file doesn't exist yet (e.g., during initial development)
22
22
  __version__ = "0.0.0.dev0"
23
23
 
24
- # Import config to auto-detect and load serverless environment
24
+ # Import config so `wavespeed.config` is available after `import wavespeed`
25
25
  from wavespeed import config # noqa: F401
26
26
 
27
27
  # Import API client
28
- from wavespeed.api import Client, run, run_no_throw, upload
28
+ from wavespeed.api import Client, get_result, run, run_no_throw, upload
29
29
 
30
- __all__ = ["__version__", "Client", "run", "run_no_throw", "upload"]
30
+ __all__ = ["__version__", "Client", "get_result", "run", "run_no_throw", "upload"]
@@ -1,2 +1,2 @@
1
1
  # This file is automatically generated by setuptools_scm
2
- __version__ = "1.0.13"
2
+ __version__ = "2.0.0"
@@ -17,11 +17,13 @@ Example usage:
17
17
  print(url) # URL of the uploaded file
18
18
  """
19
19
 
20
+ from __future__ import annotations
21
+
20
22
  from typing import BinaryIO
21
23
 
22
24
  from wavespeed.api.client import Client
23
25
 
24
- __all__ = ["Client", "run", "run_no_throw", "upload"]
26
+ __all__ = ["Client", "get_result", "run", "run_no_throw", "upload"]
25
27
 
26
28
  # Default client instance
27
29
  _default_client: Client | None = None
@@ -96,6 +98,28 @@ def run(
96
98
  )
97
99
 
98
100
 
101
+ def get_result(
102
+ request_id: str,
103
+ *,
104
+ timeout: float | None = None,
105
+ api_key: str | None = None,
106
+ ) -> dict:
107
+ """Fetch a prediction's current state by id.
108
+
109
+ Recovers a task whose local wait timed out — it keeps running server-side.
110
+
111
+ Args:
112
+ request_id: The prediction request ID.
113
+ timeout: Request timeout in seconds.
114
+ api_key: Override the API key for this call.
115
+
116
+ Returns:
117
+ Full API response, including ``data.status`` and ``data.outputs``.
118
+ """
119
+ client = Client(api_key=api_key) if api_key else _get_default_client()
120
+ return client.get_result(request_id, timeout=timeout)
121
+
122
+
99
123
  def run_no_throw(
100
124
  model: str,
101
125
  input: dict | None = None,
@@ -195,6 +195,26 @@ class Client:
195
195
 
196
196
  return request_id, None
197
197
 
198
+ def get_result(
199
+ self, request_id: str, timeout: float | None = None
200
+ ) -> dict[str, Any]:
201
+ """Fetch a prediction's current state by id.
202
+
203
+ Useful for recovering a task whose local wait timed out: the task keeps
204
+ running server-side, and this returns whatever state it has reached.
205
+
206
+ Args:
207
+ request_id: The prediction request ID.
208
+ timeout: Request timeout in seconds.
209
+
210
+ Returns:
211
+ Full API response, including ``data.status`` and ``data.outputs``.
212
+
213
+ Raises:
214
+ RuntimeError: If fetching the result fails after retries.
215
+ """
216
+ return self._get_result(request_id, timeout=timeout)
217
+
198
218
  def _get_result(
199
219
  self, request_id: str, timeout: float | None = None
200
220
  ) -> dict[str, Any]:
@@ -0,0 +1,42 @@
1
+ """Configuration module for WaveSpeed SDK."""
2
+
3
+ import os
4
+ import sys
5
+ from typing import Optional
6
+
7
+ from ._config_module import install_config_module
8
+
9
+
10
+ _save_config_ignore = {
11
+ # workaround: "Can't pickle <function ...>"
12
+ }
13
+
14
+
15
+ class api:
16
+ """API client configuration options."""
17
+
18
+ # Authentication
19
+ api_key: Optional[str] = os.environ.get("WAVESPEED_API_KEY")
20
+
21
+ # API base URL
22
+ base_url: str = "https://api.wavespeed.ai"
23
+
24
+ # Connection timeout in seconds
25
+ connection_timeout: float = 10.0
26
+
27
+ # Total API call timeout in seconds
28
+ timeout: float = 36000.0
29
+
30
+ # Maximum number of retries for the entire operation (task-level retries)
31
+ max_retries: int = 0
32
+
33
+ # Maximum retries for idempotent result-query GET requests. Submission
34
+ # POSTs are intentionally sent at most once.
35
+ max_connection_retries: int = 5
36
+
37
+ # Base interval between retries in seconds (actual delay = retry_interval * attempt)
38
+ retry_interval: float = 1.0
39
+
40
+
41
+ # adds patch, save_config, etc
42
+ install_config_module(sys.modules[__name__])