fix(cookbook): make the Dependencies recipe Run button pass validation (#6725) (#6726)

The recipe Run button sent repo_id "<backend> setup"; the space fails the
pip package-spec check, so every Run returned "Invalid pip package name".
It now sends "<backend>-setup".

The vLLM/SGLang recipes start with `uv pip install ... --torch-backend
auto`, but uv was not in the serve command allowlist. Allow uv only for
the `pip install` subcommand.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Grzegorz
2026-11-03 05:41:21 +00:00
committed by GitHub
co-authored by Claude Opus 5.5
parent f814018098
commit 631c05603c
3 changed files with 44 additions and 3 deletions
+6 -1
View File
@@ -728,8 +728,13 @@ def _check_serve_binary(seg: str) -> None:
if not tokens:
return
env_re = re.compile(r"^[A-Za-z_][A-Za-z0-9_]*=")
first = next((t for t in tokens if not env_re.match(t)), "")
idx = next((i for i, t in enumerate(tokens) if not env_re.match(t)), len(tokens))
first = tokens[idx] if idx < len(tokens) else ""
base = os.path.basename(first)
# The vLLM/SGLang Dependencies recipes install with `uv pip install …
# --torch-backend auto`. Allow uv for that subcommand only, not `uv run`.
if base == "uv" and tokens[idx + 1:idx + 3] == ["pip", "install"]:
return
if base not in _SERVE_CMD_ALLOWLIST:
raise HTTPException(
400,
+4 -2
View File
@@ -1762,7 +1762,9 @@ async function _fetchDependencies() {
envPrefix = 'eval "$(conda shell.bash hook)" && conda activate ' + _shellQuote(_envState.envPath);
}
const reqBody = {
repo_id: `${backend} setup`,
// The server validates repo_id as a pip package spec for pip
// installs, so it can't contain a space.
repo_id: `${backend}-setup`,
cmd: cmd,
remote_host: _envState.remoteHost || undefined,
ssh_port: _getPort(_envState.remoteHost) || undefined,
@@ -1780,7 +1782,7 @@ async function _fetchDependencies() {
uiModule.showToast('Run failed: ' + String(data.detail || data.error || `HTTP ${res.status}`).slice(0, 200));
return;
}
const payload = { repo_id: `${backend} setup`, _cmd: cmd, remote_host: _envState.remoteHost || '', _dep: true };
const payload = { repo_id: reqBody.repo_id, _cmd: cmd, remote_host: _envState.remoteHost || '', _dep: true };
_addTask(data.session_id, `${backend} setup`, 'download', payload);
uiModule.showToast(`Running ${backend} setup on ${targetHost}…`);
} catch (err) {
+34
View File
@@ -2,6 +2,7 @@ import json
import os
import subprocess
import sys
import re
from pathlib import Path
import pytest
@@ -1026,3 +1027,36 @@ def test_validate_serve_cmd_rejects_unrelated_subshell_pipelines():
]:
with pytest.raises(HTTPException):
_validate_serve_cmd(cmd)
def _dependency_recipe_pip_commands():
src = (Path(__file__).resolve().parents[1] / "static" / "js" / "cookbook-deps-recipes.js").read_text(encoding="utf-8")
return re.findall(r"pip:\s*\{\s*commands:\s*\['((?:[^'\\]|\\.)*)'\]\s*\}", src)
def test_validate_serve_cmd_accepts_single_line_dependency_recipes():
# The Dependencies recipe "Run" button posts these to /api/model/serve.
cmds = _dependency_recipe_pip_commands()
assert 'uv pip install -U vllm --torch-backend auto' in cmds
assert 'uv pip install -U "sglang[all]" --torch-backend auto' in cmds
for cmd in cmds:
assert _validate_serve_cmd(cmd) == cmd
@pytest.mark.parametrize("cmd", [
"uv run python -c 'print(1)'",
"uv tool install ruff",
"uv pip uninstall vllm",
"uv",
])
def test_validate_serve_cmd_allows_uv_only_for_pip_install(cmd):
with pytest.raises(HTTPException):
_validate_serve_cmd(cmd)
def test_dependency_recipe_run_sends_a_valid_pip_repo_id():
# A pip-install repo_id must match the server's package-spec regex; the old
# "<backend> setup" value had a space and every Run got "Invalid pip package name".
src = (Path(__file__).resolve().parents[1] / "static" / "js" / "cookbook.js").read_text(encoding="utf-8")
assert "repo_id: `${backend}-setup`," in src
assert "repo_id: `${backend} setup`" not in src