splox 0.0.1__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.
- splox-0.0.1/.github/workflows/publish.yml +29 -0
- splox-0.0.1/.github/workflows/test.yml +33 -0
- splox-0.0.1/.gitignore +27 -0
- splox-0.0.1/LICENSE +21 -0
- splox-0.0.1/PKG-INFO +327 -0
- splox-0.0.1/README.md +294 -0
- splox-0.0.1/pyproject.toml +67 -0
- splox-0.0.1/src/splox/__init__.py +86 -0
- splox-0.0.1/src/splox/_client.py +128 -0
- splox-0.0.1/src/splox/_models.py +928 -0
- splox-0.0.1/src/splox/_resources.py +1440 -0
- splox-0.0.1/src/splox/_transport.py +220 -0
- splox-0.0.1/src/splox/exceptions.py +70 -0
- splox-0.0.1/src/splox/py.typed +1 -0
- splox-0.0.1/tests/__init__.py +0 -0
- splox-0.0.1/tests/integration_test.py +322 -0
- splox-0.0.1/tests/integration_test_memory.py +387 -0
- splox-0.0.1/tests/test_client.py +434 -0
- splox-0.0.1/tests/test_exceptions.py +43 -0
- splox-0.0.1/tests/test_models.py +217 -0
- splox-0.0.1/tests/test_sse.py +65 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
name: Python SDK — Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags: ["v*"]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
publish:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
environment: pypi
|
|
11
|
+
permissions:
|
|
12
|
+
id-token: write # Required for Trusted Publishers (OIDC)
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
|
|
16
|
+
- uses: actions/setup-python@v5
|
|
17
|
+
with:
|
|
18
|
+
python-version: "3.12"
|
|
19
|
+
|
|
20
|
+
- name: Install build tools
|
|
21
|
+
run: pip install build
|
|
22
|
+
|
|
23
|
+
- name: Build package
|
|
24
|
+
run: python -m build
|
|
25
|
+
|
|
26
|
+
- name: Publish to PyPI
|
|
27
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
28
|
+
with:
|
|
29
|
+
packages-dir: dist/
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
name: Python SDK — Test
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
lint:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
- uses: actions/setup-python@v5
|
|
15
|
+
with:
|
|
16
|
+
python-version: "3.12"
|
|
17
|
+
- run: pip install ruff mypy
|
|
18
|
+
- run: ruff check src/ tests/
|
|
19
|
+
- run: ruff format --check src/ tests/
|
|
20
|
+
- run: mypy src/
|
|
21
|
+
|
|
22
|
+
test:
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
strategy:
|
|
25
|
+
matrix:
|
|
26
|
+
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@v4
|
|
29
|
+
- uses: actions/setup-python@v5
|
|
30
|
+
with:
|
|
31
|
+
python-version: ${{ matrix.python-version }}
|
|
32
|
+
- run: pip install -e ".[dev]"
|
|
33
|
+
- run: pytest tests/ -x --ignore=tests/integration_test.py
|
splox-0.0.1/.gitignore
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Virtual environments
|
|
2
|
+
.venv/
|
|
3
|
+
venv/
|
|
4
|
+
env/
|
|
5
|
+
|
|
6
|
+
# Python
|
|
7
|
+
__pycache__/
|
|
8
|
+
*.py[cod]
|
|
9
|
+
*.egg-info/
|
|
10
|
+
dist/
|
|
11
|
+
build/
|
|
12
|
+
*.egg
|
|
13
|
+
|
|
14
|
+
# IDE
|
|
15
|
+
.idea/
|
|
16
|
+
.vscode/
|
|
17
|
+
*.swp
|
|
18
|
+
|
|
19
|
+
# OS
|
|
20
|
+
.DS_Store
|
|
21
|
+
Thumbs.db
|
|
22
|
+
|
|
23
|
+
# Test / coverage
|
|
24
|
+
.pytest_cache/
|
|
25
|
+
.coverage
|
|
26
|
+
htmlcov/
|
|
27
|
+
.mypy_cache/
|
splox-0.0.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Splox
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
splox-0.0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: splox
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: Official Python SDK for the Splox API — run workflows, manage chats, and monitor execution
|
|
5
|
+
Project-URL: Homepage, https://splox.io
|
|
6
|
+
Project-URL: Documentation, https://docs.splox.io
|
|
7
|
+
Project-URL: Repository, https://github.com/splox-ai/python-sdk
|
|
8
|
+
Project-URL: Issues, https://github.com/splox-ai/python-sdk/issues
|
|
9
|
+
Author-email: Splox <support@splox.io>
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: agent,ai,sdk,splox,workflow
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
23
|
+
Classifier: Typing :: Typed
|
|
24
|
+
Requires-Python: >=3.9
|
|
25
|
+
Requires-Dist: httpx>=0.25.0
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: mypy>=1.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest-asyncio>=0.21; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest-httpx>=0.30; extra == 'dev'
|
|
30
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: ruff>=0.4; extra == 'dev'
|
|
32
|
+
Description-Content-Type: text/markdown
|
|
33
|
+
|
|
34
|
+
# Splox Python SDK
|
|
35
|
+
|
|
36
|
+
Official Python SDK for the [Splox API](https://docs.splox.io) — run workflows, manage chats, and monitor execution programmatically.
|
|
37
|
+
|
|
38
|
+
## Installation
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
pip install splox
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Quick Start
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
from splox import SploxClient
|
|
48
|
+
|
|
49
|
+
client = SploxClient(api_key="your-api-key")
|
|
50
|
+
|
|
51
|
+
# Create a chat session
|
|
52
|
+
chat = client.chats.create(
|
|
53
|
+
name="My Session",
|
|
54
|
+
resource_id="your-workflow-id",
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
# Run a workflow
|
|
58
|
+
result = client.workflows.run(
|
|
59
|
+
workflow_version_id="your-version-id",
|
|
60
|
+
chat_id=chat.id,
|
|
61
|
+
start_node_id="your-start-node-id",
|
|
62
|
+
query="Summarize the latest sales report",
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
print(result.workflow_request_id)
|
|
66
|
+
|
|
67
|
+
# Get execution tree
|
|
68
|
+
tree = client.workflows.get_execution_tree(result.workflow_request_id)
|
|
69
|
+
for node in tree.execution_tree.nodes:
|
|
70
|
+
print(f"{node.node_label}: {node.status}")
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Async Support
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
import asyncio
|
|
77
|
+
from splox import AsyncSploxClient
|
|
78
|
+
|
|
79
|
+
async def main():
|
|
80
|
+
client = AsyncSploxClient(api_key="your-api-key")
|
|
81
|
+
|
|
82
|
+
chat = await client.chats.create(
|
|
83
|
+
name="Async Session",
|
|
84
|
+
resource_id="your-workflow-id",
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
result = await client.workflows.run(
|
|
88
|
+
workflow_version_id="your-version-id",
|
|
89
|
+
chat_id=chat.id,
|
|
90
|
+
start_node_id="your-start-node-id",
|
|
91
|
+
query="Hello from async!",
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
# Stream execution events via SSE
|
|
95
|
+
async for event in client.workflows.listen(result.workflow_request_id):
|
|
96
|
+
if event.node_execution:
|
|
97
|
+
print(f"Node {event.node_execution.status}: {event.node_execution.output_data}")
|
|
98
|
+
if event.workflow_request and event.workflow_request.status in ("completed", "failed"):
|
|
99
|
+
break
|
|
100
|
+
|
|
101
|
+
await client.close()
|
|
102
|
+
|
|
103
|
+
asyncio.run(main())
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Streaming (SSE)
|
|
107
|
+
|
|
108
|
+
### Listen to workflow execution
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
# Sync
|
|
112
|
+
for event in client.workflows.listen(workflow_request_id):
|
|
113
|
+
print(event)
|
|
114
|
+
|
|
115
|
+
# Async
|
|
116
|
+
async for event in async_client.workflows.listen(workflow_request_id):
|
|
117
|
+
print(event)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Listen to chat messages
|
|
121
|
+
|
|
122
|
+
Stream real-time chat events including text deltas, tool calls, and more:
|
|
123
|
+
|
|
124
|
+
```python
|
|
125
|
+
# Async example — collect streamed response
|
|
126
|
+
async for event in client.chats.listen(chat_id):
|
|
127
|
+
if event.event_type == "text_delta":
|
|
128
|
+
print(event.text_delta, end="", flush=True)
|
|
129
|
+
elif event.event_type == "tool_call_start":
|
|
130
|
+
print(f"\\nCalling tool: {event.tool_name}")
|
|
131
|
+
elif event.event_type == "done":
|
|
132
|
+
print("\\nIteration complete")
|
|
133
|
+
|
|
134
|
+
# Stop when workflow completes
|
|
135
|
+
if event.workflow_request and event.workflow_request.status == "completed":
|
|
136
|
+
break
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
**Event types:**
|
|
140
|
+
|
|
141
|
+
| Type | Fields | Description |
|
|
142
|
+
|------|--------|-------------|
|
|
143
|
+
| `text_delta` | `text_delta` | Streamed text chunk |
|
|
144
|
+
| `reasoning_delta` | `reasoning_delta`, `reasoning_type` | Thinking content |
|
|
145
|
+
| `tool_call_start` | `tool_call_id`, `tool_name` | Tool call initiated |
|
|
146
|
+
| `tool_call_delta` | `tool_call_id`, `tool_args_delta` | Tool arguments delta |
|
|
147
|
+
| `tool_start` | `tool_name`, `tool_call_id` | Tool execution started |
|
|
148
|
+
| `tool_complete` | `tool_name`, `tool_call_id`, `tool_result` | Tool finished |
|
|
149
|
+
| `tool_error` | `tool_name`, `tool_call_id`, `error` | Tool failed |
|
|
150
|
+
| `done` | `iteration`, `run_id` | Iteration complete |
|
|
151
|
+
| `error` | `error` | Error occurred |
|
|
152
|
+
|
|
153
|
+
## Run & Wait
|
|
154
|
+
|
|
155
|
+
Convenience method that runs a workflow and waits for completion:
|
|
156
|
+
|
|
157
|
+
```python
|
|
158
|
+
execution = client.workflows.run_and_wait(
|
|
159
|
+
workflow_version_id="your-version-id",
|
|
160
|
+
chat_id=chat.id,
|
|
161
|
+
start_node_id="your-start-node-id",
|
|
162
|
+
query="Process this request",
|
|
163
|
+
timeout=300, # 5 minutes
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
print(execution.status) # "completed"
|
|
167
|
+
for node in execution.nodes:
|
|
168
|
+
print(f"{node.node_label}: {node.output_data}")
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Memory
|
|
172
|
+
|
|
173
|
+
Inspect and manage agent context memory — list instances, read messages, summarize, trim, clear, or export.
|
|
174
|
+
|
|
175
|
+
```python
|
|
176
|
+
# List memory instances (paginated)
|
|
177
|
+
result = client.memory.list("workflow-version-id", limit=20)
|
|
178
|
+
for inst in result.chats:
|
|
179
|
+
print(f"{inst.memory_node_label}: {inst.message_count} messages")
|
|
180
|
+
|
|
181
|
+
# Paginate
|
|
182
|
+
if result.has_more:
|
|
183
|
+
more = client.memory.list("workflow-version-id", cursor=result.next_cursor)
|
|
184
|
+
|
|
185
|
+
# Get messages for an agent node
|
|
186
|
+
messages = client.memory.get("agent-node-id", chat_id="session-id", limit=20)
|
|
187
|
+
for msg in messages.messages:
|
|
188
|
+
print(f"[{msg.role}] {msg.content}")
|
|
189
|
+
|
|
190
|
+
# Summarize — compress older messages into an LLM-generated summary
|
|
191
|
+
result = client.memory.summarize(
|
|
192
|
+
"agent-node-id",
|
|
193
|
+
context_memory_id="session-id",
|
|
194
|
+
workflow_version_id="version-id",
|
|
195
|
+
keep_last_n=3,
|
|
196
|
+
)
|
|
197
|
+
print(f"Summary: {result.summary}")
|
|
198
|
+
|
|
199
|
+
# Trim — drop oldest messages to stay under a limit
|
|
200
|
+
client.memory.trim(
|
|
201
|
+
"agent-node-id",
|
|
202
|
+
context_memory_id="session-id",
|
|
203
|
+
workflow_version_id="version-id",
|
|
204
|
+
max_messages=20,
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
# Export all messages without modifying them
|
|
208
|
+
exported = client.memory.export(
|
|
209
|
+
"agent-node-id",
|
|
210
|
+
context_memory_id="session-id",
|
|
211
|
+
workflow_version_id="version-id",
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
# Clear all messages
|
|
215
|
+
client.memory.clear(
|
|
216
|
+
"agent-node-id",
|
|
217
|
+
context_memory_id="session-id",
|
|
218
|
+
workflow_version_id="version-id",
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
# Delete a specific memory instance
|
|
222
|
+
client.memory.delete(
|
|
223
|
+
"session-id",
|
|
224
|
+
memory_node_id="agent-node-id",
|
|
225
|
+
workflow_version_id="version-id",
|
|
226
|
+
)
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
## Webhooks
|
|
230
|
+
|
|
231
|
+
```python
|
|
232
|
+
# Trigger a workflow via webhook (no auth required)
|
|
233
|
+
from splox import SploxClient
|
|
234
|
+
|
|
235
|
+
client = SploxClient() # No API key needed for webhooks
|
|
236
|
+
|
|
237
|
+
result = client.events.send(
|
|
238
|
+
webhook_id="your-webhook-id",
|
|
239
|
+
payload={"order_id": "12345", "status": "paid"},
|
|
240
|
+
)
|
|
241
|
+
print(result.event_id)
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## Error Handling
|
|
245
|
+
|
|
246
|
+
```python
|
|
247
|
+
from splox import SploxClient
|
|
248
|
+
from splox.exceptions import (
|
|
249
|
+
SploxAPIError,
|
|
250
|
+
SploxAuthError,
|
|
251
|
+
SploxRateLimitError,
|
|
252
|
+
SploxNotFoundError,
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
client = SploxClient(api_key="your-api-key")
|
|
256
|
+
|
|
257
|
+
try:
|
|
258
|
+
result = client.workflows.run(...)
|
|
259
|
+
except SploxAuthError:
|
|
260
|
+
print("Invalid or expired API token")
|
|
261
|
+
except SploxRateLimitError as e:
|
|
262
|
+
print(f"Rate limited. Retry after: {e.retry_after}")
|
|
263
|
+
except SploxNotFoundError:
|
|
264
|
+
print("Resource not found")
|
|
265
|
+
except SploxAPIError as e:
|
|
266
|
+
print(f"API error {e.status_code}: {e.message}")
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
## Custom Base URL
|
|
270
|
+
|
|
271
|
+
```python
|
|
272
|
+
client = SploxClient(
|
|
273
|
+
api_key="your-api-key",
|
|
274
|
+
base_url="https://your-self-hosted-instance.com/api/v1",
|
|
275
|
+
)
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
## API Reference
|
|
279
|
+
|
|
280
|
+
### `SploxClient` / `AsyncSploxClient`
|
|
281
|
+
|
|
282
|
+
| Parameter | Type | Default | Description |
|
|
283
|
+
|-----------|------|---------|-------------|
|
|
284
|
+
| `api_key` | `str \| None` | `SPLOX_API_KEY` env | API authentication token |
|
|
285
|
+
| `base_url` | `str` | `https://app.splox.io/api/v1` | API base URL |
|
|
286
|
+
| `timeout` | `float` | `30.0` | Request timeout in seconds |
|
|
287
|
+
|
|
288
|
+
### `client.workflows`
|
|
289
|
+
|
|
290
|
+
| Method | Description |
|
|
291
|
+
|--------|-------------|
|
|
292
|
+
| `run(...)` | Trigger a workflow execution |
|
|
293
|
+
| `listen(id)` | Stream execution events (SSE) |
|
|
294
|
+
| `get_execution_tree(id)` | Get complete execution hierarchy |
|
|
295
|
+
| `get_history(id, ...)` | Get paginated execution history |
|
|
296
|
+
| `stop(id)` | Stop a running workflow |
|
|
297
|
+
| `run_and_wait(...)` | Run and wait for completion |
|
|
298
|
+
|
|
299
|
+
### `client.chats`
|
|
300
|
+
|
|
301
|
+
| Method | Description |
|
|
302
|
+
|--------|-------------|
|
|
303
|
+
| `create(...)` | Create a new chat session |
|
|
304
|
+
| `get(id)` | Get a chat by ID |
|
|
305
|
+
| `listen(id)` | Stream chat events (SSE) |
|
|
306
|
+
|
|
307
|
+
### `client.events`
|
|
308
|
+
|
|
309
|
+
| Method | Description |
|
|
310
|
+
|--------|-------------|
|
|
311
|
+
| `send(webhook_id, ...)` | Send event via webhook |
|
|
312
|
+
|
|
313
|
+
### `client.memory`
|
|
314
|
+
|
|
315
|
+
| Method | Description |
|
|
316
|
+
|--------|-------------|
|
|
317
|
+
| `list(version_id, ...)` | List memory instances (paginated) |
|
|
318
|
+
| `get(node_id, ...)` | Get paginated messages |
|
|
319
|
+
| `summarize(node_id, ...)` | Summarize older messages with LLM |
|
|
320
|
+
| `trim(node_id, ...)` | Drop oldest messages |
|
|
321
|
+
| `clear(node_id, ...)` | Remove all messages |
|
|
322
|
+
| `export(node_id, ...)` | Export all messages |
|
|
323
|
+
| `delete(memory_id, ...)` | Delete a memory instance |
|
|
324
|
+
|
|
325
|
+
## License
|
|
326
|
+
|
|
327
|
+
MIT
|