Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 0 additions & 14 deletions .github/workflows/studio-windows-api-smoke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -170,20 +170,6 @@ jobs:
fi
cygpath -w "$SHIM_DIR" >> "$GITHUB_PATH"

- name: Patch Studio venv with full typer / pydantic dep trees
# Belt-and-suspenders: install.ps1's --no-deps install of
# no-torch-runtime.txt drops typer's and pydantic's runtime
# deps unless explicitly pinned. Re-install the ones whose
# deps don't pull torch.
run: |
STUDIO_PY=~/.unsloth/studio/unsloth_studio/Scripts/python.exe
if [ ! -f "$STUDIO_PY" ]; then
echo "::error::Studio venv python not at $STUDIO_PY"
ls -la ~/.unsloth/studio/ || true
exit 1
fi
"$STUDIO_PY" -m pip install --upgrade typer pydantic huggingface_hub

- name: Install pyjwt for the JWT-expiry forge test
run: python -m pip install 'pyjwt>=2.6'

Expand Down
42 changes: 0 additions & 42 deletions .github/workflows/studio-windows-inference-smoke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -190,20 +190,6 @@ jobs:
fi
cygpath -w "$SHIM_DIR" >> "$GITHUB_PATH"

- name: Patch Studio venv with full typer / pydantic dep trees
# Belt-and-suspenders: install.ps1's --no-deps install of
# no-torch-runtime.txt drops typer's and pydantic's runtime
# deps unless explicitly pinned. Re-install the ones whose
# deps don't pull torch.
run: |
STUDIO_PY=~/.unsloth/studio/unsloth_studio/Scripts/python.exe
if [ ! -f "$STUDIO_PY" ]; then
echo "::error::Studio venv python not at $STUDIO_PY"
ls -la ~/.unsloth/studio/ || true
exit 1
fi
"$STUDIO_PY" -m pip install --upgrade typer pydantic huggingface_hub

- name: Install OpenAI + Anthropic Python SDKs
run: python -m pip install 'openai>=1.50' 'anthropic>=0.40'

Expand Down Expand Up @@ -543,20 +529,6 @@ jobs:
fi
cygpath -w "$SHIM_DIR" >> "$GITHUB_PATH"

- name: Patch Studio venv with full typer / pydantic dep trees
# Belt-and-suspenders: install.ps1's --no-deps install of
# no-torch-runtime.txt drops typer's and pydantic's runtime
# deps unless explicitly pinned. Re-install the ones whose
# deps don't pull torch.
run: |
STUDIO_PY=~/.unsloth/studio/unsloth_studio/Scripts/python.exe
if [ ! -f "$STUDIO_PY" ]; then
echo "::error::Studio venv python not at $STUDIO_PY"
ls -la ~/.unsloth/studio/ || true
exit 1
fi
"$STUDIO_PY" -m pip install --upgrade typer pydantic huggingface_hub

- name: Reset auth + boot Studio (API-only, default tool policy)
run: |
unsloth studio reset-password
Expand Down Expand Up @@ -982,20 +954,6 @@ jobs:
fi
cygpath -w "$SHIM_DIR" >> "$GITHUB_PATH"

- name: Patch Studio venv with full typer / pydantic dep trees
# Belt-and-suspenders: install.ps1's --no-deps install of
# no-torch-runtime.txt drops typer's and pydantic's runtime
# deps unless explicitly pinned. Re-install the ones whose
# deps don't pull torch.
run: |
STUDIO_PY=~/.unsloth/studio/unsloth_studio/Scripts/python.exe
if [ ! -f "$STUDIO_PY" ]; then
echo "::error::Studio venv python not at $STUDIO_PY"
ls -la ~/.unsloth/studio/ || true
exit 1
fi
"$STUDIO_PY" -m pip install --upgrade typer pydantic huggingface_hub

- name: Install OpenAI + Anthropic Python SDKs
run: python -m pip install 'openai>=1.50' 'anthropic>=0.40'

Expand Down
14 changes: 0 additions & 14 deletions .github/workflows/studio-windows-ui-smoke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -208,20 +208,6 @@ jobs:
cygpath -w "$SHIM_DIR" >> "$GITHUB_PATH"
echo "Added Studio shim dir to PATH: $(cygpath -w "$SHIM_DIR")"

- name: Patch Studio venv with full typer / pydantic dep trees
# Belt-and-suspenders: install.ps1's --no-deps install of
# no-torch-runtime.txt drops typer's and pydantic's runtime
# deps unless explicitly pinned. Re-install the ones whose
# deps don't pull torch.
run: |
STUDIO_PY=~/.unsloth/studio/unsloth_studio/Scripts/python.exe
if [ ! -f "$STUDIO_PY" ]; then
echo "::error::Studio venv python not at $STUDIO_PY"
ls -la ~/.unsloth/studio/ || true
exit 1
fi
"$STUDIO_PY" -m pip install --upgrade typer pydantic huggingface_hub

- name: Install Playwright + Chromium
# No --with-deps on Windows: that flag installs Linux apt
# packages. windows-latest ships the system frameworks
Expand Down
26 changes: 0 additions & 26 deletions .github/workflows/studio-windows-update-smoke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -176,32 +176,6 @@ jobs:
fi
cygpath -w "$SHIM_DIR" >> "$GITHUB_PATH"

- name: Patch Studio venv with full typer / pydantic dep trees
# install.ps1 runs `uv pip install --no-deps -r
# no-torch-runtime.txt` to keep torch out of transitive
# resolution from accelerate/peft/trl. That also drops
# typer's and pydantic's runtime deps unless they're
# explicitly pinned in no-torch-runtime.txt. We pin the
# known ones (click, shellingham, annotated-doc, rich,
# pydantic-core, annotated-types, typing-inspection, ...)
# but typer / pydantic minor versions can introduce new
# transitive deps that are NOT in our pin list.
#
# Belt-and-suspenders: re-install typer + pydantic +
# huggingface_hub WITH their deps into the Studio venv.
# `pip install --upgrade` only adds missing packages; it
# never down-shifts an installed version. Cannot pull
# torch (none of typer / pydantic / huggingface_hub depend
# on it).
run: |
STUDIO_PY=~/.unsloth/studio/unsloth_studio/Scripts/python.exe
if [ ! -f "$STUDIO_PY" ]; then
echo "::error::Studio venv python not at $STUDIO_PY"
ls -la ~/.unsloth/studio/ || true
exit 1
fi
"$STUDIO_PY" -m pip install --upgrade typer pydantic huggingface_hub

- name: First update should be a no-op (prebuilt already validated)
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand Down
15 changes: 15 additions & 0 deletions install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -1301,6 +1301,16 @@ shell.Run cmd, 0, False
# No-torch: install unsloth + unsloth-zoo with --no-deps, then
# runtime deps (typer, safetensors, transformers, etc.) with --no-deps.
$baseInstallExit = Invoke-InstallCommand { uv pip install --python $VenvPython --no-deps --reinstall-package unsloth --reinstall-package unsloth-zoo "unsloth>=2026.5.6" unsloth-zoo }
if ($baseInstallExit -eq 0) {
# Install pydantic WITH deps so pip pins pydantic-core to
# the exact version pydantic's metadata requires. The
# --no-deps install of no-torch-runtime.txt below would
# otherwise pick the latest of each independently and
# trip pydantic's _ensure_pydantic_core_version check.
# pydantic's deps (annotated-types, pydantic-core,
# typing-extensions, typing-inspection) are torch-free.
$baseInstallExit = Invoke-InstallCommand { uv pip install --python $VenvPython pydantic }
}
if ($baseInstallExit -eq 0) {
$NoTorchReq = Find-NoTorchRuntimeFile
if ($NoTorchReq) {
Expand Down Expand Up @@ -1347,6 +1357,11 @@ shell.Run cmd, 0, False
# No-torch: install unsloth + unsloth-zoo with --no-deps, then
# runtime deps (typer, safetensors, transformers, etc.) with --no-deps.
$baseInstallExit = Invoke-InstallCommand { uv pip install --python $VenvPython --no-deps --upgrade-package unsloth --upgrade-package unsloth-zoo "unsloth>=2026.5.6" unsloth-zoo }
if ($baseInstallExit -eq 0) {
# Install pydantic WITH deps so pip pins pydantic-core to
# the matching version (see migrated branch above).
$baseInstallExit = Invoke-InstallCommand { uv pip install --python $VenvPython pydantic }
}
if ($baseInstallExit -eq 0) {
$NoTorchReq = Find-NoTorchRuntimeFile
if ($NoTorchReq) {
Expand Down
13 changes: 13 additions & 0 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1866,6 +1866,15 @@ if [ "$_MIGRATED" = true ]; then
run_install_cmd "install unsloth (migrated no-torch)" uv pip install --python "$_VENV_PY" --no-deps \
--reinstall-package unsloth --reinstall-package unsloth-zoo \
"unsloth>=2026.5.6" unsloth-zoo
# Install pydantic WITH deps so pip pins pydantic-core to the
# exact version pydantic's own metadata requires. The --no-deps
# install below would otherwise pick the latest of each
# independently and trip pydantic's _ensure_pydantic_core_version
# check on the next import. pydantic's deps (annotated-types,
# pydantic-core, typing-extensions, typing-inspection) are
# torch-free, so this is safe on the no-torch path.
run_install_cmd "install pydantic (with deps for compatible core)" \
uv pip install --python "$_VENV_PY" pydantic
_NO_TORCH_RT="$(_find_no_torch_runtime)"
if [ -n "$_NO_TORCH_RT" ]; then
run_install_cmd "install no-torch runtime deps" uv pip install --python "$_VENV_PY" --no-deps -r "$_NO_TORCH_RT"
Expand Down Expand Up @@ -2042,6 +2051,10 @@ elif [ -n "$TORCH_INDEX_URL" ]; then
run_install_cmd "install unsloth (no-torch)" uv pip install --python "$_VENV_PY" --no-deps \
--upgrade-package unsloth --upgrade-package unsloth-zoo \
"unsloth>=2026.5.6" unsloth-zoo
# Install pydantic WITH deps so pip pins pydantic-core to the
# exact version pydantic requires (see migrated branch above).
run_install_cmd "install pydantic (with deps for compatible core)" \
uv pip install --python "$_VENV_PY" pydantic
_NO_TORCH_RT="$(_find_no_torch_runtime)"
if [ -n "$_NO_TORCH_RT" ]; then
run_install_cmd "install no-torch runtime deps" uv pip install --python "$_VENV_PY" --no-deps -r "$_NO_TORCH_RT"
Expand Down
21 changes: 13 additions & 8 deletions studio/backend/requirements/no-torch-runtime.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,19 @@ rich>=13.0
markdown-it-py>=3.0
mdurl>=0.1
pygments>=2.0
pydantic
# pydantic 2.x deps. With --no-deps, `import pydantic` blows up
# with `ModuleNotFoundError: 'pydantic_core'` (compiled Rust core,
# separate wheel), then `'annotated_types'`, then
# `'typing_inspection'` (used by pydantic 2.10+ for fields).
pydantic-core
annotated-types>=0.6
typing-inspection>=0.4
# pydantic is intentionally NOT installed via this --no-deps file.
# install.sh / install.ps1 / install_python_stack.py run a separate
# `pip install pydantic` (with deps) just before this file is
# applied, so pip resolves `pydantic-core` to the exact version
# pydantic's `_ensure_pydantic_core_version` check expects. Listing
# pydantic + pydantic-core unpinned here and resolving them under
# --no-deps used to pick the latest of each independently and trip
# `SystemError: pydantic-core 2.X.Y is incompatible with the current
# pydantic version` on the first import (Windows fresh-venv repro
# was the canonical case). pydantic's transitive deps
# (annotated-types, pydantic-core, typing-extensions,
# typing-inspection) are torch-free, so installing it WITH deps
# does not pull torch.
pyyaml
nest-asyncio

Expand Down
14 changes: 11 additions & 3 deletions studio/frontend/src/features/auth/components/auth-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,10 @@ export function AuthForm({ mode }: AuthFormProps): ReactElement | null {
const hasBootstrapPassword = Boolean(window.__UNSLOTH_BOOTSTRAP__?.password);
const invalidChangePasswordForm =
!isLoginMode &&
(newPassword.length < 8 || newPassword !== confirmPassword || currentPassword === newPassword);
(currentPassword.length < 8 ||
newPassword.length < 8 ||
newPassword !== confirmPassword ||
currentPassword === newPassword);
const showPasswordMismatchWarning =
!isLoginMode &&
newPassword.length > 0 &&
Expand All @@ -206,8 +209,13 @@ export function AuthForm({ mode }: AuthFormProps): ReactElement | null {
setError(null);

if (!isLoginMode) {
if (!currentPassword) {
setError("Unable to initialize setup. Reload the page and try again.");
// Mirror the disable gate: Enter / autofill can bypass the button.
if (currentPassword.length < 8) {
setError(
currentPassword
? "Current password must be at least 8 characters."
: "Unable to initialize setup. Reload the page and try again.",
);
return;
}
if (newPassword.length < 8) {
Expand Down
13 changes: 13 additions & 0 deletions studio/install_llama_prebuilt.py
Original file line number Diff line number Diff line change
Expand Up @@ -3833,6 +3833,19 @@ def runtime_patterns_for_choice(choice: AssetChoice) -> list[str]:
"llama-quantize",
"libllama-common.so*",
"libllama.so*",
# Upstream llama.cpp split the per-binary entry code into
# paired ``libllama-<binary>-impl.so`` shared libraries
# around release b9261. ``llama-server`` and
# ``llama-quantize`` are NEEDED-linked against
# ``libllama-server-impl.so`` / ``libllama-quantize-impl.so``
# respectively, with RUNPATH ``$ORIGIN``. Without copying
# the impl ``.so`` files alongside the binaries, ldd
# reports them missing, preflight rejects the install, and
# the installer falls back to a source build on a fresh
# Linux install. Glob the whole family so future bundles
# that split additional binaries (e.g. ``llama-cli``,
# ``llama-bench``) keep working.
"libllama-*-impl.so*",
"libggml.so*",
"libggml-base.so*",
"libmtmd.so*",
Expand Down
21 changes: 21 additions & 0 deletions studio/install_python_stack.py
Original file line number Diff line number Diff line change
Expand Up @@ -979,6 +979,27 @@ def install_python_stack() -> int:
package_name,
"unsloth-zoo",
)
# Pydantic ships its core as a separate compiled wheel
# (pydantic-core), and pydantic's ``_ensure_pydantic_core_version``
# checks the installed core matches the exact version pinned in
# its own metadata. With ``--no-deps`` plus an unpinned
# ``pydantic`` / ``pydantic-core`` pair in no-torch-runtime.txt,
# pip resolved each to the newest available version and the two
# drifted (pydantic 2.13.4 pins pydantic-core==2.46.4 today, but
# pydantic-core 2.47.0 was the latest). On a fresh Windows venv
# the next ``import pydantic`` raised ``SystemError: ...
# incompatible with the current pydantic version``.
#
# Resolve them WITH deps in a focused pip call so pip picks a
# compatible pair. pydantic's own deps are
# ``annotated-types``, ``pydantic-core``, ``typing-extensions``,
# ``typing-inspection`` -- none of which transitively pull
# torch, so this is safe for the no-torch path.
pip_install(
"Installing pydantic (with deps for compatible core)",
"--no-cache-dir",
"pydantic",
)
pip_install(
"Installing no-torch runtime deps",
"--no-cache-dir",
Expand Down
8 changes: 8 additions & 0 deletions tests/studio/install/test_rocm_support.py
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,14 @@ def test_linux_cpu_patterns(self):
patterns = runtime_patterns_for_choice(choice)
assert "llama-server" in patterns
assert "llama-quantize" in patterns
# Upstream split entry code into ``libllama-<binary>-impl.so``
# shared libraries (b9261+). llama-server and llama-quantize
# are NEEDED-linked against ``libllama-server-impl.so`` and
# ``libllama-quantize-impl.so`` respectively with RUNPATH
# ``$ORIGIN``, so the prebuilt overlay MUST copy them
# alongside the binaries or ldd reports them missing and
# preflight forces a source-build fallback.
assert "libllama-*-impl.so*" in patterns

def test_linux_cuda_patterns(self):
choice = AssetChoice(
Expand Down
Loading