runcrate-sdk 0.1.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 (39) hide show
  1. runcrate_sdk-0.1.0/.github/workflows/notify-monorepo.yml +17 -0
  2. runcrate_sdk-0.1.0/.github/workflows/publish.yml +20 -0
  3. runcrate_sdk-0.1.0/PKG-INFO +276 -0
  4. runcrate_sdk-0.1.0/README.md +256 -0
  5. runcrate_sdk-0.1.0/pyproject.toml +45 -0
  6. runcrate_sdk-0.1.0/src/runcrate/__init__.py +44 -0
  7. runcrate_sdk-0.1.0/src/runcrate/_client.py +323 -0
  8. runcrate_sdk-0.1.0/src/runcrate/_config.py +51 -0
  9. runcrate_sdk-0.1.0/src/runcrate/_exceptions.py +147 -0
  10. runcrate_sdk-0.1.0/src/runcrate/_pagination.py +40 -0
  11. runcrate_sdk-0.1.0/src/runcrate/_transport.py +211 -0
  12. runcrate_sdk-0.1.0/src/runcrate/models/__init__.py +41 -0
  13. runcrate_sdk-0.1.0/src/runcrate/models/billing.py +36 -0
  14. runcrate_sdk-0.1.0/src/runcrate/models/environments.py +27 -0
  15. runcrate_sdk-0.1.0/src/runcrate/models/instances.py +68 -0
  16. runcrate_sdk-0.1.0/src/runcrate/models/models.py +172 -0
  17. runcrate_sdk-0.1.0/src/runcrate/models/shared.py +15 -0
  18. runcrate_sdk-0.1.0/src/runcrate/models/ssh_keys.py +26 -0
  19. runcrate_sdk-0.1.0/src/runcrate/models/storage.py +44 -0
  20. runcrate_sdk-0.1.0/src/runcrate/models/templates.py +18 -0
  21. runcrate_sdk-0.1.0/src/runcrate/resources/__init__.py +26 -0
  22. runcrate_sdk-0.1.0/src/runcrate/resources/billing.py +103 -0
  23. runcrate_sdk-0.1.0/src/runcrate/resources/environments.py +95 -0
  24. runcrate_sdk-0.1.0/src/runcrate/resources/instances.py +189 -0
  25. runcrate_sdk-0.1.0/src/runcrate/resources/models.py +502 -0
  26. runcrate_sdk-0.1.0/src/runcrate/resources/ssh_keys.py +69 -0
  27. runcrate_sdk-0.1.0/src/runcrate/resources/storage.py +121 -0
  28. runcrate_sdk-0.1.0/src/runcrate/resources/templates.py +77 -0
  29. runcrate_sdk-0.1.0/tests/__init__.py +0 -0
  30. runcrate_sdk-0.1.0/tests/conftest.py +32 -0
  31. runcrate_sdk-0.1.0/tests/test_billing.py +84 -0
  32. runcrate_sdk-0.1.0/tests/test_client.py +74 -0
  33. runcrate_sdk-0.1.0/tests/test_instances.py +162 -0
  34. runcrate_sdk-0.1.0/tests/test_models.py +236 -0
  35. runcrate_sdk-0.1.0/tests/test_pagination.py +42 -0
  36. runcrate_sdk-0.1.0/tests/test_retry.py +64 -0
  37. runcrate_sdk-0.1.0/tests/test_ssh_keys.py +65 -0
  38. runcrate_sdk-0.1.0/tests/test_storage.py +146 -0
  39. runcrate_sdk-0.1.0/tests/test_templates.py +69 -0
@@ -0,0 +1,17 @@
1
+ name: Notify Monorepo
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+
7
+ jobs:
8
+ notify:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - name: Trigger monorepo sync
12
+ run: |
13
+ curl -X POST \
14
+ -H "Authorization: token ${{ secrets.MONOREPO_TOKEN }}" \
15
+ -H "Accept: application/vnd.github.v3+json" \
16
+ https://api.github.com/repos/aeonmindai/runcrate_app/dispatches \
17
+ -d '{"event_type":"sdk-updated"}'
@@ -0,0 +1,20 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags: ['v*']
6
+
7
+ jobs:
8
+ publish:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - uses: actions/checkout@v4
12
+ - uses: actions/setup-python@v5
13
+ with:
14
+ python-version: '3.11'
15
+ - run: pip install build twine
16
+ - run: python -m build
17
+ - run: twine upload dist/*
18
+ env:
19
+ TWINE_USERNAME: __token__
20
+ TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
@@ -0,0 +1,276 @@
1
+ Metadata-Version: 2.4
2
+ Name: runcrate-sdk
3
+ Version: 0.1.0
4
+ Summary: Official Python SDK for the Runcrate API
5
+ Project-URL: Homepage, https://runcrate.ai
6
+ Project-URL: Repository, https://github.com/aeonmindai/runcrate-py
7
+ Project-URL: Documentation, https://runcrate.ai/docs
8
+ Author-email: Runcrate <support@runcrate.ai>
9
+ License-Expression: MIT
10
+ Requires-Python: >=3.9
11
+ Requires-Dist: httpx<1.0,>=0.25.0
12
+ Requires-Dist: pydantic<3.0,>=2.0
13
+ Provides-Extra: dev
14
+ Requires-Dist: mypy>=1.0; extra == 'dev'
15
+ Requires-Dist: pytest-asyncio>=0.21; extra == 'dev'
16
+ Requires-Dist: pytest>=7.0; extra == 'dev'
17
+ Requires-Dist: respx>=0.21; extra == 'dev'
18
+ Requires-Dist: ruff>=0.4; extra == 'dev'
19
+ Description-Content-Type: text/markdown
20
+
21
+ # Runcrate Python SDK
22
+
23
+ Official Python SDK for the [Runcrate](https://runcrate.ai) API.
24
+
25
+ ## Installation
26
+
27
+ ```bash
28
+ pip install runcrate
29
+ ```
30
+
31
+ ## Quick Start
32
+
33
+ ```python
34
+ from runcrate import Runcrate
35
+
36
+ client = Runcrate(api_key="rc_live_...")
37
+
38
+ # Chat completion
39
+ response = client.models.chat_completion(
40
+ model="meta-llama/Meta-Llama-3.1-8B-Instruct",
41
+ messages=[{"role": "user", "content": "Hello!"}],
42
+ )
43
+ print(response.choices[0].message.content)
44
+
45
+ # List GPU instances
46
+ instances = client.instances.list()
47
+
48
+ # Create an instance
49
+ instance = client.instances.create(
50
+ name="training-run",
51
+ ssh_key_id="key_abc123",
52
+ gpu_type="A100",
53
+ )
54
+
55
+ # Check status
56
+ status = client.instances.get_status(instance.id)
57
+ print(status.status, status.ip)
58
+
59
+ # Check billing
60
+ balance = client.billing.get_balance()
61
+ print(f"Credits: ${balance.credits_balance}")
62
+
63
+ client.close()
64
+ ```
65
+
66
+ ## Async Usage
67
+
68
+ ```python
69
+ import asyncio
70
+ from runcrate import AsyncRuncrate
71
+
72
+ async def main():
73
+ async with AsyncRuncrate(api_key="rc_live_...") as client:
74
+ response = await client.models.chat_completion(
75
+ model="meta-llama/Meta-Llama-3.1-8B-Instruct",
76
+ messages=[{"role": "user", "content": "Hello!"}],
77
+ )
78
+ print(response.choices[0].message.content)
79
+
80
+ asyncio.run(main())
81
+ ```
82
+
83
+ ## Configuration
84
+
85
+ ```python
86
+ client = Runcrate(
87
+ api_key="rc_live_...", # or set RUNCRATE_API_KEY env var
88
+ base_url="https://runcrate.ai", # infra API (default)
89
+ inference_url="https://api.runcrate.ai", # model inference API (default)
90
+ timeout=30.0, # request timeout in seconds
91
+ max_retries=3, # retry on 429/5xx with exponential backoff
92
+ )
93
+ ```
94
+
95
+ ## Model Inference
96
+
97
+ The `client.models` resource connects to `api.runcrate.ai` for AI model inference. Same API key works for both infrastructure and inference.
98
+
99
+ ### Chat Completions
100
+
101
+ ```python
102
+ # Standard request
103
+ response = client.models.chat_completion(
104
+ model="meta-llama/Meta-Llama-3.1-8B-Instruct",
105
+ messages=[
106
+ {"role": "system", "content": "You are a helpful assistant."},
107
+ {"role": "user", "content": "Explain quantum computing in 3 sentences."},
108
+ ],
109
+ max_tokens=256,
110
+ temperature=0.7,
111
+ )
112
+ print(response.choices[0].message.content)
113
+ print(f"Tokens used: {response.usage.total_tokens}")
114
+
115
+ # Streaming
116
+ for chunk in client.models.chat_completion(
117
+ model="meta-llama/Meta-Llama-3.1-8B-Instruct",
118
+ messages=[{"role": "user", "content": "Write a poem about GPUs"}],
119
+ stream=True,
120
+ ):
121
+ delta = chunk.get("choices", [{}])[0].get("delta", {})
122
+ print(delta.get("content", ""), end="", flush=True)
123
+ ```
124
+
125
+ ### Image Generation
126
+
127
+ ```python
128
+ result = client.models.generate_image(
129
+ model="black-forest-labs/FLUX.1-schnell",
130
+ prompt="A futuristic city skyline at sunset",
131
+ width=1024,
132
+ height=1024,
133
+ )
134
+ # result.data[0].b64_json contains the base64-encoded image
135
+ ```
136
+
137
+ ### Video Generation
138
+
139
+ ```python
140
+ # Submit video job (async processing)
141
+ job = client.models.generate_video(
142
+ model="google/veo-3.0",
143
+ prompt="A drone flyover of a mountain landscape",
144
+ duration=8,
145
+ )
146
+ print(f"Job ID: {job.id}, Status: {job.status}")
147
+
148
+ # Poll until complete
149
+ import time
150
+ while True:
151
+ job = client.models.get_video_status(job.id)
152
+ print(f"Status: {job.status}")
153
+ if job.status in ("completed", "failed"):
154
+ break
155
+ time.sleep(5)
156
+
157
+ # Download the video
158
+ if job.status == "completed":
159
+ video_bytes = client.models.download_video(job.id)
160
+ with open("output.mp4", "wb") as f:
161
+ f.write(video_bytes)
162
+ ```
163
+
164
+ ### Text-to-Speech
165
+
166
+ ```python
167
+ audio_bytes = client.models.text_to_speech(
168
+ model="openai/tts-1",
169
+ input="Hello, welcome to Runcrate!",
170
+ voice="alloy",
171
+ response_format="mp3",
172
+ )
173
+ with open("speech.mp3", "wb") as f:
174
+ f.write(audio_bytes)
175
+ ```
176
+
177
+ ### Transcription (Speech-to-Text)
178
+
179
+ ```python
180
+ with open("audio.wav", "rb") as f:
181
+ result = client.models.transcribe(
182
+ model="openai/whisper-1",
183
+ file=f,
184
+ filename="audio.wav",
185
+ )
186
+ print(result.text)
187
+ print(f"Duration: {result.duration}s")
188
+ ```
189
+
190
+ ## Infrastructure Resources
191
+
192
+ ### Instances
193
+
194
+ ```python
195
+ client.instances.list(search="my-gpu")
196
+ client.instances.create(name="run", ssh_key_id="key", gpu_type="A100")
197
+ client.instances.get("instance-id")
198
+ client.instances.terminate("instance-id")
199
+ client.instances.get_status("instance-id")
200
+ client.instances.list_types(gpu_type="A100", region="us-east")
201
+ ```
202
+
203
+ ### Environments
204
+
205
+ ```python
206
+ client.environments.list()
207
+ client.environments.create(name="staging")
208
+ client.environments.get("env-id")
209
+ client.environments.update("env-id", name="production")
210
+ client.environments.delete("env-id")
211
+ ```
212
+
213
+ ### SSH Keys
214
+
215
+ ```python
216
+ client.ssh_keys.list()
217
+ client.ssh_keys.create(name="my-key", public_key="ssh-ed25519 AAAA...")
218
+ client.ssh_keys.delete("key-id")
219
+ ```
220
+
221
+ ### Storage
222
+
223
+ ```python
224
+ client.storage.list()
225
+ client.storage.get("volume-id")
226
+ ```
227
+
228
+ ### Billing
229
+
230
+ ```python
231
+ client.billing.get_balance()
232
+ client.billing.list_transactions(limit=10, offset=0)
233
+ client.billing.usage(from_date="2025-01-01", to_date="2025-01-31")
234
+ ```
235
+
236
+ ### Templates
237
+
238
+ ```python
239
+ client.templates.list(search="cuda", category="ml", page_size=10)
240
+ ```
241
+
242
+ ## Error Handling
243
+
244
+ ```python
245
+ from runcrate import Runcrate, NotFoundError, InsufficientCreditsError, RateLimitError
246
+
247
+ client = Runcrate(api_key="rc_live_...")
248
+
249
+ try:
250
+ instance = client.instances.get("nonexistent")
251
+ except NotFoundError as e:
252
+ print(f"Not found: {e.message}")
253
+ except InsufficientCreditsError as e:
254
+ print(f"Need more credits: {e.message}")
255
+ except RateLimitError as e:
256
+ print(f"Rate limited: {e.message}")
257
+ ```
258
+
259
+ ## Pagination
260
+
261
+ ```python
262
+ # Transactions support offset-based pagination
263
+ page = client.billing.list_transactions(limit=10, offset=0)
264
+ print(page.data) # list of Transaction objects
265
+ print(page.has_more) # True if more pages exist
266
+ print(page.total) # total count
267
+
268
+ # Templates support page-based pagination
269
+ templates = client.templates.list(page=1, page_size=25)
270
+ ```
271
+
272
+ ## Requirements
273
+
274
+ - Python >= 3.9
275
+ - httpx >= 0.25.0
276
+ - pydantic >= 2.0
@@ -0,0 +1,256 @@
1
+ # Runcrate Python SDK
2
+
3
+ Official Python SDK for the [Runcrate](https://runcrate.ai) API.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install runcrate
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```python
14
+ from runcrate import Runcrate
15
+
16
+ client = Runcrate(api_key="rc_live_...")
17
+
18
+ # Chat completion
19
+ response = client.models.chat_completion(
20
+ model="meta-llama/Meta-Llama-3.1-8B-Instruct",
21
+ messages=[{"role": "user", "content": "Hello!"}],
22
+ )
23
+ print(response.choices[0].message.content)
24
+
25
+ # List GPU instances
26
+ instances = client.instances.list()
27
+
28
+ # Create an instance
29
+ instance = client.instances.create(
30
+ name="training-run",
31
+ ssh_key_id="key_abc123",
32
+ gpu_type="A100",
33
+ )
34
+
35
+ # Check status
36
+ status = client.instances.get_status(instance.id)
37
+ print(status.status, status.ip)
38
+
39
+ # Check billing
40
+ balance = client.billing.get_balance()
41
+ print(f"Credits: ${balance.credits_balance}")
42
+
43
+ client.close()
44
+ ```
45
+
46
+ ## Async Usage
47
+
48
+ ```python
49
+ import asyncio
50
+ from runcrate import AsyncRuncrate
51
+
52
+ async def main():
53
+ async with AsyncRuncrate(api_key="rc_live_...") as client:
54
+ response = await client.models.chat_completion(
55
+ model="meta-llama/Meta-Llama-3.1-8B-Instruct",
56
+ messages=[{"role": "user", "content": "Hello!"}],
57
+ )
58
+ print(response.choices[0].message.content)
59
+
60
+ asyncio.run(main())
61
+ ```
62
+
63
+ ## Configuration
64
+
65
+ ```python
66
+ client = Runcrate(
67
+ api_key="rc_live_...", # or set RUNCRATE_API_KEY env var
68
+ base_url="https://runcrate.ai", # infra API (default)
69
+ inference_url="https://api.runcrate.ai", # model inference API (default)
70
+ timeout=30.0, # request timeout in seconds
71
+ max_retries=3, # retry on 429/5xx with exponential backoff
72
+ )
73
+ ```
74
+
75
+ ## Model Inference
76
+
77
+ The `client.models` resource connects to `api.runcrate.ai` for AI model inference. Same API key works for both infrastructure and inference.
78
+
79
+ ### Chat Completions
80
+
81
+ ```python
82
+ # Standard request
83
+ response = client.models.chat_completion(
84
+ model="meta-llama/Meta-Llama-3.1-8B-Instruct",
85
+ messages=[
86
+ {"role": "system", "content": "You are a helpful assistant."},
87
+ {"role": "user", "content": "Explain quantum computing in 3 sentences."},
88
+ ],
89
+ max_tokens=256,
90
+ temperature=0.7,
91
+ )
92
+ print(response.choices[0].message.content)
93
+ print(f"Tokens used: {response.usage.total_tokens}")
94
+
95
+ # Streaming
96
+ for chunk in client.models.chat_completion(
97
+ model="meta-llama/Meta-Llama-3.1-8B-Instruct",
98
+ messages=[{"role": "user", "content": "Write a poem about GPUs"}],
99
+ stream=True,
100
+ ):
101
+ delta = chunk.get("choices", [{}])[0].get("delta", {})
102
+ print(delta.get("content", ""), end="", flush=True)
103
+ ```
104
+
105
+ ### Image Generation
106
+
107
+ ```python
108
+ result = client.models.generate_image(
109
+ model="black-forest-labs/FLUX.1-schnell",
110
+ prompt="A futuristic city skyline at sunset",
111
+ width=1024,
112
+ height=1024,
113
+ )
114
+ # result.data[0].b64_json contains the base64-encoded image
115
+ ```
116
+
117
+ ### Video Generation
118
+
119
+ ```python
120
+ # Submit video job (async processing)
121
+ job = client.models.generate_video(
122
+ model="google/veo-3.0",
123
+ prompt="A drone flyover of a mountain landscape",
124
+ duration=8,
125
+ )
126
+ print(f"Job ID: {job.id}, Status: {job.status}")
127
+
128
+ # Poll until complete
129
+ import time
130
+ while True:
131
+ job = client.models.get_video_status(job.id)
132
+ print(f"Status: {job.status}")
133
+ if job.status in ("completed", "failed"):
134
+ break
135
+ time.sleep(5)
136
+
137
+ # Download the video
138
+ if job.status == "completed":
139
+ video_bytes = client.models.download_video(job.id)
140
+ with open("output.mp4", "wb") as f:
141
+ f.write(video_bytes)
142
+ ```
143
+
144
+ ### Text-to-Speech
145
+
146
+ ```python
147
+ audio_bytes = client.models.text_to_speech(
148
+ model="openai/tts-1",
149
+ input="Hello, welcome to Runcrate!",
150
+ voice="alloy",
151
+ response_format="mp3",
152
+ )
153
+ with open("speech.mp3", "wb") as f:
154
+ f.write(audio_bytes)
155
+ ```
156
+
157
+ ### Transcription (Speech-to-Text)
158
+
159
+ ```python
160
+ with open("audio.wav", "rb") as f:
161
+ result = client.models.transcribe(
162
+ model="openai/whisper-1",
163
+ file=f,
164
+ filename="audio.wav",
165
+ )
166
+ print(result.text)
167
+ print(f"Duration: {result.duration}s")
168
+ ```
169
+
170
+ ## Infrastructure Resources
171
+
172
+ ### Instances
173
+
174
+ ```python
175
+ client.instances.list(search="my-gpu")
176
+ client.instances.create(name="run", ssh_key_id="key", gpu_type="A100")
177
+ client.instances.get("instance-id")
178
+ client.instances.terminate("instance-id")
179
+ client.instances.get_status("instance-id")
180
+ client.instances.list_types(gpu_type="A100", region="us-east")
181
+ ```
182
+
183
+ ### Environments
184
+
185
+ ```python
186
+ client.environments.list()
187
+ client.environments.create(name="staging")
188
+ client.environments.get("env-id")
189
+ client.environments.update("env-id", name="production")
190
+ client.environments.delete("env-id")
191
+ ```
192
+
193
+ ### SSH Keys
194
+
195
+ ```python
196
+ client.ssh_keys.list()
197
+ client.ssh_keys.create(name="my-key", public_key="ssh-ed25519 AAAA...")
198
+ client.ssh_keys.delete("key-id")
199
+ ```
200
+
201
+ ### Storage
202
+
203
+ ```python
204
+ client.storage.list()
205
+ client.storage.get("volume-id")
206
+ ```
207
+
208
+ ### Billing
209
+
210
+ ```python
211
+ client.billing.get_balance()
212
+ client.billing.list_transactions(limit=10, offset=0)
213
+ client.billing.usage(from_date="2025-01-01", to_date="2025-01-31")
214
+ ```
215
+
216
+ ### Templates
217
+
218
+ ```python
219
+ client.templates.list(search="cuda", category="ml", page_size=10)
220
+ ```
221
+
222
+ ## Error Handling
223
+
224
+ ```python
225
+ from runcrate import Runcrate, NotFoundError, InsufficientCreditsError, RateLimitError
226
+
227
+ client = Runcrate(api_key="rc_live_...")
228
+
229
+ try:
230
+ instance = client.instances.get("nonexistent")
231
+ except NotFoundError as e:
232
+ print(f"Not found: {e.message}")
233
+ except InsufficientCreditsError as e:
234
+ print(f"Need more credits: {e.message}")
235
+ except RateLimitError as e:
236
+ print(f"Rate limited: {e.message}")
237
+ ```
238
+
239
+ ## Pagination
240
+
241
+ ```python
242
+ # Transactions support offset-based pagination
243
+ page = client.billing.list_transactions(limit=10, offset=0)
244
+ print(page.data) # list of Transaction objects
245
+ print(page.has_more) # True if more pages exist
246
+ print(page.total) # total count
247
+
248
+ # Templates support page-based pagination
249
+ templates = client.templates.list(page=1, page_size=25)
250
+ ```
251
+
252
+ ## Requirements
253
+
254
+ - Python >= 3.9
255
+ - httpx >= 0.25.0
256
+ - pydantic >= 2.0
@@ -0,0 +1,45 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "runcrate-sdk"
7
+ version = "0.1.0"
8
+ description = "Official Python SDK for the Runcrate API"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.9"
12
+ authors = [
13
+ { name = "Runcrate", email = "support@runcrate.ai" }
14
+ ]
15
+ dependencies = [
16
+ "httpx>=0.25.0,<1.0",
17
+ "pydantic>=2.0,<3.0",
18
+ ]
19
+
20
+ [project.urls]
21
+ Homepage = "https://runcrate.ai"
22
+ Repository = "https://github.com/aeonmindai/runcrate-py"
23
+ Documentation = "https://runcrate.ai/docs"
24
+
25
+ [project.optional-dependencies]
26
+ dev = [
27
+ "pytest>=7.0",
28
+ "pytest-asyncio>=0.21",
29
+ "respx>=0.21",
30
+ "ruff>=0.4",
31
+ "mypy>=1.0",
32
+ ]
33
+
34
+ [tool.hatch.build.targets.wheel]
35
+ packages = ["src/runcrate"]
36
+
37
+ [tool.ruff]
38
+ target-version = "py39"
39
+ line-length = 100
40
+
41
+ [tool.mypy]
42
+ strict = true
43
+
44
+ [tool.pytest.ini_options]
45
+ asyncio_mode = "auto"
@@ -0,0 +1,44 @@
1
+ """Runcrate Python SDK — Official client for the Runcrate API."""
2
+
3
+ from runcrate._client import AsyncRuncrate, Runcrate
4
+ from runcrate._exceptions import (
5
+ ApiError,
6
+ AuthenticationError,
7
+ BadRequestError,
8
+ ConflictError,
9
+ UnprocessableEntityError,
10
+ ConnectionError,
11
+ InsufficientCreditsError,
12
+ InternalServerError,
13
+ NotFoundError,
14
+ PermissionDeniedError,
15
+ RateLimitError,
16
+ RuncrateError,
17
+ TimeoutError,
18
+ )
19
+ from runcrate._pagination import PaginatedResponse
20
+
21
+ __version__ = "0.1.0"
22
+
23
+ __all__ = [
24
+ "AsyncRuncrate",
25
+ "Runcrate",
26
+ # Exceptions
27
+ "ApiError",
28
+ "AuthenticationError",
29
+ "BadRequestError",
30
+ "ConflictError",
31
+ "UnprocessableEntityError",
32
+ "ConnectionError",
33
+ "InsufficientCreditsError",
34
+ "InternalServerError",
35
+ "NotFoundError",
36
+ "PermissionDeniedError",
37
+ "RateLimitError",
38
+ "RuncrateError",
39
+ "TimeoutError",
40
+ # Pagination
41
+ "PaginatedResponse",
42
+ # Version
43
+ "__version__",
44
+ ]