boxxkite-client 0.2.3__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.
- boxxkite_client-0.2.3/PKG-INFO +117 -0
- boxxkite_client-0.2.3/README.md +99 -0
- boxxkite_client-0.2.3/pyproject.toml +27 -0
- boxxkite_client-0.2.3/setup.cfg +4 -0
- boxxkite_client-0.2.3/src/boxxkite_client/__init__.py +31 -0
- boxxkite_client-0.2.3/src/boxxkite_client/client.py +1890 -0
- boxxkite_client-0.2.3/src/boxxkite_client/exceptions.py +22 -0
- boxxkite_client-0.2.3/src/boxxkite_client/langchain_tools.py +197 -0
- boxxkite_client-0.2.3/src/boxxkite_client.egg-info/PKG-INFO +117 -0
- boxxkite_client-0.2.3/src/boxxkite_client.egg-info/SOURCES.txt +15 -0
- boxxkite_client-0.2.3/src/boxxkite_client.egg-info/dependency_links.txt +1 -0
- boxxkite_client-0.2.3/src/boxxkite_client.egg-info/requires.txt +9 -0
- boxxkite_client-0.2.3/src/boxxkite_client.egg-info/top_level.txt +1 -0
- boxxkite_client-0.2.3/tests/test_async_client.py +1482 -0
- boxxkite_client-0.2.3/tests/test_client.py +1451 -0
- boxxkite_client-0.2.3/tests/test_langchain_tools.py +220 -0
- boxxkite_client-0.2.3/tests/test_retry.py +177 -0
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: boxxkite-client
|
|
3
|
+
Version: 0.2.3
|
|
4
|
+
Summary: Python client for a hosted boxxkite control-plane (sandbox creation, exec, files, LangChain tools).
|
|
5
|
+
License: Apache-2.0
|
|
6
|
+
Project-URL: Homepage, https://github.com/EvAlssment/boxxkite
|
|
7
|
+
Project-URL: Repository, https://github.com/EvAlssment/boxxkite
|
|
8
|
+
Project-URL: Issues, https://github.com/EvAlssment/boxxkite/issues
|
|
9
|
+
Requires-Python: >=3.10
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
Requires-Dist: httpx>=0.27
|
|
12
|
+
Requires-Dist: websockets>=13
|
|
13
|
+
Provides-Extra: langchain
|
|
14
|
+
Requires-Dist: langchain-core>=0.3; extra == "langchain"
|
|
15
|
+
Provides-Extra: dev
|
|
16
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
17
|
+
Requires-Dist: ruff>=0.6; extra == "dev"
|
|
18
|
+
|
|
19
|
+
# boxxkite-client
|
|
20
|
+
|
|
21
|
+
[](https://pypi.org/project/boxxkite-client/)
|
|
22
|
+
|
|
23
|
+
A Python client for a **hosted** boxxkite control-plane — create sandboxes,
|
|
24
|
+
run commands, edit files, over HTTP. Not the boxxkite package itself
|
|
25
|
+
(`boxxkite-sandbox`, which embeds `SandboxManager` against your own
|
|
26
|
+
Kubernetes cluster) — use this to talk to *someone else's* running
|
|
27
|
+
control-plane, hosted or self-hosted, over its API.
|
|
28
|
+
|
|
29
|
+
## Install
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pip install boxxkite-client
|
|
33
|
+
pip install boxxkite-client[langchain] # for create_sandbox_tools
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Quickstart
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
from boxxkite_client import BoxxkiteClient
|
|
40
|
+
|
|
41
|
+
client = BoxxkiteClient(base_url="https://your-control-plane.example.com", api_key="bxk_live_...")
|
|
42
|
+
|
|
43
|
+
with client.sandbox(label="demo") as sb:
|
|
44
|
+
result = sb.exec("python3 -c 'print(1 + 1)'")
|
|
45
|
+
print(result["stdout"]) # "2\n"
|
|
46
|
+
|
|
47
|
+
sb.file_create("notes.txt", "hello from boxxkite-client\n")
|
|
48
|
+
print(sb.view("notes.txt")["content"])
|
|
49
|
+
# sandbox is destroyed automatically here, even if an exception was raised above
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Also available: `AsyncBoxxkiteClient` (same shapes, `async`/`await`),
|
|
53
|
+
file/directory search (`ls`/`glob`/`grep`), long-running background
|
|
54
|
+
processes (`start_process`/`get_process_output`/`stop_process`), signed
|
|
55
|
+
preview URLs for exposing a port, an audit-log feed (`get_log`/`watch`),
|
|
56
|
+
interactive human takeover over a raw WebSocket, desktop (GUI) takeover
|
|
57
|
+
over the same raw-WebSocket pattern, secret management
|
|
58
|
+
(`create_secret`/`list_secrets`/`delete_secret`, for use via
|
|
59
|
+
`create_sandbox(secret_names=[...])`), and a `create_sandbox_tools()`
|
|
60
|
+
LangChain factory. Full reference with examples
|
|
61
|
+
for all of these: [`docs/API.md`](https://github.com/EvAlssment/boxxkite/blob/main/docs/API.md).
|
|
62
|
+
|
|
63
|
+
## Error handling
|
|
64
|
+
|
|
65
|
+
Every non-2xx response raises `BoxxkiteApiError` (`.status_code`, `.code`,
|
|
66
|
+
`.message`). A network-level failure raises `BoxxkiteConnectionError`. Both
|
|
67
|
+
subclass `BoxxkiteError`.
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
from boxxkite_client import BoxxkiteApiError
|
|
71
|
+
|
|
72
|
+
try:
|
|
73
|
+
client.exec(sandbox["id"], "echo hi")
|
|
74
|
+
except BoxxkiteApiError as exc:
|
|
75
|
+
if exc.code == "concurrent_sandbox_limit_reached":
|
|
76
|
+
... # back off, destroy an old session, etc.
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Retries
|
|
80
|
+
|
|
81
|
+
Automatic retry is **off by default**. Pass a `RetryConfig` to enable it;
|
|
82
|
+
`RetryConfig()` carries sensible defaults (2 retries, exponential backoff
|
|
83
|
+
with full jitter, `Retry-After` honored):
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
from boxxkite_client import BoxxkiteClient, RetryConfig
|
|
87
|
+
|
|
88
|
+
client = BoxxkiteClient(base_url="...", api_key="...", retry=RetryConfig())
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Only idempotent verbs (`GET`/`HEAD`/`PUT`/`DELETE`/`OPTIONS`) are retried,
|
|
92
|
+
and only on a connection failure or a transient status (429, 500, 502, 503,
|
|
93
|
+
504) — a non-idempotent `POST` (create-sandbox/secret/webhook) is never
|
|
94
|
+
retried, so this can't double-create a resource. `AsyncBoxxkiteClient` takes
|
|
95
|
+
the same `retry=` argument and awaits its backoff. Every field of
|
|
96
|
+
`RetryConfig` is tunable if the defaults don't fit.
|
|
97
|
+
|
|
98
|
+
## Development
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
pip install -e ".[dev,langchain]"
|
|
102
|
+
pytest tests/
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Tests mock the control-plane with `httpx.MockTransport` — no real deployment needed.
|
|
106
|
+
|
|
107
|
+
## Related tools
|
|
108
|
+
|
|
109
|
+
Moving an in-progress local Claude Code/Codex CLI/opencode session (full
|
|
110
|
+
conversation history, not just a diff) into a fresh boxxkite sandbox is
|
|
111
|
+
handled by the separate `boxxkite-handoff` CLI, built on this SDK — see
|
|
112
|
+
[`../docs/handoff-adapters.md`](../docs/handoff-adapters.md) and
|
|
113
|
+
[`../handoff-cli/README.md`](../handoff-cli/README.md). Not yet published
|
|
114
|
+
to PyPI.
|
|
115
|
+
|
|
116
|
+
See the [root README](https://github.com/EvAlssment/boxxkite#readme) for
|
|
117
|
+
what boxxkite is and the full self-hosting story.
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# boxxkite-client
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/boxxkite-client/)
|
|
4
|
+
|
|
5
|
+
A Python client for a **hosted** boxxkite control-plane — create sandboxes,
|
|
6
|
+
run commands, edit files, over HTTP. Not the boxxkite package itself
|
|
7
|
+
(`boxxkite-sandbox`, which embeds `SandboxManager` against your own
|
|
8
|
+
Kubernetes cluster) — use this to talk to *someone else's* running
|
|
9
|
+
control-plane, hosted or self-hosted, over its API.
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install boxxkite-client
|
|
15
|
+
pip install boxxkite-client[langchain] # for create_sandbox_tools
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Quickstart
|
|
19
|
+
|
|
20
|
+
```python
|
|
21
|
+
from boxxkite_client import BoxxkiteClient
|
|
22
|
+
|
|
23
|
+
client = BoxxkiteClient(base_url="https://your-control-plane.example.com", api_key="bxk_live_...")
|
|
24
|
+
|
|
25
|
+
with client.sandbox(label="demo") as sb:
|
|
26
|
+
result = sb.exec("python3 -c 'print(1 + 1)'")
|
|
27
|
+
print(result["stdout"]) # "2\n"
|
|
28
|
+
|
|
29
|
+
sb.file_create("notes.txt", "hello from boxxkite-client\n")
|
|
30
|
+
print(sb.view("notes.txt")["content"])
|
|
31
|
+
# sandbox is destroyed automatically here, even if an exception was raised above
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Also available: `AsyncBoxxkiteClient` (same shapes, `async`/`await`),
|
|
35
|
+
file/directory search (`ls`/`glob`/`grep`), long-running background
|
|
36
|
+
processes (`start_process`/`get_process_output`/`stop_process`), signed
|
|
37
|
+
preview URLs for exposing a port, an audit-log feed (`get_log`/`watch`),
|
|
38
|
+
interactive human takeover over a raw WebSocket, desktop (GUI) takeover
|
|
39
|
+
over the same raw-WebSocket pattern, secret management
|
|
40
|
+
(`create_secret`/`list_secrets`/`delete_secret`, for use via
|
|
41
|
+
`create_sandbox(secret_names=[...])`), and a `create_sandbox_tools()`
|
|
42
|
+
LangChain factory. Full reference with examples
|
|
43
|
+
for all of these: [`docs/API.md`](https://github.com/EvAlssment/boxxkite/blob/main/docs/API.md).
|
|
44
|
+
|
|
45
|
+
## Error handling
|
|
46
|
+
|
|
47
|
+
Every non-2xx response raises `BoxxkiteApiError` (`.status_code`, `.code`,
|
|
48
|
+
`.message`). A network-level failure raises `BoxxkiteConnectionError`. Both
|
|
49
|
+
subclass `BoxxkiteError`.
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
from boxxkite_client import BoxxkiteApiError
|
|
53
|
+
|
|
54
|
+
try:
|
|
55
|
+
client.exec(sandbox["id"], "echo hi")
|
|
56
|
+
except BoxxkiteApiError as exc:
|
|
57
|
+
if exc.code == "concurrent_sandbox_limit_reached":
|
|
58
|
+
... # back off, destroy an old session, etc.
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Retries
|
|
62
|
+
|
|
63
|
+
Automatic retry is **off by default**. Pass a `RetryConfig` to enable it;
|
|
64
|
+
`RetryConfig()` carries sensible defaults (2 retries, exponential backoff
|
|
65
|
+
with full jitter, `Retry-After` honored):
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
from boxxkite_client import BoxxkiteClient, RetryConfig
|
|
69
|
+
|
|
70
|
+
client = BoxxkiteClient(base_url="...", api_key="...", retry=RetryConfig())
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Only idempotent verbs (`GET`/`HEAD`/`PUT`/`DELETE`/`OPTIONS`) are retried,
|
|
74
|
+
and only on a connection failure or a transient status (429, 500, 502, 503,
|
|
75
|
+
504) — a non-idempotent `POST` (create-sandbox/secret/webhook) is never
|
|
76
|
+
retried, so this can't double-create a resource. `AsyncBoxxkiteClient` takes
|
|
77
|
+
the same `retry=` argument and awaits its backoff. Every field of
|
|
78
|
+
`RetryConfig` is tunable if the defaults don't fit.
|
|
79
|
+
|
|
80
|
+
## Development
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
pip install -e ".[dev,langchain]"
|
|
84
|
+
pytest tests/
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Tests mock the control-plane with `httpx.MockTransport` — no real deployment needed.
|
|
88
|
+
|
|
89
|
+
## Related tools
|
|
90
|
+
|
|
91
|
+
Moving an in-progress local Claude Code/Codex CLI/opencode session (full
|
|
92
|
+
conversation history, not just a diff) into a fresh boxxkite sandbox is
|
|
93
|
+
handled by the separate `boxxkite-handoff` CLI, built on this SDK — see
|
|
94
|
+
[`../docs/handoff-adapters.md`](../docs/handoff-adapters.md) and
|
|
95
|
+
[`../handoff-cli/README.md`](../handoff-cli/README.md). Not yet published
|
|
96
|
+
to PyPI.
|
|
97
|
+
|
|
98
|
+
See the [root README](https://github.com/EvAlssment/boxxkite#readme) for
|
|
99
|
+
what boxxkite is and the full self-hosting story.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "boxxkite-client"
|
|
7
|
+
version = "0.2.3"
|
|
8
|
+
description = "Python client for a hosted boxxkite control-plane (sandbox creation, exec, files, LangChain tools)."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { text = "Apache-2.0" }
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
dependencies = [
|
|
13
|
+
"httpx>=0.27",
|
|
14
|
+
"websockets>=13",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
[project.optional-dependencies]
|
|
18
|
+
langchain = ["langchain-core>=0.3"]
|
|
19
|
+
dev = ["pytest>=8", "ruff>=0.6"]
|
|
20
|
+
|
|
21
|
+
[project.urls]
|
|
22
|
+
Homepage = "https://github.com/EvAlssment/boxxkite"
|
|
23
|
+
Repository = "https://github.com/EvAlssment/boxxkite"
|
|
24
|
+
Issues = "https://github.com/EvAlssment/boxxkite/issues"
|
|
25
|
+
|
|
26
|
+
[tool.setuptools.packages.find]
|
|
27
|
+
where = ["src"]
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""boxxkite_client — a Python client for a hosted boxxkite control-plane.
|
|
2
|
+
|
|
3
|
+
from boxxkite_client import BoxxkiteClient
|
|
4
|
+
|
|
5
|
+
client = BoxxkiteClient(base_url="https://your-control-plane", api_key="bxk_live_...")
|
|
6
|
+
with client.sandbox(label="demo") as sb:
|
|
7
|
+
result = sb.exec("echo hello")
|
|
8
|
+
print(result["stdout"])
|
|
9
|
+
|
|
10
|
+
See README.md for the async client and LangChain tool factory.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from .client import (
|
|
14
|
+
AsyncBoxxkiteClient,
|
|
15
|
+
AsyncSandboxSession,
|
|
16
|
+
BoxxkiteClient,
|
|
17
|
+
RetryConfig,
|
|
18
|
+
SandboxSession,
|
|
19
|
+
)
|
|
20
|
+
from .exceptions import BoxxkiteApiError, BoxxkiteConnectionError, BoxxkiteError
|
|
21
|
+
|
|
22
|
+
__all__ = [
|
|
23
|
+
"AsyncBoxxkiteClient",
|
|
24
|
+
"AsyncSandboxSession",
|
|
25
|
+
"BoxxkiteApiError",
|
|
26
|
+
"BoxxkiteClient",
|
|
27
|
+
"BoxxkiteConnectionError",
|
|
28
|
+
"BoxxkiteError",
|
|
29
|
+
"RetryConfig",
|
|
30
|
+
"SandboxSession",
|
|
31
|
+
]
|