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