Skip to content

Commit e9d49be

Browse files
authored
Merge pull request jsturtevant#1 from jsturtevant/fix/hyperlight-python-compat
fix(hyperlight-codeact): pin version >=0.3.0 and handle Python 3.14+
2 parents 12a011e + 4a06bc6 commit e9d49be

2 files changed

Lines changed: 81 additions & 13 deletions

File tree

‎skills/hyperlight-codeact/SKILL.md‎

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,10 @@ Sandboxed code can only reach the outside world through `call_tool()` bridges.
5353
python3 scripts/codeact.py --discover
5454

5555
# 2. Run code (uv auto-installs hyperlight-sandbox into an ephemeral env)
56-
uv run --with 'hyperlight-sandbox[wasm,python_guest]' python3 scripts/codeact.py --auto --workspace . --code '
56+
# NOTE: The Wasm backend requires Python ≤3.13. Use --python 3.13 if your
57+
# system default is newer. Pin >=0.3.0 to avoid the empty stub package.
58+
uv run --python 3.13 --with 'hyperlight-sandbox[wasm,python_guest]>=0.3.0' \
59+
python3 scripts/codeact.py --auto --workspace . --code '
5760
content = call_tool("view", path="README.md")
5861
print(f"README has {len(content.splitlines())} lines")
5962
'
@@ -100,14 +103,20 @@ content = call_tool('view', path=call_tool('glob', pattern='config.json')[0])
100103

101104
### Step 3 -- Execute
102105

103-
Use `uv run --with` to auto-install the dependency:
106+
Use `uv run --with` to auto-install the dependency.
107+
108+
**Important:** The Wasm backend only has wheels for Python ≤3.13. If your
109+
system Python is 3.14+, add `--python 3.13` to the `uv run` command. Always
110+
pin `>=0.3.0` — earlier versions are stub packages without the `Sandbox` class.
104111

105112
```bash
106113
# Auto-discover + workspace scoping (recommended)
107-
uv run --with 'hyperlight-sandbox[wasm,python_guest]' python3 scripts/codeact.py --auto --workspace . --code '...'
114+
uv run --python 3.13 --with 'hyperlight-sandbox[wasm,python_guest]>=0.3.0' \
115+
python3 scripts/codeact.py --auto --workspace . --code '...'
108116

109117
# With saved manifest
110-
uv run --with 'hyperlight-sandbox[wasm,python_guest]' python3 scripts/codeact.py --manifest tools.json --code-file script.py
118+
uv run --python 3.13 --with 'hyperlight-sandbox[wasm,python_guest]>=0.3.0' \
119+
python3 scripts/codeact.py --manifest tools.json --code-file script.py
111120
```
112121

113122
If `hyperlight-sandbox` is already installed, plain `python3` works too:
@@ -134,6 +143,9 @@ Main executor. Key flags:
134143

135144
## Prerequisites
136145

137-
- Python 3.10+
146+
- Python 3.10–3.13 (the Wasm backend does **not** have wheels for 3.14+)
138147
- `uv` (recommended — auto-installs `hyperlight-sandbox` with no side effects)
139-
- Or: `pip install 'hyperlight-sandbox[wasm,python_guest]'`
148+
- Or: `pip install 'hyperlight-sandbox[wasm,python_guest]>=0.3.0'`
149+
150+
> **Tip:** If your system Python is 3.14+, use `uv run --python 3.13 ...` to
151+
> automatically fetch and use a compatible interpreter.

‎skills/hyperlight-codeact/scripts/codeact.py‎

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,68 @@ def _try_install(package: str, import_name: str):
509509
return None
510510

511511

512+
# Minimum version that exports the Sandbox class and Wasm backend.
513+
_MIN_VERSION = "0.3.0"
514+
# Maximum Python version with pre-built Wasm backend wheels.
515+
_MAX_PYTHON = (3, 13)
516+
517+
518+
def _check_python_version() -> None:
519+
"""Warn if the current Python is too new for pre-built Wasm wheels."""
520+
if sys.version_info[:2] > _MAX_PYTHON:
521+
max_str = f"{_MAX_PYTHON[0]}.{_MAX_PYTHON[1]}"
522+
cur_str = f"{sys.version_info.major}.{sys.version_info.minor}"
523+
print(
524+
f"\n⚠ Python {cur_str} detected. The hyperlight-sandbox Wasm backend "
525+
f"only ships wheels for Python ≤{max_str}.\n"
526+
f" Re-run with: uv run --python {max_str} "
527+
f"--with 'hyperlight-sandbox[wasm,python_guest]>={_MIN_VERSION}' "
528+
f"python3 scripts/codeact.py ...\n",
529+
file=sys.stderr,
530+
)
531+
sys.exit(1)
532+
533+
534+
def _import_sandbox():
535+
"""Import the Sandbox class, giving actionable errors on failure."""
536+
# 1. Check Python version first — avoids confusing resolution errors.
537+
_check_python_version()
538+
539+
# 2. Try the import.
540+
try:
541+
from hyperlight_sandbox import Sandbox
542+
return Sandbox
543+
except ImportError:
544+
pass
545+
546+
# 3. Check if hyperlight_sandbox is installed but too old (stub package).
547+
try:
548+
import hyperlight_sandbox as _hl
549+
ver = getattr(_hl, "__version__", "0.0.0")
550+
if not hasattr(_hl, "Sandbox"):
551+
print(
552+
f"\n✗ hyperlight-sandbox {ver} is installed but does not "
553+
f"export Sandbox (likely a stub package).\n"
554+
f" Install version ≥{_MIN_VERSION}:\n"
555+
f" uv run --python {_MAX_PYTHON[0]}.{_MAX_PYTHON[1]} "
556+
f"--with 'hyperlight-sandbox[wasm,python_guest]>={_MIN_VERSION}' "
557+
f"python3 scripts/codeact.py ...\n",
558+
file=sys.stderr,
559+
)
560+
sys.exit(1)
561+
except ImportError:
562+
pass
563+
564+
# 4. Not installed at all — try interactive install.
565+
_mod = _try_install(
566+
f"hyperlight-sandbox[wasm,python_guest]>={_MIN_VERSION}",
567+
"hyperlight_sandbox",
568+
)
569+
if _mod is None:
570+
sys.exit(1)
571+
return _mod.Sandbox
572+
573+
512574
# ---------------------------------------------------------------------------
513575
# Main
514576
# ---------------------------------------------------------------------------
@@ -559,13 +621,7 @@ def main() -> None:
559621
return
560622

561623
# ---- execution ----
562-
try:
563-
from hyperlight_sandbox import Sandbox
564-
except ImportError:
565-
_mod = _try_install("hyperlight-sandbox[wasm,python_guest]", "hyperlight_sandbox")
566-
if _mod is None:
567-
sys.exit(1)
568-
Sandbox = _mod.Sandbox
624+
Sandbox = _import_sandbox()
569625

570626
global _WORKSPACE_ROOT
571627
if args.workspace:

0 commit comments

Comments
 (0)