diff --git a/AGENTS.md b/AGENTS.md index 7832f70f8e..3272a1c3c8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -248,7 +248,7 @@ Ensure all pre-commit hooks pass by running `uv run pre-commit run -a`. A clean - **uv version pin:** Root `pyproject.toml` requires `uv>=0.9.14,<0.10.0`. Newer uv releases (e.g. 0.11.x) fail `uv sync` with a version mismatch. Install the pinned range before bootstrapping: `pip install 'uv>=0.9.14,<0.10.0'`. - **Native build deps:** `make bootstrap-python` builds `annoy` (via `nemoguardrails`). Install system headers once per VM image: `sudo apt-get install -y python3-dev build-essential`. - **Python bootstrap:** Run `make bootstrap-python` from repo root (creates `.venv`, runs `uv sync --frozen --all-packages`). See [SETUP.md](SETUP.md) for the full playbook. -- **Studio (optional):** `make bootstrap-studio` requires Node **22.23.x** and pnpm per `web/package.json` engines. The VM may ship an older Node (e.g. 22.14); API services still run without Studio assets. Upgrade Node then run `make bootstrap-studio` if you need `http://localhost:8080/studio/`. +- **Studio (optional):** `make bootstrap-studio` installs mise and resolves the Node.js/pnpm versions pinned in `mise.toml`, so a VM shipping an older Node doesn't need upgrading. API services still run without Studio assets. Pass `NMP_SKIP_MISE=1` to bootstrap against the toolchain already on PATH. ### Running the platform diff --git a/Makefile b/Makefile index e8433caea3..4821cac8d9 100644 --- a/Makefile +++ b/Makefile @@ -67,8 +67,8 @@ stainless: ## Run Stainless to generate the OpenAPI spec and sync it with the SD SDK_RELEASE_TIER=ga ./sdk/stainless.sh sync .PHONY: update-web-sdk -update-web-sdk: ## Regenerate the TypeScript web SDK (web/packages/sdk) from the OpenAPI spec via Orval - cd web && pnpm gen +update-web-sdk: verify-mise ## Regenerate the TypeScript web SDK (web/packages/sdk) from the OpenAPI spec via Orval + cd web && $(MISE_EXEC) pnpm gen .PHONY: update-sdk update-sdk: build-policy refresh-openapi stainless update-web-sdk update-cli ## Update the SDK by regenerating the OpenAPI spec and syncing it with Stainless @@ -195,18 +195,55 @@ bootstrap-python: ## Bootstrap Python dependencies. $(BOOTSTRAP_ACTIVATION_REMINDER); \ fi +# Set NMP_SKIP_MISE=1 to bootstrap against the node/pnpm already on PATH +# instead of the mise-managed ones (offline installs, nix shells, distro +# toolchains). web/package.json engines are still enforced either way. +NMP_SKIP_MISE ?= +MISE_VERSION ?= v2026.5.7 +MISE := $(shell command -v mise 2>/dev/null || echo $(HOME)/.local/bin/mise) +MISE_EXEC := $(if $(NMP_SKIP_MISE),,"$(MISE)" exec --) + +.PHONY: verify-mise +verify-mise: ## Install mise (if missing) and run `mise install` from mise.toml + @if [ -n "$(NMP_SKIP_MISE)" ]; then \ + echo "NMP_SKIP_MISE set, using node/pnpm from PATH"; \ + exit 0; \ + fi; \ + if [ ! -x "$(MISE)" ] && ! command -v mise >/dev/null 2>&1; then \ + curl -fsSL https://mise.run | MISE_VERSION=$(MISE_VERSION) sh; \ + fi; \ + if [ ! -x "$(MISE)" ] && ! command -v mise >/dev/null 2>&1; then \ + echo "mise not on PATH. Add $$HOME/.local/bin to PATH and re-run,"; \ + echo "or re-run with NMP_SKIP_MISE=1 to use your own node/pnpm."; \ + exit 1; \ + fi; \ + "$(MISE)" install --yes + +.PHONY: verify-pnpm +verify-pnpm: verify-mise ## Verify pnpm is available for Studio bootstrap + @$(MISE_EXEC) pnpm --version || { \ + echo "pnpm not found."; \ + if [ -n "$(NMP_SKIP_MISE)" ]; then \ + echo "NMP_SKIP_MISE is set, so pnpm has to come from your PATH."; \ + echo "Install pnpm, or re-run without NMP_SKIP_MISE to use the mise-managed one."; \ + else \ + echo "Run 'make verify-mise' to install the pinned toolchain."; \ + fi; \ + exit 1; \ + } + .PHONY: verify-node-version -verify-node-version: ## Verify pnpm and Node.js satisfy Studio's package engine +verify-node-version: verify-pnpm ## Verify pnpm and Node.js satisfy Studio's package engine @echo "~~~~~~" @echo "verifying Node.js version from web/package.json engines" - @script/verify-node-version.sh + @$(MISE_EXEC) script/verify-node-version.sh .PHONY: bootstrap-studio bootstrap-studio: verify-node-version ## Install web dependencies and build Studio assets for FastAPI @echo "~~~~~~" @echo "installing Studio web dependencies and building FastAPI assets" - cd web && CI=true pnpm install --frozen-lockfile - cd web && pnpm --filter nemo-studio-ui build:fastapi + cd web && CI=true $(MISE_EXEC) pnpm install --frozen-lockfile + cd web && $(MISE_EXEC) pnpm --filter nemo-studio-ui build:fastapi .PHONY: bootstrap-plugins bootstrap-plugins: .venv ## Install editable plugin packages not covered by the root uv workspace @@ -232,8 +269,7 @@ bootstrap: bootstrap-python ## Bootstrap the local dev environment, including St echo ""; \ echo "warning: optional Studio asset bootstrap did not complete."; \ echo "Studio will be unavailable at http://localhost:8080/studio/ until assets are built."; \ - echo "Install Node.js matching web/package.json with pnpm, then rerun:"; \ - echo " pnpm env use --global 22.23.2"; \ + echo "Check the output above, then rerun:"; \ echo " make bootstrap-studio"; \ fi @echo "bootstrap completed" diff --git a/SETUP.md b/SETUP.md index aa6dd27107..6b728dc041 100644 --- a/SETUP.md +++ b/SETUP.md @@ -95,6 +95,31 @@ nemo setup --auto --start-services --install-skills --deploy-agent `make clean` removes the venv; `make clean-python` is the venv-only variant. +### Node.js and pnpm + +`mise.toml` pins the Node.js and pnpm versions that satisfy `web/package.json` engines, and `make bootstrap-studio` installs mise on first run and invokes both through `mise exec --`. Nothing is written to your shell rc. + +That covers the `make` targets only. To run `pnpm` directly in `web/` — the Studio dev server, tests, lint — you need mise on your PATH first, since it installs to `~/.local/bin`: + +```bash +export PATH="$HOME/.local/bin:$PATH" +``` + +Then either prefix commands: + +```bash +mise exec -- pnpm dev +``` + +or activate mise once so every shell picks up the pinned versions: + +```bash +eval "$(mise activate bash)" # ~/.bashrc +eval "$(mise activate zsh)" # ~/.zshrc +``` + +Without one of those, a system or nvm-managed Node.js takes precedence and may not satisfy `engines`. To bootstrap against your own toolchain instead of mise, use `make bootstrap-studio NMP_SKIP_MISE=1`. + If `nemo setup` is too high-level for the task (e.g. debugging startup, custom service set, custom plugin install after bootstrap), use the manual sections below. ### Default model selection (under `--auto`) diff --git a/mise.toml b/mise.toml new file mode 100644 index 0000000000..724c599309 --- /dev/null +++ b/mise.toml @@ -0,0 +1,3 @@ +[tools] +node = "22.23.2" +pnpm = "10.34" diff --git a/script/verify-node-version.sh b/script/verify-node-version.sh index 21d074a8a4..e293e066b3 100755 --- a/script/verify-node-version.sh +++ b/script/verify-node-version.sh @@ -5,25 +5,20 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" WEB_DIR="$REPO_ROOT/web" -# --- pnpm availability --- - -if ! command -v pnpm >/dev/null 2>&1; then - if command -v corepack >/dev/null 2>&1; then - corepack enable pnpm - else - echo "pnpm is required for Studio bootstrap." - echo "Install pnpm and put it first on PATH." +# --- Toolchain availability --- + +for tool in node pnpm; do + if ! command -v "$tool" >/dev/null 2>&1; then + echo "$tool is not on PATH." + if [ -n "${NMP_SKIP_MISE:-}" ]; then + echo "NMP_SKIP_MISE is set, so $tool has to come from your PATH." + echo "Install it, or re-run without NMP_SKIP_MISE to use the mise-managed one." + else + echo "Run 'make verify-mise' to install the pinned toolchain." + fi exit 1 fi -fi - -# --- Node.js availability --- - -if ! command -v node >/dev/null 2>&1; then - echo "Node.js is required for Studio bootstrap." - echo "Install a matching local Node.js and put it first on PATH." - exit 1 -fi +done # --- Engine compatibility check --- diff --git a/web/AGENTS.md b/web/AGENTS.md index dc64049144..11b8c4ca09 100644 --- a/web/AGENTS.md +++ b/web/AGENTS.md @@ -32,6 +32,7 @@ Cursor/Claude skills for this monorepo live under **`web/.agents/skills/`** (for - Use **pnpm** exclusively — never npm or yarn - Run frontend commands from `web/`, not from repo root +- Node.js and pnpm come from mise (`mise.toml` at the repo root). Run `make verify-mise` from the repo root to install the pinned versions; mise lands in `~/.local/bin`, so use `~/.local/bin/mise exec -- ` if that directory isn't on PATH and mise isn't activated in the shell - Install dependencies: `pnpm add ` - Run scripts: `pnpm ` diff --git a/web/README.md b/web/README.md index 8d48fdb4d2..dc54d2336c 100644 --- a/web/README.md +++ b/web/README.md @@ -4,11 +4,26 @@ NeMo Studio is a UI built on the NeMo Platform, which is aimed at improving agen ## Getting Started -1. Install the latest [Node.js 22](https://nodejs.org/en/download) (LTS). -2. Install pnpm, install workspace deps, and copy `.env` files: +1. Get Node.js and pnpm satisfying the `engines` in `package.json` onto your PATH. Either let [mise](https://mise.jdx.dev/) manage them from the versions pinned in `mise.toml` at the repo root: + + ```bash + make verify-mise # from the repo root, installs mise + the pinned versions + ``` + + mise installs to `~/.local/bin`, so make sure that's on your PATH, then add the matching line for your shell to its startup file: + + ```bash + export PATH="$HOME/.local/bin:$PATH" + + eval "$(mise activate bash)" # ~/.bashrc + eval "$(mise activate zsh)" # ~/.zshrc + ``` + + or install Node.js and pnpm yourself. `make bootstrap-studio` and the other `make` targets use the mise-managed versions by default, whatever you pick here — pass `NMP_SKIP_MISE=1` to make them use your PATH instead. + +2. Install workspace deps and copy `.env` files, from `web/`: ```bash - npm install -g pnpm pnpm install cp packages/studio/env/.env.dev.local.sample packages/studio/env/.env.dev.local && \ cp packages/studio/env/.env.e2e packages/studio/env/.env.e2e.local @@ -16,7 +31,7 @@ NeMo Studio is a UI built on the NeMo Platform, which is aimed at improving agen ## Running Studio Locally -Run the following script from the root of the repo: +Run the following script from `web/`: ```bash pnpm dev