Spaces:
Running on Zero
Running on Zero
File size: 3,752 Bytes
e2b893f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | """Provision Node.js and the shared nerimity.js install inside the Space container.
Gradio Space images ship Python, not Node. Rather than depend on whatever `apt` would give
us, we download the official Node LTS tarball on cold start (~25 MB compressed, ~20 s) into
/home/user/.node and install @nerimity/nerimity.js once into a shared node_modules that all
bots resolve through NODE_PATH.
(The plan called this bootstrap_node.sh; it's Python so failures surface in the same log
stream as everything else instead of vanishing into a subshell.)
"""
from __future__ import annotations
import os
import shutil
import subprocess
import tarfile
import urllib.request
from pathlib import Path
NODE_VERSION = os.environ.get("BB_NODE_VERSION", "v22.14.0")
NODE_HOME = Path(os.environ.get("BB_NODE_HOME", "/home/user/.node"))
DATA_DIR = Path(os.environ.get("BB_DATA_DIR", "/home/user/data"))
SHARED_MODULES = DATA_DIR / "node_modules"
NERIMITY_PKG = "@nerimity/nerimity.js"
def _log(msg: str) -> None:
print(f"[node] {msg}", flush=True)
def ensure_node() -> str:
"""Return a usable `node` binary path, downloading the runtime if needed."""
existing = shutil.which("node")
if existing:
_log(f"using system node: {existing}")
return existing
node_bin = NODE_HOME / "bin" / "node"
if node_bin.exists():
_log(f"using cached node: {node_bin}")
os.environ["PATH"] = f"{NODE_HOME / 'bin'}:{os.environ.get('PATH', '')}"
return str(node_bin)
name = f"node-{NODE_VERSION}-linux-x64"
url = f"https://nodejs.org/dist/{NODE_VERSION}/{name}.tar.xz"
tmp = Path("/tmp") / f"{name}.tar.xz"
_log(f"downloading {url}")
urllib.request.urlretrieve(url, tmp) # noqa: S310 - fixed, trusted URL
_log("extracting")
NODE_HOME.parent.mkdir(parents=True, exist_ok=True)
with tarfile.open(tmp) as tf:
tf.extractall("/tmp") # noqa: S202 - official tarball
extracted = Path("/tmp") / name
if NODE_HOME.exists():
shutil.rmtree(NODE_HOME, ignore_errors=True)
shutil.move(str(extracted), str(NODE_HOME))
tmp.unlink(missing_ok=True)
os.environ["PATH"] = f"{NODE_HOME / 'bin'}:{os.environ.get('PATH', '')}"
_log(f"node ready: {node_bin}")
return str(node_bin)
def ensure_nerimity(node_bin: str) -> bool:
"""Install the Nerimity SDK once into a shared node_modules. Returns True if usable."""
marker = SHARED_MODULES / "@nerimity" / "nerimity.js" / "package.json"
if marker.exists():
_log("nerimity.js already installed")
return True
DATA_DIR.mkdir(parents=True, exist_ok=True)
pkg = DATA_DIR / "package.json"
if not pkg.exists():
pkg.write_text('{"name":"bbuilder-host-deps","private":true}\n')
npm = Path(node_bin).parent / "npm"
npm_cmd = [str(npm)] if npm.exists() else ["npm"]
_log(f"installing {NERIMITY_PKG}")
try:
res = subprocess.run(
npm_cmd + ["install", "--no-audit", "--no-fund", NERIMITY_PKG],
cwd=str(DATA_DIR),
capture_output=True,
text=True,
timeout=300,
env={**os.environ, "PATH": f"{Path(node_bin).parent}:{os.environ.get('PATH','')}"},
)
except Exception as exc: # noqa: BLE001
_log(f"install failed: {exc}")
return False
if res.returncode != 0:
_log(f"npm install failed:\n{res.stderr[-1500:]}")
return False
_log("nerimity.js installed")
return marker.exists()
def version(node_bin: str) -> str:
try:
return subprocess.run([node_bin, "--version"], capture_output=True, text=True,
timeout=15).stdout.strip()
except Exception: # noqa: BLE001
return "unknown"
|