rocketride 1.0.2__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.
- rocketride-1.0.2/LICENSE +21 -0
- rocketride-1.0.2/PKG-INFO +562 -0
- rocketride-1.0.2/README.md +518 -0
- rocketride-1.0.2/pyproject.toml +79 -0
- rocketride-1.0.2/setup.cfg +4 -0
- rocketride-1.0.2/src/rocketride/__init__.py +158 -0
- rocketride-1.0.2/src/rocketride/cli/__init__.py +57 -0
- rocketride-1.0.2/src/rocketride/cli/commands/__init__.py +55 -0
- rocketride-1.0.2/src/rocketride/cli/commands/base.py +184 -0
- rocketride-1.0.2/src/rocketride/cli/commands/events.py +389 -0
- rocketride-1.0.2/src/rocketride/cli/commands/list.py +160 -0
- rocketride-1.0.2/src/rocketride/cli/commands/start.py +258 -0
- rocketride-1.0.2/src/rocketride/cli/commands/status.py +249 -0
- rocketride-1.0.2/src/rocketride/cli/commands/stop.py +225 -0
- rocketride-1.0.2/src/rocketride/cli/commands/store.py +453 -0
- rocketride-1.0.2/src/rocketride/cli/commands/upload.py +335 -0
- rocketride-1.0.2/src/rocketride/cli/main.py +842 -0
- rocketride-1.0.2/src/rocketride/cli/monitors/__init__.py +53 -0
- rocketride-1.0.2/src/rocketride/cli/monitors/base.py +306 -0
- rocketride-1.0.2/src/rocketride/cli/monitors/events.py +362 -0
- rocketride-1.0.2/src/rocketride/cli/monitors/generic.py +105 -0
- rocketride-1.0.2/src/rocketride/cli/monitors/status.py +411 -0
- rocketride-1.0.2/src/rocketride/cli/monitors/upload.py +689 -0
- rocketride-1.0.2/src/rocketride/cli/ui/__init__.py +91 -0
- rocketride-1.0.2/src/rocketride/cli/ui/box.py +228 -0
- rocketride-1.0.2/src/rocketride/cli/ui/colors.py +72 -0
- rocketride-1.0.2/src/rocketride/cli/ui/display.py +151 -0
- rocketride-1.0.2/src/rocketride/cli/utils/__init__.py +50 -0
- rocketride-1.0.2/src/rocketride/cli/utils/config.py +120 -0
- rocketride-1.0.2/src/rocketride/cli/utils/file_utils.py +173 -0
- rocketride-1.0.2/src/rocketride/cli/utils/formatters.py +196 -0
- rocketride-1.0.2/src/rocketride/client.py +224 -0
- rocketride-1.0.2/src/rocketride/core/__init__.py +94 -0
- rocketride-1.0.2/src/rocketride/core/constants.py +84 -0
- rocketride-1.0.2/src/rocketride/core/dap_base.py +775 -0
- rocketride-1.0.2/src/rocketride/core/dap_client.py +348 -0
- rocketride-1.0.2/src/rocketride/core/exceptions.py +244 -0
- rocketride-1.0.2/src/rocketride/core/transport.py +315 -0
- rocketride-1.0.2/src/rocketride/core/transport_websocket.py +541 -0
- rocketride-1.0.2/src/rocketride/mixins/chat.py +196 -0
- rocketride-1.0.2/src/rocketride/mixins/connection.py +422 -0
- rocketride-1.0.2/src/rocketride/mixins/data.py +639 -0
- rocketride-1.0.2/src/rocketride/mixins/events.py +352 -0
- rocketride-1.0.2/src/rocketride/mixins/execution.py +427 -0
- rocketride-1.0.2/src/rocketride/mixins/ping.py +157 -0
- rocketride-1.0.2/src/rocketride/mixins/services.py +167 -0
- rocketride-1.0.2/src/rocketride/mixins/store.py +888 -0
- rocketride-1.0.2/src/rocketride/py.typed +2 -0
- rocketride-1.0.2/src/rocketride/rocketride.py +29 -0
- rocketride-1.0.2/src/rocketride/schema/__init__.py +84 -0
- rocketride-1.0.2/src/rocketride/schema/doc.py +128 -0
- rocketride-1.0.2/src/rocketride/schema/doc_filter.py +119 -0
- rocketride-1.0.2/src/rocketride/schema/doc_group.py +97 -0
- rocketride-1.0.2/src/rocketride/schema/doc_metadata.py +154 -0
- rocketride-1.0.2/src/rocketride/schema/question.py +661 -0
- rocketride-1.0.2/src/rocketride/types/__init__.py +125 -0
- rocketride-1.0.2/src/rocketride/types/client.py +174 -0
- rocketride-1.0.2/src/rocketride/types/data.py +172 -0
- rocketride-1.0.2/src/rocketride/types/events.py +307 -0
- rocketride-1.0.2/src/rocketride/types/pipeline.py +133 -0
- rocketride-1.0.2/src/rocketride/types/task.py +387 -0
- rocketride-1.0.2/src/rocketride.egg-info/PKG-INFO +562 -0
- rocketride-1.0.2/src/rocketride.egg-info/SOURCES.txt +65 -0
- rocketride-1.0.2/src/rocketride.egg-info/dependency_links.txt +1 -0
- rocketride-1.0.2/src/rocketride.egg-info/entry_points.txt +2 -0
- rocketride-1.0.2/src/rocketride.egg-info/requires.txt +16 -0
- rocketride-1.0.2/src/rocketride.egg-info/top_level.txt +1 -0
rocketride-1.0.2/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Aparavi Software AG
|
|
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.
|
|
@@ -0,0 +1,562 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rocketride
|
|
3
|
+
Version: 1.0.2
|
|
4
|
+
Summary: RocketRide Pipeline Python Client SDK
|
|
5
|
+
Author-email: "RocketRide, Inc." <dev@rocketride.ai>
|
|
6
|
+
Maintainer-email: "RocketRide, Inc." <dev@rocketride.ai>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Project-URL: Homepage, https://github.com/rocketride-ai/rocketride-server
|
|
9
|
+
Project-URL: Documentation, https://github.com/rocketride-ai/rocketride-server#readme
|
|
10
|
+
Project-URL: Repository, https://github.com/rocketride-ai/rocketride-server.git
|
|
11
|
+
Project-URL: Bug Reports, https://github.com/rocketride-ai/rocketride-server/issues
|
|
12
|
+
Keywords: rocketride,pipeline,dap,debug-adapter-protocol,data-processing,client-sdk,async,websocket
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
16
|
+
Classifier: Topic :: System :: Networking
|
|
17
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
24
|
+
Classifier: Operating System :: OS Independent
|
|
25
|
+
Classifier: Typing :: Typed
|
|
26
|
+
Requires-Python: >=3.8
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
License-File: LICENSE
|
|
29
|
+
Requires-Dist: websockets>=11.0.0
|
|
30
|
+
Requires-Dist: aiofiles>=23.0.0
|
|
31
|
+
Requires-Dist: pydantic>=2.0.0
|
|
32
|
+
Provides-Extra: dev
|
|
33
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
34
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
35
|
+
Requires-Dist: ruff>=0.8.0; extra == "dev"
|
|
36
|
+
Requires-Dist: build>=0.10.0; extra == "dev"
|
|
37
|
+
Requires-Dist: twine>=4.0.0; extra == "dev"
|
|
38
|
+
Provides-Extra: test
|
|
39
|
+
Requires-Dist: pytest>=7.0.0; extra == "test"
|
|
40
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "test"
|
|
41
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "test"
|
|
42
|
+
Requires-Dist: python-dotenv>=1.0.0; extra == "test"
|
|
43
|
+
Dynamic: license-file
|
|
44
|
+
|
|
45
|
+
# rocketride
|
|
46
|
+
|
|
47
|
+
RocketRide Python Client -- Python SDK for the RocketRide Engine. Complete API reference below.
|
|
48
|
+
|
|
49
|
+
## Installation
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
pip install rocketride
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Import from the package (e.g. `from rocketride import RocketRideClient`).
|
|
56
|
+
|
|
57
|
+
## Quick Start
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
import asyncio
|
|
61
|
+
from rocketride import RocketRideClient
|
|
62
|
+
|
|
63
|
+
async def main():
|
|
64
|
+
async with RocketRideClient(uri="https://cloud.rocketride.ai", auth="my-key") as client:
|
|
65
|
+
result = await client.use(filepath="pipeline.json")
|
|
66
|
+
token = result["token"]
|
|
67
|
+
out = await client.send(token, "Hello, pipeline!", objinfo={"name": "input.txt"}, mimetype="text/plain")
|
|
68
|
+
print(out)
|
|
69
|
+
await client.terminate(token)
|
|
70
|
+
|
|
71
|
+
asyncio.run(main())
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Features
|
|
75
|
+
|
|
76
|
+
- **Pipeline execution** -- Start with `use()`, send data via `send()`, `send_files()`, or `pipe()`
|
|
77
|
+
- **Chat** -- Conversational AI via `chat()` and `Question`
|
|
78
|
+
- **Event streaming** -- Real-time events via `on_event` and `set_events()`
|
|
79
|
+
- **File upload** -- `send_files()` with progress; streaming with `pipe()`
|
|
80
|
+
- **Connection lifecycle** -- Optional persist mode, reconnection, and callbacks (`on_connected`, `on_disconnected`, `on_connect_error`)
|
|
81
|
+
- **Async context manager** -- `async with RocketRideClient(...) as client:` for automatic cleanup
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## RocketRideClient
|
|
86
|
+
|
|
87
|
+
### Constructor
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
RocketRideClient(
|
|
91
|
+
uri: str = "",
|
|
92
|
+
auth: str = "",
|
|
93
|
+
*,
|
|
94
|
+
env: dict = None,
|
|
95
|
+
module: str = None,
|
|
96
|
+
request_timeout: float = None,
|
|
97
|
+
max_retry_time: float = None,
|
|
98
|
+
persist: bool = False,
|
|
99
|
+
on_event = None,
|
|
100
|
+
on_connected = None,
|
|
101
|
+
on_disconnected = None,
|
|
102
|
+
on_connect_error = None,
|
|
103
|
+
on_protocol_message = None,
|
|
104
|
+
on_debug_message = None,
|
|
105
|
+
)
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**Why the options matter:** `uri` and `auth` tell the client *where* and *how* to authenticate. `persist` and `max_retry_time` control what happens when the connection fails or the server is not ready yet: with `persist=True` the client retries with exponential backoff and calls `on_connect_error` on each failure, so you can show "Still connecting..." or "Connection failed" without implementing retry logic yourself. Use `on_disconnected` only for "we were connected and then dropped"; use `on_connect_error` for "failed to connect" or "gave up after max retry time."
|
|
109
|
+
|
|
110
|
+
| Argument | Type | Required | Description |
|
|
111
|
+
| --------------------- | ------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
112
|
+
| `uri` | `str` | Yes* | Server URI. *Can be empty if `ROCKETRIDE_URI` is set in env/`.env`. |
|
|
113
|
+
| `auth` | `str` | Yes* | API key. *Can be empty if `ROCKETRIDE_APIKEY` is set. |
|
|
114
|
+
| `env` | `dict` | No | Override env; if omitted, `.env` is loaded. Use when passing config in code instead of env files. |
|
|
115
|
+
| `module` | `str` | No | Client name for logging. |
|
|
116
|
+
| `request_timeout` | `float` | No | Default timeout in ms for requests. Prevents a single DAP call from hanging. |
|
|
117
|
+
| `max_retry_time` | `float` | No | Max time in ms to keep retrying connection. Use (e.g. 300000) so the app can show "gave up" after a bounded time. |
|
|
118
|
+
| `persist` | `bool` | No | Enable automatic reconnection. Default: `False`. Set `True` for long-lived scripts or UIs. |
|
|
119
|
+
| `on_event` | async callable | No | Called with each server event dict. Use for progress or status updates. |
|
|
120
|
+
| `on_connected` | async callable | No | Called when connection is established. |
|
|
121
|
+
| `on_disconnected` | async callable | No | Called when connection is lost **only if** connected first; args: `reason`, `has_error`. Do not call `disconnect()` here if you want auto-reconnect. |
|
|
122
|
+
| `on_connect_error` | callable `(message: str)` | No | Called on each failed connection attempt. On auth failure the client stops retrying. |
|
|
123
|
+
| `on_protocol_message` | callable `(message: str)` | No | Optional; for logging raw DAP messages. Helpful when debugging protocol issues. |
|
|
124
|
+
| `on_debug_message` | callable `(message: str)` | No | Optional; for debug output. |
|
|
125
|
+
|
|
126
|
+
Raises `ValueError` if both `uri` and `ROCKETRIDE_URI` are empty or if `auth` is missing and not in env.
|
|
127
|
+
|
|
128
|
+
**Example -- client with persist and callbacks:**
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
client = RocketRideClient(
|
|
132
|
+
uri="https://cloud.rocketride.ai",
|
|
133
|
+
auth="my-key",
|
|
134
|
+
persist=True,
|
|
135
|
+
max_retry_time=300000,
|
|
136
|
+
on_connect_error=lambda msg: print("Connect error:", msg),
|
|
137
|
+
on_event=handle_event,
|
|
138
|
+
)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Context manager
|
|
142
|
+
|
|
143
|
+
| Method | Signature | Returns | Description |
|
|
144
|
+
| ------------ | ------------------------------------------------------ | ------- | ------------------------------------ |
|
|
145
|
+
| `__aenter__` | `async def __aenter__(self)` | `self` | Enters context; calls `connect()`. |
|
|
146
|
+
| `__aexit__` | `async def __aexit__(self, exc_type, exc_val, exc_tb)` | -- | Exits context; calls `disconnect()`. |
|
|
147
|
+
|
|
148
|
+
**How to use:** Prefer `async with RocketRideClient(...) as client:` so the connection is always closed when you leave the block, even on exception. No need to call `disconnect()` manually.
|
|
149
|
+
|
|
150
|
+
**Example:**
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
async with RocketRideClient(uri="wss://cloud.rocketride.ai", auth=os.environ["ROCKETRIDE_APIKEY"]) as client:
|
|
154
|
+
result = await client.use(filepath="pipeline.json")
|
|
155
|
+
token = result["token"]
|
|
156
|
+
await client.send(token, "Hello, pipeline!")
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Connection
|
|
160
|
+
|
|
161
|
+
| Method | Signature | Returns | Description |
|
|
162
|
+
| ----------------------- | --------------------------------------------------------------------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
163
|
+
| `connect` | `async def connect(self, uri: str = None, auth: str = None, timeout: float = None) -> None` | -- | Opens the WebSocket and performs DAP auth. Optional `uri`/`auth` override the constructor values for this connection attempt. Optional `timeout` (ms) bounds the connect + auth handshake (non-persist only). In **persist** mode, on failure the client calls `on_connect_error` and retries; on **auth** failure it does not retry. |
|
|
164
|
+
| `disconnect` | `async def disconnect(self) -> None` | -- | Closes the connection and cancels reconnection. Call when the user disconnects or the script is done. |
|
|
165
|
+
| `is_connected` | `def is_connected(self) -> bool` | `bool` | Whether the client is connected. Check before calling `use()` or `send()` if needed. |
|
|
166
|
+
| `set_connection_params` | `async def set_connection_params(self, uri: str = None, auth: str = None) -> None` | -- | Updates server URI and/or auth at runtime. If currently connected, disconnects and reconnects with the new params (in persist mode, reconnection is scheduled; otherwise reconnects once). Use when the user changes server or credentials without creating a new client. |
|
|
167
|
+
| `get_connection_info` | `def get_connection_info(self) -> dict` | `dict` | Current connection state and URI. Returns `{ 'connected': bool, 'transport': str, 'uri': str }`. Useful for debugging or displaying "Connected to ..." in the UI. |
|
|
168
|
+
| `get_apikey` | `def get_apikey(self) -> Optional[str]` | `str \| None` | The API key in use. For debugging only; avoid logging in production. |
|
|
169
|
+
|
|
170
|
+
### Low-level DAP
|
|
171
|
+
|
|
172
|
+
| Method | Signature | Returns | Description |
|
|
173
|
+
| --------------- | --------------------------------------------------------------------------------------------------------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
174
|
+
| `build_request` | `def build_request(self, command: str, *, token: str = None, arguments: dict = None, data: bytes \| str = None) -> dict` | `dict` | Builds a DAP request message. Use for custom commands not covered by `use()`, `send()`, etc. |
|
|
175
|
+
| `request` | `async def request(self, request: dict, timeout: float = None) -> dict` | `dict` | Sends the request and returns the response. `timeout` in ms overrides the default for this call. Use `did_fail(response)` before trusting `body`. |
|
|
176
|
+
| `dap_request` | `async def dap_request(self, command: str, arguments: dict = None, token: str = None, timeout: float = None) -> dict` | `dict` | Shorthand: builds a request and sends it in one call. Equivalent to `build_request()` + `request()`. |
|
|
177
|
+
| `did_fail` | `def did_fail(self, request: dict) -> bool` | `bool` | Returns `True` when the response indicates failure (`success === False`). |
|
|
178
|
+
|
|
179
|
+
**Example:**
|
|
180
|
+
|
|
181
|
+
```python
|
|
182
|
+
# Two-step (build then request)
|
|
183
|
+
req = client.build_request("rrext_monitor", token=token, arguments={"types": ["apaevt_status_upload"]})
|
|
184
|
+
res = await client.request(req, timeout=5000)
|
|
185
|
+
|
|
186
|
+
# One-step with dap_request
|
|
187
|
+
res = await client.dap_request("rrext_services", {}, timeout=5000)
|
|
188
|
+
|
|
189
|
+
if client.did_fail(res):
|
|
190
|
+
raise RuntimeError(res.get("message", "Request failed"))
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Pipeline execution
|
|
194
|
+
|
|
195
|
+
| Method | Signature | Returns | Description |
|
|
196
|
+
| ----------------- | --------- | ------- | ----------- |
|
|
197
|
+
| `use` | `async def use(self, *, token: str = None, filepath: str = None, pipeline: dict = None, source: str = None, threads: int = None, use_existing: bool = None, args: list = None, ttl: int = None) -> dict` | `dict` | Starts a pipeline. Requires `filepath` or `pipeline`. The client substitutes `${ROCKETRIDE_*}` from its env. Returns a dict with at least `'token'`; use that token for all data and control operations. |
|
|
198
|
+
| `terminate` | `async def terminate(self, token: str) -> None` | -- | Stops the pipeline and frees server resources. |
|
|
199
|
+
| `get_task_status` | `async def get_task_status(self, token: str) -> dict` | `dict` | Returns current task status (e.g. completed count, total, state). Poll until `completed` or use for progress display. |
|
|
200
|
+
|
|
201
|
+
**Why a token:** The server runs each pipeline as a separate task. The token identifies that task so `send()`, `send_files()`, `pipe()`, `chat()`, and `get_task_status()` target the correct pipeline.
|
|
202
|
+
|
|
203
|
+
### Data
|
|
204
|
+
|
|
205
|
+
| Method | Signature | Returns | Description |
|
|
206
|
+
| ------------ | --------- | ------- | ----------- |
|
|
207
|
+
| `pipe` | `async def pipe(self, token: str, objinfo: dict = None, mime_type: str = None, provider: str = None) -> DataPipe` | `DataPipe` | Creates a **streaming** pipe: open, then one or more write, then close. Use for large or chunked data. Default MIME: `'application/octet-stream'`. |
|
|
208
|
+
| `send` | `async def send(self, token: str, data: str \| bytes, objinfo: dict = None, mimetype: str = None) -> PIPELINE_RESULT` | `PIPELINE_RESULT` | Sends data in **one shot** (open pipe, write once, close). Use when you have the full payload in memory. |
|
|
209
|
+
| `send_files` | `async def send_files(self, files: List[str \| Tuple[str, dict] \| Tuple[str, dict, str]], token: str) -> List[UPLOAD_RESULT]` | `List[UPLOAD_RESULT]` | Uploads files. Each item: path `str`, or `(path, objinfo)`, or `(path, objinfo, mimetype)`. Progress via `on_event` as `apaevt_status_upload`. |
|
|
210
|
+
|
|
211
|
+
**When to use pipe vs send:** Use `send()` for a single string or bytes. Use `pipe()` when you read a file in chunks, or when data arrives incrementally.
|
|
212
|
+
|
|
213
|
+
**Example -- send a string:**
|
|
214
|
+
|
|
215
|
+
```python
|
|
216
|
+
result = await client.send(token, "Hello, pipeline!", objinfo={"name": "greeting.txt"}, mimetype="text/plain")
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
**Example -- stream with a pipe (context manager):**
|
|
220
|
+
|
|
221
|
+
```python
|
|
222
|
+
pipe = await client.pipe(token, mime_type="application/json")
|
|
223
|
+
async with pipe:
|
|
224
|
+
await pipe.write(b'{"key": "value1"}')
|
|
225
|
+
await pipe.write(b'{"key": "value2"}')
|
|
226
|
+
result = await pipe.close() # result available after context
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Events
|
|
230
|
+
|
|
231
|
+
| Method | Signature | Returns | Description |
|
|
232
|
+
| ------------ | --------- | ------- | ----------- |
|
|
233
|
+
| `set_events` | `async def set_events(self, token: str, event_types: List[str]) -> None` | -- | Subscribes this task to the given event types. After this, those events are delivered to `on_event`. Call after `use()` when you need upload or processing progress. |
|
|
234
|
+
|
|
235
|
+
### Services, validation, and ping
|
|
236
|
+
|
|
237
|
+
| Method | Signature | Returns | Description |
|
|
238
|
+
| -------------- | --------- | ------- | ----------- |
|
|
239
|
+
| `get_services` | `async def get_services(self) -> dict` | `dict` | Returns all service definitions. Use to discover what the server supports. |
|
|
240
|
+
| `get_service` | `async def get_service(self, service: str) -> Optional[dict]` | `dict \| None` | Returns one service by name; `None` if not found or on error. |
|
|
241
|
+
| `validate` | `async def validate(self, pipeline: PipelineConfig, *, source: str = None) -> dict` | `dict` | Validates a pipeline configuration without starting it. Returns validation results (e.g. errors, warnings). Use to check pipeline correctness before `use()`. |
|
|
242
|
+
| `ping` | `async def ping(self, token: str = None) -> None` | -- | Liveness check; raises on failure. |
|
|
243
|
+
|
|
244
|
+
### Chat
|
|
245
|
+
|
|
246
|
+
| Method | Signature | Returns | Description |
|
|
247
|
+
| ------ | --------- | ------- | ----------- |
|
|
248
|
+
| `chat` | `async def chat(self, *, token: str, question: Question) -> PIPELINE_RESULT` | `PIPELINE_RESULT` | Sends the `Question` to the AI for the given token and returns the pipeline result. The answer is in the result body; use the schema's answer helpers if you need to parse JSON from the AI text. |
|
|
249
|
+
|
|
250
|
+
**How it works:** The client opens a pipe with the question MIME type, writes the serialized `Question`, closes the pipe, and returns the server result. The pipeline must support the chat provider.
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## DataPipe
|
|
255
|
+
|
|
256
|
+
Returned by `await client.pipe(...)`. One streaming upload: **open** -> **write** (one or more) -> **close**. You can also use it as an async context manager: entering calls `open()`, exiting calls `close()`.
|
|
257
|
+
|
|
258
|
+
| Property | Type | Description |
|
|
259
|
+
| ----------- | -------------- | ---------------------------------------- |
|
|
260
|
+
| `is_opened` | `bool` | Whether the pipe is open. |
|
|
261
|
+
| `pipe_id` | `int \| None` | Server-assigned pipe ID after `open()`. |
|
|
262
|
+
|
|
263
|
+
| Method | Signature | Returns | Description |
|
|
264
|
+
| ------------ | ------------------------------------------------------ | ----------------- | ------------------------------------------------- |
|
|
265
|
+
| `open` | `async def open(self) -> DataPipe` | `self` | Opens the pipe; required before `write()`. |
|
|
266
|
+
| `write` | `async def write(self, buffer: bytes) -> None` | -- | Writes a chunk. Pipe must be open. |
|
|
267
|
+
| `close` | `async def close(self) -> PIPELINE_RESULT` | `PIPELINE_RESULT` | Closes the pipe and returns the processing result. |
|
|
268
|
+
| `__aenter__` | `async def __aenter__(self)` | `self` | Enters context; calls `open()`. |
|
|
269
|
+
| `__aexit__` | `async def __aexit__(self, exc_type, exc_val, exc_tb)` | -- | Exits context; calls `close()`. |
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
## Question
|
|
274
|
+
|
|
275
|
+
From `rocketride.schema`. Build a question for `client.chat(token=..., question=question)`. Add instructions, examples, context, history, and documents to steer the AI.
|
|
276
|
+
|
|
277
|
+
### Constructor
|
|
278
|
+
|
|
279
|
+
```python
|
|
280
|
+
Question(
|
|
281
|
+
type: QuestionType = QuestionType.QUESTION,
|
|
282
|
+
filter: DocFilter = None,
|
|
283
|
+
expectJson: bool = False,
|
|
284
|
+
role: str = '',
|
|
285
|
+
)
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
`QuestionType`: `QUESTION`, `SEMANTIC`, `KEYWORD`, `GET`, `PROMPT`. Default type is `QUESTION`. Default filter and `expectJson=False`, `role=''` if omitted.
|
|
289
|
+
|
|
290
|
+
### Methods
|
|
291
|
+
|
|
292
|
+
| Method | Signature | Description |
|
|
293
|
+
| ---------------- | -------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
|
|
294
|
+
| `addInstruction` | `addInstruction(self, title: str, instruction: str)` | Adds an instruction (e.g. "Use bullet points"). |
|
|
295
|
+
| `addExample` | `addExample(self, given: str, result: dict \| list \| str)` | Adds an example input/output; `result` can be dict/list (JSON-serialized). |
|
|
296
|
+
| `addContext` | `addContext(self, context: str \| dict \| List[str] \| List[dict])` | Adds context. |
|
|
297
|
+
| `addHistory` | `addHistory(self, item: QuestionHistory)` | Adds a history item for multi-turn chat. |
|
|
298
|
+
| `addQuestion` | `addQuestion(self, question: str)` | Appends the question text. |
|
|
299
|
+
| `addDocuments` | `addDocuments(self, documents: Doc \| List[Doc])` | Adds documents for the AI to reference. |
|
|
300
|
+
| `getPrompt` | `getPrompt(self, has_previous_json_failed: bool = False) -> str` | Returns the full prompt (internal). |
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## Answer
|
|
305
|
+
|
|
306
|
+
From `rocketride.schema`. Used to parse chat response content. The client does not attach an `Answer` instance to the pipeline result; you read the response body and, if needed, use these helpers to extract JSON or code from AI text (which often includes markdown or code fences).
|
|
307
|
+
|
|
308
|
+
| Method | Signature | Description |
|
|
309
|
+
| ------------- | ------------------------------------------ | ---------------------------------------------------------------------- |
|
|
310
|
+
| `getText` | `getText(self) -> str` | Get the answer as plain text. |
|
|
311
|
+
| `getJson` | `getJson(self) -> Optional[dict]` | Get the answer as parsed JSON; returns `None` if not valid JSON. |
|
|
312
|
+
| `isJson` | `isJson(self) -> bool` | Whether the answer contains valid JSON. |
|
|
313
|
+
| `parseJson` | `parseJson(self, value: str) -> Any` | Parses JSON from AI text (strips markdown/code blocks). |
|
|
314
|
+
| `parsePython` | `parsePython(self, value: str) -> Any` | Extracts Python code from a code block in the response. |
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## Types
|
|
319
|
+
|
|
320
|
+
- **PIPELINE_RESULT**: TypedDict with `name`, `path`, `objectId`, optional `result_types`, and dynamic fields.
|
|
321
|
+
- **UPLOAD_RESULT**: Per-file result with `action`, `filepath`, `error?`, `result?`, `upload_time?`, etc.
|
|
322
|
+
- **TASK_STATUS**: Task status with `completedCount`, `totalCount`, `completed`, `state`, `exitCode`, and many more fields.
|
|
323
|
+
- **DAPMessage**: Dict with `type`, `seq`, and optional `command`, `arguments`, `body`, `success`, `message`, `event`, `token`, etc.
|
|
324
|
+
- **PipelineConfig**: Pipeline definition with `name`, `description`, `version`, `components`, `source`, `project_id`.
|
|
325
|
+
- **QuestionHistory**: `{ 'role': str, 'content': str }`.
|
|
326
|
+
- **QuestionInstruction**: `{ 'subtitle': str, 'instructions': str }`.
|
|
327
|
+
- **QuestionExample**: `{ 'given': str, 'result': str }`.
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
## Exceptions
|
|
332
|
+
|
|
333
|
+
The exception hierarchy provides fine-grained error handling:
|
|
334
|
+
|
|
335
|
+
```text
|
|
336
|
+
DAPException # Base DAP protocol error (has dap_result dict)
|
|
337
|
+
└── RocketRideException # Base for all RocketRide errors
|
|
338
|
+
├── ConnectionException # Connection/network issues
|
|
339
|
+
│ └── AuthenticationException # Bad API key or credentials
|
|
340
|
+
├── PipeException # Data pipe errors (open/write/close)
|
|
341
|
+
├── ExecutionException # Pipeline start/run failures
|
|
342
|
+
└── ValidationException # Invalid input/config
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
All exceptions expose a `dap_result` dict with detailed server error context.
|
|
346
|
+
|
|
347
|
+
`AuthenticationException` is thrown on DAP auth failure. In persist mode the client catches it, calls `on_connect_error`, and does not retry so the app can fix credentials and call `connect()` again.
|
|
348
|
+
|
|
349
|
+
**Example:**
|
|
350
|
+
|
|
351
|
+
```python
|
|
352
|
+
from rocketride import RocketRideClient, AuthenticationException
|
|
353
|
+
from rocketride.core.exceptions import PipeException, ExecutionException
|
|
354
|
+
|
|
355
|
+
try:
|
|
356
|
+
async with RocketRideClient(uri=uri, auth=auth) as client:
|
|
357
|
+
result = await client.use(filepath="pipeline.json")
|
|
358
|
+
await client.send(result["token"], data)
|
|
359
|
+
except AuthenticationException:
|
|
360
|
+
print("Bad credentials")
|
|
361
|
+
except ExecutionException as e:
|
|
362
|
+
print(f"Pipeline failed: {e}")
|
|
363
|
+
except PipeException as e:
|
|
364
|
+
print(f"Data transfer error: {e}")
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
---
|
|
368
|
+
|
|
369
|
+
## Examples (Full API Usage)
|
|
370
|
+
|
|
371
|
+
### 1. Minimal: connect, run pipeline from file, send one string, disconnect
|
|
372
|
+
|
|
373
|
+
```python
|
|
374
|
+
import asyncio
|
|
375
|
+
from rocketride import RocketRideClient
|
|
376
|
+
|
|
377
|
+
async def main():
|
|
378
|
+
client = RocketRideClient(uri="https://cloud.rocketride.ai", auth="my-key")
|
|
379
|
+
await client.connect()
|
|
380
|
+
result = await client.use(filepath="pipeline.json")
|
|
381
|
+
token = result["token"]
|
|
382
|
+
out = await client.send(token, "Hello, pipeline!", objinfo={"name": "input.txt"}, mimetype="text/plain")
|
|
383
|
+
print(out)
|
|
384
|
+
await client.terminate(token)
|
|
385
|
+
await client.disconnect()
|
|
386
|
+
|
|
387
|
+
asyncio.run(main())
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
### 2. One-off script with context manager (recommended)
|
|
391
|
+
|
|
392
|
+
```python
|
|
393
|
+
import asyncio
|
|
394
|
+
from rocketride import RocketRideClient
|
|
395
|
+
|
|
396
|
+
async def main():
|
|
397
|
+
async with RocketRideClient(uri="wss://cloud.rocketride.ai", auth="my-key") as client:
|
|
398
|
+
result = await client.use(pipeline={"pipeline": my_pipeline_config})
|
|
399
|
+
token = result["token"]
|
|
400
|
+
await client.send(token, '{"data": 1}')
|
|
401
|
+
status = await client.get_task_status(token)
|
|
402
|
+
print(status)
|
|
403
|
+
await client.terminate(token)
|
|
404
|
+
|
|
405
|
+
asyncio.run(main())
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
### 3. Long-lived app: persist mode, callbacks, and status handling
|
|
409
|
+
|
|
410
|
+
```python
|
|
411
|
+
import asyncio
|
|
412
|
+
from rocketride import RocketRideClient
|
|
413
|
+
|
|
414
|
+
async def main():
|
|
415
|
+
client = RocketRideClient(
|
|
416
|
+
uri="https://cloud.rocketride.ai",
|
|
417
|
+
auth="my-key",
|
|
418
|
+
persist=True,
|
|
419
|
+
max_retry_time=300000,
|
|
420
|
+
on_connected=lambda info: print("Connected:", info),
|
|
421
|
+
on_disconnected=lambda reason, has_error: print("Disconnected:", reason, has_error),
|
|
422
|
+
on_connect_error=lambda msg: print("Connect error:", msg),
|
|
423
|
+
on_event=lambda e: print(e.get("event"), e.get("body")),
|
|
424
|
+
)
|
|
425
|
+
await client.connect()
|
|
426
|
+
# Later: use(), send_files(), etc. If connection drops, client retries; do not call disconnect() in on_disconnected.
|
|
427
|
+
|
|
428
|
+
asyncio.run(main())
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
### 4. Upload multiple files and poll until pipeline completes
|
|
432
|
+
|
|
433
|
+
```python
|
|
434
|
+
import asyncio
|
|
435
|
+
from pathlib import Path
|
|
436
|
+
from rocketride import RocketRideClient
|
|
437
|
+
|
|
438
|
+
async def main():
|
|
439
|
+
client = RocketRideClient(uri="https://cloud.rocketride.ai", auth="my-key")
|
|
440
|
+
await client.connect()
|
|
441
|
+
result = await client.use(filepath="vectorize.json")
|
|
442
|
+
token = result["token"]
|
|
443
|
+
await client.set_events(token, ["apaevt_status_upload", "apaevt_status_processing"])
|
|
444
|
+
|
|
445
|
+
files = ["doc1.md", "doc2.md", ("doc3.json", {"tag": "export"}, "application/json")]
|
|
446
|
+
upload_results = await client.send_files(files, token)
|
|
447
|
+
for r in upload_results:
|
|
448
|
+
if r["action"] == "complete":
|
|
449
|
+
print("OK", r["filepath"])
|
|
450
|
+
else:
|
|
451
|
+
print("Failed", r["filepath"], r.get("error"))
|
|
452
|
+
|
|
453
|
+
while True:
|
|
454
|
+
status = await client.get_task_status(token)
|
|
455
|
+
print(f"Progress: {status.get('completedCount', 0)}/{status.get('totalCount', 0)}")
|
|
456
|
+
if status.get("completed"):
|
|
457
|
+
break
|
|
458
|
+
await asyncio.sleep(2)
|
|
459
|
+
await client.terminate(token)
|
|
460
|
+
await client.disconnect()
|
|
461
|
+
|
|
462
|
+
asyncio.run(main())
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
### 5. Streaming large data with a pipe
|
|
466
|
+
|
|
467
|
+
```python
|
|
468
|
+
import asyncio
|
|
469
|
+
from rocketride import RocketRideClient
|
|
470
|
+
|
|
471
|
+
async def main():
|
|
472
|
+
async with RocketRideClient(uri="https://cloud.rocketride.ai", auth="my-key") as client:
|
|
473
|
+
result = await client.use(filepath="ingest.json")
|
|
474
|
+
token = result["token"]
|
|
475
|
+
pipe = await client.pipe(token, objinfo={"name": "large.csv"}, mime_type="text/csv")
|
|
476
|
+
async with pipe:
|
|
477
|
+
with open("large.csv", "rb") as f:
|
|
478
|
+
while True:
|
|
479
|
+
chunk = f.read(64 * 1024)
|
|
480
|
+
if not chunk:
|
|
481
|
+
break
|
|
482
|
+
await pipe.write(chunk)
|
|
483
|
+
result = await pipe.close()
|
|
484
|
+
print(result)
|
|
485
|
+
await client.terminate(token)
|
|
486
|
+
|
|
487
|
+
asyncio.run(main())
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
### 6. Chat: question with instructions and examples, parse JSON answer
|
|
491
|
+
|
|
492
|
+
```python
|
|
493
|
+
import asyncio
|
|
494
|
+
from rocketride import RocketRideClient
|
|
495
|
+
from rocketride.schema import Question, Answer
|
|
496
|
+
|
|
497
|
+
async def main():
|
|
498
|
+
async with RocketRideClient(uri="https://cloud.rocketride.ai", auth="my-key") as client:
|
|
499
|
+
result = await client.use(filepath="chat_pipeline.json")
|
|
500
|
+
token = result["token"]
|
|
501
|
+
question = Question(expectJson=True)
|
|
502
|
+
question.addInstruction("Format", "Return a JSON object with keys: summary, keywords.")
|
|
503
|
+
question.addExample("Summarize X", {"summary": "...", "keywords": ["a", "b"]})
|
|
504
|
+
question.addQuestion("Summarize the main points and list keywords.")
|
|
505
|
+
response = await client.chat(token=token, question=question)
|
|
506
|
+
answer_text = response.get("data", {}).get("answer") or (response.get("answers") or [None])[0]
|
|
507
|
+
structured = Answer().parseJson(answer_text) if answer_text else None
|
|
508
|
+
print(structured)
|
|
509
|
+
await client.terminate(token)
|
|
510
|
+
|
|
511
|
+
asyncio.run(main())
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
### 7. Discover services and send a custom DAP request
|
|
515
|
+
|
|
516
|
+
```python
|
|
517
|
+
import asyncio
|
|
518
|
+
from rocketride import RocketRideClient
|
|
519
|
+
|
|
520
|
+
async def main():
|
|
521
|
+
client = RocketRideClient(uri="https://cloud.rocketride.ai", auth="my-key")
|
|
522
|
+
await client.connect()
|
|
523
|
+
services = await client.get_services()
|
|
524
|
+
print("Available:", list(services.keys()))
|
|
525
|
+
ocr = await client.get_service("ocr")
|
|
526
|
+
if ocr:
|
|
527
|
+
print("OCR schema:", ocr.get("schema"))
|
|
528
|
+
req = client.build_request("rrext_ping", token=my_token)
|
|
529
|
+
res = await client.request(req, timeout=5000)
|
|
530
|
+
if client.did_fail(res):
|
|
531
|
+
raise RuntimeError(res.get("message", "Ping failed"))
|
|
532
|
+
await client.disconnect()
|
|
533
|
+
|
|
534
|
+
asyncio.run(main())
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
---
|
|
538
|
+
|
|
539
|
+
## Directory Structure
|
|
540
|
+
|
|
541
|
+
Source location in the repository:
|
|
542
|
+
|
|
543
|
+
```text
|
|
544
|
+
packages/client-python/
|
|
545
|
+
├── src/rocketride/
|
|
546
|
+
│ ├── client.py # Main RocketRideClient class
|
|
547
|
+
│ ├── core/ # DAP protocol, transport, exceptions
|
|
548
|
+
│ ├── mixins/ # Connection, data, chat, events, services, store
|
|
549
|
+
│ ├── schema/ # Question, Answer, Doc, DocFilter, DocGroup, DocMetadata
|
|
550
|
+
│ ├── types/ # Type definitions (PIPELINE_RESULT, TASK_STATUS, etc.)
|
|
551
|
+
│ └── cli/ # CLI (rocketride command)
|
|
552
|
+
├── tests/
|
|
553
|
+
├── examples/
|
|
554
|
+
├── pyproject.toml
|
|
555
|
+
└── README.md
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
---
|
|
559
|
+
|
|
560
|
+
## License
|
|
561
|
+
|
|
562
|
+
MIT License -- see [LICENSE](../LICENSE).
|