@@ -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