comments: condense multiline blocks added by this PR
Across the 27-cycle review process, comments accumulated as multiline blocks explaining each fix's history (cycle numbers, prior bugs, reviewer rationale). Compress every block to 1-2 lines that capture just the WHY, dropping cycle references and history that belongs in the PR description / commit log instead. Net: 268 deletions / 124 insertions (-144 lines) of comments only. Behavior unchanged. Verified: bash -n, pwsh parser, python ast.parse, cargo check all pass.
This commit is contained in:
parent
fe309d2192
commit
b7fa2c8718
15 changed files with 124 additions and 268 deletions
91
install.ps1
91
install.ps1
|
|
@ -70,10 +70,8 @@ function Install-UnslothStudio {
|
|||
# Resolve install destinations. Priority: env vars, then USERPROFILE-redirect, then default.
|
||||
$envOverride = if ($env:UNSLOTH_STUDIO_HOME) { $env:UNSLOTH_STUDIO_HOME } elseif ($env:STUDIO_HOME) { $env:STUDIO_HOME } else { $null }
|
||||
|
||||
# Custom Studio roots are not supported in Tauri-mode installs because
|
||||
# the desktop app still resolves the legacy %USERPROFILE%\.unsloth\studio
|
||||
# path. Pass through when the override resolves to that legacy default
|
||||
# (the desktop app already uses it); fail fast otherwise.
|
||||
# Custom Studio roots are not supported with --tauri (desktop app still
|
||||
# resolves %USERPROFILE%\.unsloth\studio). Pass through if override == legacy.
|
||||
if ($TauriMode -and $envOverride) {
|
||||
$_tauriOverride = $envOverride
|
||||
if ($_tauriOverride -eq "~" -or $_tauriOverride -like "~/*" -or $_tauriOverride -like "~\*") {
|
||||
|
|
@ -86,8 +84,7 @@ function Install-UnslothStudio {
|
|||
try {
|
||||
$_legacyTauriRoot = [System.IO.Path]::GetFullPath($_legacyTauriRoot)
|
||||
} catch {}
|
||||
# Strip trailing separators so a legacy override with a trailing
|
||||
# backslash or slash still matches the legacy root.
|
||||
# Strip trailing separators so ".../studio\" matches ".../studio".
|
||||
$_trimSeps = @(
|
||||
[System.IO.Path]::DirectorySeparatorChar,
|
||||
[System.IO.Path]::AltDirectorySeparatorChar
|
||||
|
|
@ -106,35 +103,29 @@ function Install-UnslothStudio {
|
|||
$defaultProfile = $null
|
||||
try { $defaultProfile = [Environment]::GetFolderPath("UserProfile") } catch {}
|
||||
|
||||
# Default DataDir uses LOCALAPPDATA. Guard the lookup: in service / CI
|
||||
# contexts LOCALAPPDATA may be unset, and Join-Path under
|
||||
# $ErrorActionPreference='Stop' would otherwise abort the installer.
|
||||
# LOCALAPPDATA may be unset in service / CI contexts; Join-Path would abort
|
||||
# under ErrorActionPreference=Stop without this guard.
|
||||
$defaultDataDir = if ($env:LOCALAPPDATA -and -not [string]::IsNullOrWhiteSpace($env:LOCALAPPDATA)) {
|
||||
Join-Path $env:LOCALAPPDATA "Unsloth Studio"
|
||||
} else { $null }
|
||||
|
||||
if ($envOverride) {
|
||||
# Expand a leading '~' to $HOME / $env:USERPROFILE because env-var
|
||||
# values are not subject to tilde expansion in any shell.
|
||||
# Tilde expansion: env vars aren't subject to it when quoted on assignment.
|
||||
if ($envOverride -eq "~" -or $envOverride -like "~/*" -or $envOverride -like "~\*") {
|
||||
$envOverride = (Join-Path $env:USERPROFILE $envOverride.Substring(1).TrimStart('/','\'))
|
||||
}
|
||||
try {
|
||||
# New-Item has no -LiteralPath in PowerShell 5.1 and -Path treats
|
||||
# square brackets as wildcards. Use the .NET API so a custom root
|
||||
# like C:\workspaces\studio[abc] is handled literally.
|
||||
# .NET API: New-Item -Path treats brackets as wildcards and has no
|
||||
# -LiteralPath in PS 5.1, so a root like C:\studio[abc] would fail.
|
||||
[System.IO.Directory]::CreateDirectory($envOverride) | Out-Null
|
||||
$StudioHome = (Resolve-Path -LiteralPath $envOverride).Path
|
||||
} catch {
|
||||
Write-Host "ERROR: STUDIO_HOME=$envOverride cannot be created or accessed." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
# Default ToString() form already produces a unique GUID string.
|
||||
$probe = Join-Path $StudioHome (".unsloth-write-probe-" + [guid]::NewGuid())
|
||||
try {
|
||||
# WriteAllText is literal-path safe and closes the file handle
|
||||
# before the Remove-Item below; New-Item -Path would fail on
|
||||
# bracketed roots (wildcard expansion) just like the dir case.
|
||||
# WriteAllText: literal-path safe + closes handle so Remove-Item works.
|
||||
[System.IO.File]::WriteAllText($probe, "")
|
||||
Remove-Item -LiteralPath $probe -Force -ErrorAction SilentlyContinue
|
||||
} catch {
|
||||
|
|
@ -415,8 +406,7 @@ function Install-UnslothStudio {
|
|||
# This prevents runtime variable expansion for paths containing '$'.
|
||||
$SingleQuotedExePath = $UnslothExePath -replace "'", "''"
|
||||
|
||||
# $StudioDataDir was resolved at install start (default = LOCALAPPDATA\Unsloth Studio,
|
||||
# or $StudioHome\share when UNSLOTH_STUDIO_HOME / STUDIO_HOME is set).
|
||||
# $StudioDataDir = LOCALAPPDATA\Unsloth Studio, or $StudioHome\share in env-mode.
|
||||
if (-not $StudioDataDir -or [string]::IsNullOrWhiteSpace($StudioDataDir)) {
|
||||
substep "DataDir path unavailable; skipped shortcut creation" "Yellow"
|
||||
return
|
||||
|
|
@ -457,18 +447,14 @@ function Install-UnslothStudio {
|
|||
[System.IO.Directory]::CreateDirectory($appDir) | Out-Null
|
||||
}
|
||||
|
||||
# Persist UNSLOTH_STUDIO_HOME inside the generated launcher when
|
||||
# in env-override mode. Lets fresh shells launch Studio without
|
||||
# the user re-exporting the env var. Default installs get an
|
||||
# empty string here so behavior matches today exactly.
|
||||
# Env-mode: persist UNSLOTH_STUDIO_HOME (and llama path) in the
|
||||
# launcher so fresh shells don't need to re-export. Default installs
|
||||
# get an empty prefix so behavior matches pre-PR exactly.
|
||||
$studioHomeExport = if ($StudioRedirectMode -eq 'env') {
|
||||
# Mirror setup.ps1: when an env override happens to equal the
|
||||
# legacy default, llama.cpp still lives at ~/.unsloth/llama.cpp.
|
||||
# Keep the persisted UNSLOTH_LLAMA_CPP_PATH consistent with that.
|
||||
# When override == legacy default, llama.cpp stays at
|
||||
# ~/.unsloth/llama.cpp (one shared build). Canonicalize the
|
||||
# legacy side so the comparison survives path normalization.
|
||||
$_legacyStudio = Join-Path $env:USERPROFILE ".unsloth\studio"
|
||||
# Canonicalize the legacy side (when it exists) to match the
|
||||
# resolved $StudioHome from the env-override path. This keeps
|
||||
# the legacy-equality check stable across path normalization.
|
||||
if (Test-Path -LiteralPath $_legacyStudio -PathType Container) {
|
||||
$_legacyStudio = (Resolve-Path -LiteralPath $_legacyStudio).Path
|
||||
}
|
||||
|
|
@ -479,9 +465,7 @@ function Install-UnslothStudio {
|
|||
}
|
||||
$_sq = $StudioHome -replace "'", "''"
|
||||
$_llama = $_llamaPath -replace "'", "''"
|
||||
# UNSLOTH_LLAMA_CPP_PATH is a pre-existing user-controlled
|
||||
# llama.cpp directory override. Only default it when the
|
||||
# caller has not already set one in their environment.
|
||||
# UNSLOTH_LLAMA_CPP_PATH is a pre-existing user override; only default if unset.
|
||||
"`$env:UNSLOTH_STUDIO_HOME = '$_sq'`nif (-not `$env:UNSLOTH_LLAMA_CPP_PATH) {`n `$env:UNSLOTH_LLAMA_CPP_PATH = '$_llama'`n}`n"
|
||||
} else { "" }
|
||||
|
||||
|
|
@ -707,10 +691,8 @@ shell.Run cmd, 0, False
|
|||
}
|
||||
}
|
||||
|
||||
# Env-override installs are workspace-scoped: skip persistent
|
||||
# Desktop / Start Menu .lnk shortcuts that would point at a
|
||||
# path the user may later delete. The launcher scripts and
|
||||
# icon written above ARE kept regardless of mode.
|
||||
# Env-mode: skip persistent Desktop / Start Menu .lnk shortcuts
|
||||
# that may point at a deleted workspace; launcher + icon stay.
|
||||
if ($StudioRedirectMode -eq 'env') {
|
||||
substep "wrote launcher at $launcherPs1 (persistent shortcuts skipped in env-override mode)"
|
||||
return
|
||||
|
|
@ -909,8 +891,7 @@ shell.Run cmd, 0, False
|
|||
# a version string back to a conda interpreter.
|
||||
Write-TauriLog "STEP" "Creating virtual environment"
|
||||
if (-not (Test-Path -LiteralPath $StudioHome)) {
|
||||
# New-Item has no -LiteralPath parameter; use the .NET API to honor
|
||||
# bracket characters in custom Studio roots.
|
||||
# .NET API: New-Item -Path treats brackets as wildcards.
|
||||
[System.IO.Directory]::CreateDirectory($StudioHome) | Out-Null
|
||||
}
|
||||
|
||||
|
|
@ -946,11 +927,9 @@ shell.Run cmd, 0, False
|
|||
$StudioRedirectMode -ne 'env' `
|
||||
-and (Test-Path -LiteralPath (Join-Path $env:USERPROFILE "unsloth_studio\Scripts\python.exe"))
|
||||
) {
|
||||
# CWD-relative venv from old install.ps1 -- migrate to absolute path.
|
||||
# Skip in env-override mode: workspace-scoped installs must not
|
||||
# move the user's pre-existing default-install venv away from
|
||||
# %USERPROFILE%, which would break their legacy default install
|
||||
# and contaminate the workspace root.
|
||||
# CWD-relative venv from old install.ps1 -> migrate to absolute path.
|
||||
# Skip in env-mode so we don't relocate the default-install venv into
|
||||
# the workspace root.
|
||||
$CwdVenv = Join-Path $env:USERPROFILE "unsloth_studio"
|
||||
substep "found CWD-relative Studio environment, migrating to $VenvDir..."
|
||||
Move-Item -LiteralPath $CwdVenv -Destination $VenvDir -Force
|
||||
|
|
@ -1225,9 +1204,8 @@ shell.Run cmd, 0, False
|
|||
# Use 'studio setup' (not 'studio update') because 'update' pops
|
||||
# SKIP_STUDIO_BASE, which would cause redundant package reinstallation
|
||||
# and bypass the fast-path version check from PR #4667.
|
||||
# Only propagate UNSLOTH_STUDIO_HOME for actual env-override installs;
|
||||
# otherwise default-install setups would mistakenly take the env path
|
||||
# (placing llama.cpp under $StudioHome\llama.cpp instead of legacy).
|
||||
# Propagate UNSLOTH_STUDIO_HOME only for env-override installs; otherwise
|
||||
# an inherited value would put llama.cpp in the wrong place.
|
||||
$previousUnslothStudioHome = $env:UNSLOTH_STUDIO_HOME
|
||||
$hadPreviousUnslothStudioHome = ($null -ne $previousUnslothStudioHome)
|
||||
if ($StudioRedirectMode -eq 'env') {
|
||||
|
|
@ -1314,10 +1292,8 @@ shell.Run cmd, 0, False
|
|||
Write-Host " Launch unsloth studio directly via '$UnslothExe' until the next successful install." -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
# Only add to PATH when the launcher actually exists on disk.
|
||||
# Skip persistent registry PATH modification when env-override is active:
|
||||
# the workspace path may be deleted, and we should not pollute the user's
|
||||
# persistent PATH with it. Caller is expected to add $StudioHome\bin manually.
|
||||
# Add to PATH only when launcher exists. Env-mode: session-only export,
|
||||
# no registry change (workspace path may be deleted later).
|
||||
$pathAdded = $false
|
||||
if (Test-Path -LiteralPath $ShimExe) {
|
||||
if ($StudioRedirectMode -eq 'env') {
|
||||
|
|
@ -1332,9 +1308,8 @@ shell.Run cmd, 0, False
|
|||
}
|
||||
Refresh-SessionPath # sync current session with registry
|
||||
|
||||
# Re-prepend the env-override shim AFTER Refresh-SessionPath, otherwise
|
||||
# a previously-installed legacy User PATH entry would win precedence
|
||||
# (Refresh rebuilds Path as Machine > User > current $env:Path).
|
||||
# Re-prepend env-mode shim AFTER Refresh-SessionPath; otherwise a legacy
|
||||
# User PATH entry (Machine > User > current $env:Path) would win.
|
||||
if ($StudioRedirectMode -eq 'env' -and (Test-Path -LiteralPath $ShimExe)) {
|
||||
$env:Path = "$ShimDir;$env:Path"
|
||||
}
|
||||
|
|
@ -1345,9 +1320,7 @@ shell.Run cmd, 0, False
|
|||
return
|
||||
}
|
||||
|
||||
# New-StudioShortcuts itself gates the persistent Desktop / Start
|
||||
# Menu .lnk shortcuts based on $StudioRedirectMode; the launcher
|
||||
# script and icon are always written so env-mode shims still resolve.
|
||||
# New-StudioShortcuts gates the .lnk shortcuts on env-mode internally.
|
||||
New-StudioShortcuts -UnslothExePath $UnslothExe
|
||||
|
||||
# Launch studio automatically in interactive terminals;
|
||||
|
|
@ -1358,9 +1331,7 @@ shell.Run cmd, 0, False
|
|||
} else {
|
||||
step "launch" "manual commands:"
|
||||
if ($StudioRedirectMode -eq 'env') {
|
||||
# Env-override mode skips persistent registry PATH update, so
|
||||
# `unsloth` may not resolve in a fresh shell. Print the
|
||||
# absolute shim path so callers can launch directly.
|
||||
# Env-mode skips registry PATH; print the absolute shim path.
|
||||
$_shim = Join-Path $StudioHome "bin\unsloth.exe"
|
||||
substep "& `"$_shim`" studio -H 0.0.0.0 -p 8888"
|
||||
substep "or activate env first:"
|
||||
|
|
|
|||
138
install.sh
138
install.sh
|
|
@ -71,13 +71,8 @@ if [ "$_VERBOSE" = true ]; then
|
|||
export UNSLOTH_VERBOSE=1
|
||||
fi
|
||||
|
||||
# Custom Studio roots are not supported in Tauri-mode installs because the
|
||||
# desktop app still resolves the legacy ~/.unsloth/studio path. Producing
|
||||
# a custom-root --tauri install would yield a desktop app that cannot
|
||||
# locate the freshly installed binary or auth secret. Fail fast for real
|
||||
# custom roots; pass through when the override resolves to the legacy
|
||||
# default ($HOME/.unsloth/studio), since that is exactly what the desktop
|
||||
# app already uses.
|
||||
# Custom Studio roots are not supported with --tauri (desktop app still
|
||||
# resolves ~/.unsloth/studio). Pass through if the override == legacy default.
|
||||
if [ "$TAURI_MODE" = true ]; then
|
||||
_tauri_override="${UNSLOTH_STUDIO_HOME:-${STUDIO_HOME:-}}"
|
||||
if [ -n "$_tauri_override" ]; then
|
||||
|
|
@ -85,25 +80,20 @@ if [ "$TAURI_MODE" = true ]; then
|
|||
"~") _tauri_override="$HOME" ;;
|
||||
"~/"*) _tauri_override="$HOME/${_tauri_override#'~/'}" ;;
|
||||
esac
|
||||
# Resolve symlinks/relative paths if the dir exists, else use as-is.
|
||||
# CDPATH= prevents `cd` from echoing the resolved path on stdout when
|
||||
# the user has CDPATH set in their environment. -P resolves symlinks.
|
||||
# Canonicalize both sides (CDPATH=, -P) so a CDPATH-set env or
|
||||
# symlinked $HOME doesn't break the legacy-equality comparison.
|
||||
if [ -d "$_tauri_override" ]; then
|
||||
_tauri_override_abs=$(CDPATH= cd -P -- "$_tauri_override" 2>/dev/null && pwd -P) \
|
||||
|| _tauri_override_abs="$_tauri_override"
|
||||
else
|
||||
_tauri_override_abs="$_tauri_override"
|
||||
fi
|
||||
# Strip trailing separators so a legacy override with a trailing
|
||||
# slash (".../studio/") still matches the legacy root (".../studio").
|
||||
# Strip trailing separators so ".../studio/" matches ".../studio".
|
||||
while [ "$_tauri_override_abs" != "/" ] \
|
||||
&& [ "${_tauri_override_abs%/}" != "$_tauri_override_abs" ]; do
|
||||
_tauri_override_abs=${_tauri_override_abs%/}
|
||||
done
|
||||
_tauri_legacy_root="$HOME/.unsloth/studio"
|
||||
# Apply the same physical-path canonicalization to the legacy root
|
||||
# so a symlinked $HOME (e.g. /home/alice -> /u/alice) doesn't make
|
||||
# the comparison fail when both sides point at the same directory.
|
||||
if [ -d "$_tauri_legacy_root" ]; then
|
||||
_tauri_legacy_root=$(CDPATH= cd -P -- "$_tauri_legacy_root" 2>/dev/null && pwd -P) \
|
||||
|| _tauri_legacy_root="$HOME/.unsloth/studio"
|
||||
|
|
@ -220,14 +210,11 @@ tauri_log() {
|
|||
|
||||
PYTHON_VERSION="" # resolved after platform detection
|
||||
|
||||
# Resolve install destinations. Priority: env vars, then HOME-redirect, then default.
|
||||
# Best-effort HOME-redirect detection: skipped on hosts without getent/dscl.
|
||||
# Resolve install destinations: env override, HOME-redirect (best-effort
|
||||
# via getent/dscl), or default.
|
||||
_resolve_studio_destinations() {
|
||||
_override="${UNSLOTH_STUDIO_HOME:-${STUDIO_HOME:-}}"
|
||||
# Expand leading ~ / ~/path to $HOME because env vars are not subject to
|
||||
# tilde expansion when set with quotes around the value. Quote the
|
||||
# ~/ inside the prefix-removal so the shell does not tilde-expand it
|
||||
# back to $HOME/ before matching.
|
||||
# Tilde expansion: env vars are not subject to it when quoted on assignment.
|
||||
case "$_override" in
|
||||
"~") _override="$HOME" ;;
|
||||
"~/"*) _override="$HOME/${_override#'~/'}" ;;
|
||||
|
|
@ -235,8 +222,6 @@ _resolve_studio_destinations() {
|
|||
if [ -n "$_override" ]; then
|
||||
mkdir -p -- "$_override" 2>/dev/null || { echo "ERROR: STUDIO_HOME=$_override cannot be created." >&2; exit 1; }
|
||||
[ -w "$_override" ] || { echo "ERROR: STUDIO_HOME=$_override is not writable." >&2; exit 1; }
|
||||
# CDPATH= prevents `cd` from echoing a CDPATH-prefixed path on stdout
|
||||
# if the user has CDPATH set; -P / pwd -P canonicalizes symlinks.
|
||||
STUDIO_HOME="$(CDPATH= cd -P -- "$_override" && pwd -P)" || exit 1
|
||||
DATA_DIR="$STUDIO_HOME/share"
|
||||
_LOCAL_BIN="$STUDIO_HOME/bin"
|
||||
|
|
@ -381,10 +366,8 @@ create_studio_shortcuts() {
|
|||
mkdir -p "$_css_data_dir"
|
||||
|
||||
# ── Write launcher script ──
|
||||
# Heredoc is single-quoted (no $-expansion at write time). The
|
||||
# @@DATA_DIR@@ placeholder below is substituted via sed after the
|
||||
# heredoc is written so the runtime launcher reads studio.conf
|
||||
# from the same DATA_DIR install.sh resolved.
|
||||
# Single-quoted heredoc; @@DATA_DIR@@ is substituted via sed below so
|
||||
# the runtime launcher reads studio.conf from the resolved DATA_DIR.
|
||||
cat > "$_css_launcher" << 'LAUNCHER_EOF'
|
||||
#!/usr/bin/env bash
|
||||
# Unsloth Studio Launcher
|
||||
|
|
@ -638,33 +621,20 @@ else
|
|||
fi
|
||||
LAUNCHER_EOF
|
||||
|
||||
# Substitute @@DATA_DIR@@. Default and HOME-redirect installs keep the
|
||||
# legacy runtime form (DATA_DIR="$HOME/.local/share/unsloth") so a later
|
||||
# shell with a different $HOME still resolves DATA_DIR correctly --
|
||||
# byte-identical to pre-PR. Only env-mode installs bake the resolved
|
||||
# absolute path because their root is fixed at install time.
|
||||
# Portable in-place edit: redirect to tempfile, then mv. Avoids the
|
||||
# GNU-vs-BSD-vs-BusyBox `sed -i` divergence (per Gemini review feedback).
|
||||
# Default / HOME-redirect installs replace the placeholder line with the
|
||||
# legacy literal (DATA_DIR="$HOME/.local/share/unsloth") so a later shell
|
||||
# with a different $HOME still resolves correctly -- byte-identical to
|
||||
# pre-PR. Env-mode installs bake the resolved absolute path because their
|
||||
# root is fixed at install time.
|
||||
if [ "$_STUDIO_HOME_REDIRECT" = "env" ]; then
|
||||
# Two-stage escape so path metacharacters survive sed and shell
|
||||
# single-quoted embedding. Verified end-to-end with apostrophes,
|
||||
# spaces, &, |, $; do not "simplify" to fewer/more backslashes.
|
||||
# 1) ' -> '\'' for safe single-quote shell embedding.
|
||||
# The shell pattern "s/'/'\\''/g" passes "s/'/'\''/g" to sed
|
||||
# (\\ -> \). sed's replacement '\'' contains a literal
|
||||
# backslash-quote-quote, producing the canonical close-quote /
|
||||
# escaped-quote / open-quote sequence on output. Result:
|
||||
# `a b's` -> `a b'\''s`.
|
||||
# 2) For the value to land inside a sed s|...|VALUE|g call below,
|
||||
# escape \, &, and | (the chosen delimiter) so they survive sed
|
||||
# replacement. Result of stage 2: `a b'\''s` -> `a b'\\''s`.
|
||||
# Two-stage escape: (1) `'` -> `'\''` for shell single-quote embedding,
|
||||
# (2) backslash/&/| escape so the value survives the s|...|VALUE| sed
|
||||
# below. Verified end-to-end with apostrophes, spaces, &, |, $.
|
||||
_sq_escaped=$(printf '%s' "$DATA_DIR" | sed "s/'/'\\\\''/g")
|
||||
_sed_safe=$(printf '%s' "$_sq_escaped" | sed 's/[\\&|]/\\&/g')
|
||||
sed "s|@@DATA_DIR@@|$_sed_safe|g" "$_css_launcher" > "$_css_launcher.tmp" \
|
||||
&& mv "$_css_launcher.tmp" "$_css_launcher"
|
||||
else
|
||||
# Replace the placeholder line entirely with the legacy literal
|
||||
# so the launcher reads $HOME at runtime, not install time.
|
||||
sed "s|DATA_DIR='@@DATA_DIR@@'|DATA_DIR=\"\$HOME/.local/share/unsloth\"|" \
|
||||
"$_css_launcher" > "$_css_launcher.tmp" \
|
||||
&& mv "$_css_launcher.tmp" "$_css_launcher"
|
||||
|
|
@ -672,30 +642,16 @@ LAUNCHER_EOF
|
|||
|
||||
chmod +x "$_css_launcher"
|
||||
|
||||
# Write the exe path to a separate conf file sourced by the launcher.
|
||||
# Single-quote wrapping with the standard `'\''` escape (shell pattern
|
||||
# "s/'/'\\''/g" -> sed "s/'/'\''/g"; replacement `'\''` produces
|
||||
# close-quote, backslash-quote, open-quote on output). No sed templating
|
||||
# is applied to studio.conf, so no second-stage backslash/&/| escaping
|
||||
# is needed here.
|
||||
# studio.conf: exe path + (env-mode only) persisted env vars so fresh
|
||||
# shells launch the right install without re-exporting.
|
||||
_css_quoted_exe=$(printf '%s' "$_css_exe" | sed "s/'/'\\\\''/g")
|
||||
{
|
||||
printf '%s\n' "UNSLOTH_EXE='$_css_quoted_exe'"
|
||||
# Persist UNSLOTH_STUDIO_HOME for env-override installs so the launcher,
|
||||
# CLI, and backend pick up the same root in fresh shells where the user
|
||||
# did not re-export the env var. Also persist UNSLOTH_LLAMA_CPP_PATH so
|
||||
# unsloth-zoo's import-time LLAMA_CPP_DEFAULT_DIR binding finds the
|
||||
# custom-root build. Default installs do NOT get these lines so the
|
||||
# legacy ~/.unsloth/studio + ~/.unsloth/llama.cpp resolution stands.
|
||||
if [ "$_STUDIO_HOME_REDIRECT" = "env" ]; then
|
||||
# Mirror setup.sh's legacy-equality check: when an env override
|
||||
# happens to point at the legacy default, llama.cpp still lives
|
||||
# at ~/.unsloth/llama.cpp (one shared build across legacy
|
||||
# installs) -- keep UNSLOTH_LLAMA_CPP_PATH consistent with that.
|
||||
# $STUDIO_HOME is canonicalized (cycle 24) but $HOME/.unsloth/studio
|
||||
# is still logical. Canonicalize the legacy side too so a symlinked
|
||||
# $HOME doesn't make the comparison fail when both point at the
|
||||
# same dir.
|
||||
# When an override resolves to the legacy default, llama.cpp
|
||||
# still lives at ~/.unsloth/llama.cpp (one shared build).
|
||||
# Canonicalize the legacy side so a symlinked $HOME doesn't
|
||||
# break the comparison.
|
||||
_css_legacy_studio="$HOME/.unsloth/studio"
|
||||
if [ -d "$_css_legacy_studio" ]; then
|
||||
_css_legacy_studio=$(CDPATH= cd -P -- "$_css_legacy_studio" 2>/dev/null && pwd -P) \
|
||||
|
|
@ -709,9 +665,8 @@ LAUNCHER_EOF
|
|||
_css_quoted_home=$(printf '%s' "$STUDIO_HOME" | sed "s/'/'\\\\''/g")
|
||||
_css_quoted_llama=$(printf '%s' "$_css_llama_path" | sed "s/'/'\\\\''/g")
|
||||
printf '%s\n' "export UNSLOTH_STUDIO_HOME='$_css_quoted_home'"
|
||||
# UNSLOTH_LLAMA_CPP_PATH is a pre-existing custom-llama.cpp-dir
|
||||
# override the Python backend / unsloth-zoo respect. Only default
|
||||
# it when the caller has not already set one in their shell.
|
||||
# UNSLOTH_LLAMA_CPP_PATH is a pre-existing user-controlled
|
||||
# llama.cpp dir override; only default it if unset.
|
||||
printf '%s\n' 'if [ -z "${UNSLOTH_LLAMA_CPP_PATH:-}" ]; then'
|
||||
printf '%s\n' " export UNSLOTH_LLAMA_CPP_PATH='$_css_quoted_llama'"
|
||||
printf '%s\n' 'fi'
|
||||
|
|
@ -762,11 +717,9 @@ LAUNCHER_EOF
|
|||
fi
|
||||
|
||||
# ── Platform-specific shortcuts ──
|
||||
# Env-override installs are workspace-scoped: skip persistent
|
||||
# desktop / Start-Menu / dock launchers that would point at a path
|
||||
# the user may later delete. The runtime launcher + studio.conf +
|
||||
# icon written above are still essential for the env-mode shim and
|
||||
# ARE kept regardless of mode.
|
||||
# Env-mode installs are workspace-scoped: skip persistent desktop /
|
||||
# Start-Menu / dock launchers that may point at a deleted workspace.
|
||||
# Runtime launcher + studio.conf + icon are still written above.
|
||||
if [ "$_STUDIO_HOME_REDIRECT" = "env" ]; then
|
||||
substep "wrote launcher at $_css_launcher (persistent shortcuts skipped in env-override mode)"
|
||||
return 0
|
||||
|
|
@ -849,12 +802,9 @@ DESKTOP_EOF
|
|||
</plist>
|
||||
PLIST_EOF
|
||||
|
||||
# Executable stub
|
||||
# The stub embeds the resolved launcher path. Use a single-quoted
|
||||
# heredoc + post-write sed substitution + single-quoted shell
|
||||
# embedding so any path metacharacters ($, ", `, &, |, \, ') in
|
||||
# $_css_data_dir do not expand at .app launch time. Same pattern
|
||||
# as the launch-studio.sh @@DATA_DIR@@ substitution above.
|
||||
# Executable stub: same single-quoted-heredoc + sed-substitute
|
||||
# pattern as launch-studio.sh so $-vars in $_css_data_dir don't
|
||||
# expand at .app launch time.
|
||||
_css_sq_dir=$(printf '%s' "$_css_data_dir" | sed "s/'/'\\\\''/g")
|
||||
_css_sed_dir=$(printf '%s' "$_css_sq_dir" | sed 's/[\\&|]/\\&/g')
|
||||
cat > "$_css_macos_dir/launch-studio" << 'STUB_EOF'
|
||||
|
|
@ -1807,10 +1757,8 @@ _SKIP_FRONTEND=0
|
|||
if [ "$TAURI_MODE" = true ]; then
|
||||
_SKIP_FRONTEND=1
|
||||
fi
|
||||
# Helper: prepend UNSLOTH_STUDIO_HOME=$STUDIO_HOME to "$@" only for actual
|
||||
# env-override installs. Avoids word-splitting on whitespace paths -- a
|
||||
# string-form '_STUDIO_ENV_FOR_SETUP="UNSLOTH_STUDIO_HOME=$STUDIO_HOME"'
|
||||
# would split '/tmp/space path' into separate argv entries.
|
||||
# Prepend UNSLOTH_STUDIO_HOME=$STUDIO_HOME to "$@" for env-override installs
|
||||
# without word-splitting on whitespace paths.
|
||||
_run_setup_with_studio_home() {
|
||||
if [ "$_STUDIO_HOME_REDIRECT" = "env" ]; then
|
||||
UNSLOTH_STUDIO_HOME="$STUDIO_HOME" "$@"
|
||||
|
|
@ -1844,9 +1792,8 @@ else
|
|||
fi
|
||||
|
||||
# ── Make 'unsloth' available via $_LOCAL_BIN (resolved earlier) ──
|
||||
# When STUDIO_HOME / UNSLOTH_STUDIO_HOME is used, $_LOCAL_BIN is workspace-scoped
|
||||
# ($STUDIO_HOME/bin) and we skip the shell-rc PATH append so we do not pollute
|
||||
# the user's profile with a path that may be deleted with the workspace.
|
||||
# Env-mode: $_LOCAL_BIN is $STUDIO_HOME/bin; skip shell-rc PATH append so we
|
||||
# don't pollute the user's profile with a workspace-scoped path.
|
||||
mkdir -p "$_LOCAL_BIN"
|
||||
ln -sf "$VENV_DIR/bin/unsloth" "$_LOCAL_BIN/unsloth"
|
||||
|
||||
|
|
@ -1879,9 +1826,8 @@ case ":$PATH:" in
|
|||
esac
|
||||
|
||||
# Non-Tauri installs keep shortcuts even if setup reports failure.
|
||||
# create_studio_shortcuts itself gates the persistent desktop/menu
|
||||
# launchers based on $_STUDIO_HOME_REDIRECT; the runtime launcher +
|
||||
# studio.conf + icon are always written so env-mode shims still resolve.
|
||||
# create_studio_shortcuts gates persistent menu shortcuts on env-mode;
|
||||
# launcher + studio.conf + icon are always written.
|
||||
if [ "$TAURI_MODE" != true ]; then
|
||||
create_studio_shortcuts "$VENV_ABS_BIN/unsloth" "$OS"
|
||||
fi
|
||||
|
|
@ -1925,15 +1871,11 @@ if [ -t 1 ]; then
|
|||
exit "$_LAUNCH_EXIT"
|
||||
else
|
||||
step "launch" "manual commands:"
|
||||
# Single-quote-escape paths so values with spaces / apostrophes /
|
||||
# metacharacters round-trip through copy-paste from a non-TTY install log.
|
||||
# Single-quote-escape so paths with spaces / apostrophes copy-paste cleanly.
|
||||
_li_shim_q="'$(printf '%s' "${_LOCAL_BIN}/unsloth" | sed "s/'/'\\\\''/g")'"
|
||||
_li_act_q="'$(printf '%s' "${VENV_DIR}/bin/activate" | sed "s/'/'\\\\''/g")'"
|
||||
if [ "$_STUDIO_HOME_REDIRECT" = "env" ]; then
|
||||
# In env-override mode we deliberately skip the persistent shell
|
||||
# rc PATH append, so a fresh shell will not have `unsloth` on PATH
|
||||
# unless the caller re-exports UNSLOTH_STUDIO_HOME. Print the
|
||||
# absolute shim path and the activate-then-run alternative.
|
||||
# Env-mode skips the rc PATH append, so print the absolute shim path.
|
||||
substep "$_li_shim_q studio -H 0.0.0.0 -p 8888"
|
||||
substep "or activate env first:"
|
||||
substep "source $_li_act_q"
|
||||
|
|
|
|||
|
|
@ -491,14 +491,10 @@ class LlamaCppBackend:
|
|||
if win_bin.is_file():
|
||||
return str(win_bin)
|
||||
|
||||
# 2-4. Mirror setup.sh / setup.ps1's install layout:
|
||||
# - In env-override mode (custom Studio root != legacy default),
|
||||
# llama.cpp is installed under $STUDIO_HOME/llama.cpp.
|
||||
# - Otherwise (default install or HOME redirect), llama.cpp is
|
||||
# installed at ~/.unsloth/llama.cpp (sibling of the Studio dir).
|
||||
# Default-mode searches must NOT look at $STUDIO_HOME/llama.cpp,
|
||||
# to avoid picking a stale partial install from a previous failed
|
||||
# install over the real legacy binary.
|
||||
# 2-4. Match installer layout: env-mode -> $STUDIO_HOME/llama.cpp;
|
||||
# default/HOME-redirect -> ~/.unsloth/llama.cpp (sibling of studio).
|
||||
# Default mode skips $STUDIO_HOME/llama.cpp so a stale partial install
|
||||
# there cannot shadow the real legacy binary.
|
||||
legacy_llama = Path.home() / ".unsloth" / "llama.cpp"
|
||||
try:
|
||||
from utils.paths.storage_roots import studio_root as _sr # noqa: WPS433
|
||||
|
|
@ -511,7 +507,6 @@ class LlamaCppBackend:
|
|||
search_roots = [_resolved_sr / "llama.cpp", legacy_llama]
|
||||
except (ImportError, OSError, ValueError):
|
||||
search_roots = [legacy_llama]
|
||||
# De-dupe while preserving order (defensive in case both resolve equal).
|
||||
_seen: set[str] = set()
|
||||
for unsloth_home in [
|
||||
r for r in search_roots if str(r) not in _seen and not _seen.add(str(r))
|
||||
|
|
@ -2084,12 +2079,9 @@ class LlamaCppBackend:
|
|||
# (binary must be *under* one of these)
|
||||
install_roots: list[Path] = []
|
||||
|
||||
# Resolved Studio root (covers env-override custom installs).
|
||||
# Mirror _find_llama_server_binary: only treat $STUDIO_HOME/llama.cpp
|
||||
# as Studio-owned when STUDIO_HOME is a real env override, not the
|
||||
# legacy default. In default-mode installs llama.cpp is a sibling
|
||||
# of studio (~/.unsloth/llama.cpp), and ~/.unsloth/studio/llama.cpp
|
||||
# may be owned by a different tool or a stale partial install.
|
||||
# Env-mode custom root (mirrors _find_llama_server_binary). Default
|
||||
# mode excluded so we don't kill llama-server from another tool
|
||||
# running under ~/.unsloth/studio/llama.cpp.
|
||||
try:
|
||||
from utils.paths.storage_roots import studio_root as _sr # noqa: WPS433
|
||||
|
||||
|
|
|
|||
|
|
@ -23,12 +23,9 @@ if _backend_dir not in sys.path:
|
|||
# See: https://github.com/python/cpython/issues/102396
|
||||
import _platform_compat # noqa: F401
|
||||
|
||||
# Custom-root env propagation BEFORE any unsloth/unsloth-zoo import: when
|
||||
# main.py is launched directly via `uvicorn main:app` from a custom-root
|
||||
# venv, neither unsloth_cli nor run.py runs, so UNSLOTH_LLAMA_CPP_PATH
|
||||
# stays unset and unsloth-zoo's import-time LLAMA_CPP_DEFAULT_DIR binding
|
||||
# falls back to the legacy ~/.unsloth/llama.cpp. Mirror run.py's logic:
|
||||
# only export when the resolved root is a real custom override.
|
||||
# Direct `uvicorn main:app` launches bypass run.py, so re-export here too
|
||||
# (mirrors run.py). Required BEFORE the unsloth-zoo import below, since
|
||||
# its LLAMA_CPP_DEFAULT_DIR binding is import-time.
|
||||
from utils.paths.storage_roots import studio_root as _studio_root
|
||||
|
||||
_LEGACY_STUDIO_ROOT = (_Path.home() / ".unsloth" / "studio").resolve()
|
||||
|
|
|
|||
|
|
@ -159,17 +159,14 @@ def _find_free_port(host: str, start: int, max_attempts: int = 20) -> int:
|
|||
)
|
||||
|
||||
|
||||
# Resolved via the shared helper so custom installs land in the right place.
|
||||
from utils.paths.storage_roots import studio_root as _studio_root
|
||||
|
||||
_PID_FILE = _studio_root() / "studio.pid"
|
||||
|
||||
# When the backend is launched directly (bypassing unsloth_cli, which
|
||||
# normally re-exports these env vars), make sure unsloth-zoo's import-time
|
||||
# LLAMA_CPP_DEFAULT_DIR binding still picks up the custom-root build. Only
|
||||
# set when the resolved root is a real custom override -- legacy default
|
||||
# installs must NOT export, since the installers treat any non-empty
|
||||
# UNSLOTH_STUDIO_HOME as env-override mode.
|
||||
# Direct backend launches bypass the CLI's env re-export; do it here for
|
||||
# real custom roots so unsloth-zoo's import-time LLAMA_CPP_DEFAULT_DIR
|
||||
# picks up the custom build. Skip for legacy-default to avoid flipping
|
||||
# default-mode installs into env-override.
|
||||
_LEGACY_STUDIO_ROOT = (Path.home() / ".unsloth" / "studio").resolve()
|
||||
try:
|
||||
_STUDIO_ROOT_RESOLVED = _studio_root().resolve()
|
||||
|
|
|
|||
|
|
@ -499,7 +499,6 @@ _VLM_MODEL_TYPES = {
|
|||
|
||||
# Pre-computed .venv_t5 paths and backend dir for subprocess version switching.
|
||||
# Vision check uses 5.5.0 (newest, recognizes all architectures).
|
||||
# Use the shared resolver so custom-root installs find their own venv.
|
||||
from utils.paths.storage_roots import studio_root as _studio_root # noqa: E402
|
||||
|
||||
_VENV_T5_DIR = str(_studio_root() / ".venv_t5_550")
|
||||
|
|
|
|||
|
|
@ -11,14 +11,9 @@ import tempfile
|
|||
|
||||
|
||||
def _infer_studio_home_from_venv() -> Path | None:
|
||||
"""If running from an installer-managed unsloth_studio venv, return the
|
||||
parent dir as STUDIO_HOME.
|
||||
|
||||
Fallback for fresh shells after a custom install where the installer
|
||||
wrote to a workspace path but the user did not re-export the env var.
|
||||
Narrowed via installer-sentinel check (share/studio.conf or bin shim)
|
||||
so a developer venv that happens to be named ``unsloth_studio`` is not
|
||||
misidentified as a custom Studio root.
|
||||
"""Return parent dir of sys.prefix as STUDIO_HOME if running from an
|
||||
installer-managed unsloth_studio venv. Sentinel-gated (share/studio.conf
|
||||
or bin shim) so a developer venv named unsloth_studio is not misidentified.
|
||||
"""
|
||||
try:
|
||||
prefix = Path(sys.prefix).resolve()
|
||||
|
|
@ -36,12 +31,10 @@ def _infer_studio_home_from_venv() -> Path | None:
|
|||
|
||||
|
||||
def studio_root() -> Path:
|
||||
"""Resolve the Studio install root.
|
||||
"""Studio install root.
|
||||
|
||||
Priority: UNSLOTH_STUDIO_HOME env, STUDIO_HOME env (alias), sys.prefix
|
||||
inference, legacy ~/.unsloth/studio. Backwards-compatible: identical
|
||||
to the legacy default when no env var is set and we are not running
|
||||
from the venv.
|
||||
Priority: UNSLOTH_STUDIO_HOME, STUDIO_HOME, sys.prefix inference,
|
||||
legacy ~/.unsloth/studio.
|
||||
"""
|
||||
override = os.environ.get("UNSLOTH_STUDIO_HOME") or os.environ.get("STUDIO_HOME")
|
||||
if override:
|
||||
|
|
|
|||
|
|
@ -94,7 +94,6 @@ TRANSFORMERS_DEFAULT_VERSION = "4.57.6"
|
|||
TRANSFORMERS_5_VERSION = TRANSFORMERS_550_VERSION
|
||||
|
||||
# Pre-installed directories — created by setup.sh / setup.ps1.
|
||||
# Use the shared resolver so custom-root installs find their own venvs.
|
||||
from utils.paths.storage_roots import studio_root as _studio_root # noqa: E402
|
||||
|
||||
_VENV_T5_530_DIR = str(_studio_root() / ".venv_t5_530")
|
||||
|
|
|
|||
|
|
@ -1455,11 +1455,8 @@ if (-not $PythonCmd) {
|
|||
|
||||
substep "Using $PythonCmd ($(& $PythonCmd --version 2>&1))"
|
||||
|
||||
# The venv must already exist (created by install.ps1).
|
||||
# This script (setup.ps1 / "unsloth studio update") only updates packages.
|
||||
# UNSLOTH_STUDIO_HOME / STUDIO_HOME (alias) override the install root,
|
||||
# mirroring install.ps1. install.ps1 exports UNSLOTH_STUDIO_HOME when
|
||||
# invoking the studio update.
|
||||
# The venv must already exist (created by install.ps1); this script only
|
||||
# updates packages. UNSLOTH_STUDIO_HOME / STUDIO_HOME override the root.
|
||||
$_studioOverride = if ($env:UNSLOTH_STUDIO_HOME) { $env:UNSLOTH_STUDIO_HOME } elseif ($env:STUDIO_HOME) { $env:STUDIO_HOME } else { $null }
|
||||
if ($_studioOverride) {
|
||||
if ($_studioOverride -eq "~" -or $_studioOverride -like "~/*" -or $_studioOverride -like "~\*") {
|
||||
|
|
@ -1728,8 +1725,7 @@ if ($stackExit -ne 0) {
|
|||
# ── Pre-install transformers 5.x into .venv_t5_530/ and .venv_t5_550/ ──
|
||||
# Runs outside the deps fast-path gate so that upgrades from the legacy
|
||||
# single .venv_t5 are always migrated to the tiered layout.
|
||||
# T5 sidecar venvs live next to the main venv under the resolved $StudioHome
|
||||
# so custom-root installs are self-contained.
|
||||
# T5 sidecar venvs live under the resolved $StudioHome so custom installs are self-contained.
|
||||
$VenvT5_530Dir = Join-Path $StudioHome ".venv_t5_530"
|
||||
$VenvT5_550Dir = Join-Path $StudioHome ".venv_t5_550"
|
||||
$VenvT5Legacy = Join-Path $StudioHome ".venv_t5"
|
||||
|
|
@ -1822,15 +1818,12 @@ step "transformers" "5.5.0 pre-installed"
|
|||
# ==========================================================================
|
||||
# PHASE 3.4: Prefer prebuilt llama.cpp bundles before source build
|
||||
# ==========================================================================
|
||||
# Only nest llama.cpp under $StudioHome when the resolved Studio root is
|
||||
# a real override (not the legacy default). Compare resolved paths so a
|
||||
# stale UNSLOTH_STUDIO_HOME pointing at the legacy default does not
|
||||
# Nest llama.cpp under $StudioHome only for real env-overrides, never the
|
||||
# legacy default. Stale UNSLOTH_STUDIO_HOME pointing at legacy must not
|
||||
# accidentally relocate llama.cpp.
|
||||
$LegacyStudioHome = Join-Path $env:USERPROFILE ".unsloth\studio"
|
||||
# Canonicalize BOTH sides. $StudioHome is the resolved env-override path
|
||||
# in env-mode (line 1474) but the bare logical path in default mode
|
||||
# (line 1480). Canonicalizing on the fly handles a junctioned/symlinked
|
||||
# %USERPROFILE% the same in both modes.
|
||||
# Canonicalize both sides so a junctioned/symlinked %USERPROFILE% behaves
|
||||
# the same in env-mode (resolved) and default mode (logical $StudioHome).
|
||||
$_studioHomeCanon = $StudioHome
|
||||
if (Test-Path -LiteralPath $_studioHomeCanon -PathType Container) {
|
||||
$_studioHomeCanon = (Resolve-Path -LiteralPath $_studioHomeCanon).Path
|
||||
|
|
|
|||
|
|
@ -399,18 +399,14 @@ if [ -d "$SCRIPT_DIR/backend/core/data_recipe/oxc-validator" ] && command -v npm
|
|||
fi
|
||||
|
||||
# ── Python venv + deps ──
|
||||
# UNSLOTH_STUDIO_HOME / STUDIO_HOME (alias) override the install root, mirroring
|
||||
# install.sh. install.sh exports UNSLOTH_STUDIO_HOME when invoking this script.
|
||||
# UNSLOTH_STUDIO_HOME / STUDIO_HOME override the install root (mirrors install.sh).
|
||||
_studio_override="${UNSLOTH_STUDIO_HOME:-${STUDIO_HOME:-}}"
|
||||
# Expand a leading ~ / ~/path because env vars are not subject to tilde
|
||||
# expansion when set with quotes around the value.
|
||||
case "$_studio_override" in
|
||||
"~") _studio_override="$HOME" ;;
|
||||
"~/"*) _studio_override="$HOME/${_studio_override#'~/'}" ;;
|
||||
esac
|
||||
if [ -n "$_studio_override" ]; then
|
||||
mkdir -p -- "$_studio_override"
|
||||
# CDPATH= prevents CDPATH-prefixed echo; -P canonicalizes symlinks.
|
||||
STUDIO_HOME="$(CDPATH= cd -P -- "$_studio_override" && pwd -P)" || exit 1
|
||||
else
|
||||
STUDIO_HOME="$HOME/.unsloth/studio"
|
||||
|
|
@ -570,16 +566,11 @@ fi
|
|||
fi
|
||||
|
||||
# ── 7. Prefer prebuilt llama.cpp bundles before any source build path ──
|
||||
# Only nest llama.cpp under $STUDIO_HOME when the resolved Studio root is a
|
||||
# real override (not the legacy default). Comparing resolved paths instead
|
||||
# of env-var presence avoids regressing default installs that incidentally
|
||||
# inherit UNSLOTH_STUDIO_HOME from a parent process or the CLI.
|
||||
# Nest llama.cpp under $STUDIO_HOME only for real env-overrides, never the
|
||||
# legacy default. Compare canonicalized paths so STUDIO_HOME (logical in
|
||||
# default mode, canonical in env mode) and the legacy side line up under
|
||||
# symlinked $HOME.
|
||||
_LEGACY_STUDIO_HOME="$HOME/.unsloth/studio"
|
||||
# Canonicalize BOTH sides under symlinked $HOME. STUDIO_HOME is logical
|
||||
# in default-mode (line 416 sets it from the bare $HOME path) and
|
||||
# canonical in env-mode (line 413 uses pwd -P). Canonicalizing on the
|
||||
# fly here means default-mode under symlinked $HOME still recognizes
|
||||
# the legacy default and keeps llama.cpp at ~/.unsloth/llama.cpp.
|
||||
_studio_home_canon="$STUDIO_HOME"
|
||||
if [ -d "$_studio_home_canon" ]; then
|
||||
_studio_home_canon=$(CDPATH= cd -P -- "$_studio_home_canon" 2>/dev/null && pwd -P) \
|
||||
|
|
|
|||
|
|
@ -194,10 +194,8 @@ async fn provision_desktop_auth() -> Result<(), String> {
|
|||
cmd.env_remove("PYTHONPATH");
|
||||
}
|
||||
|
||||
// Tauri does not honor UNSLOTH_STUDIO_HOME / STUDIO_HOME yet; scrub so the
|
||||
// provisioning subprocess writes to the legacy ~/.unsloth/studio root that
|
||||
// matches what the Rust auth code reads. UNSLOTH_LLAMA_CPP_PATH is a
|
||||
// pre-existing backend-only llama.cpp directory override and is kept.
|
||||
// Tauri uses the legacy root regardless of UNSLOTH_STUDIO_HOME / STUDIO_HOME.
|
||||
// Scrub so provisioning writes match what the Rust auth code reads.
|
||||
cmd.env_remove("UNSLOTH_STUDIO_HOME");
|
||||
cmd.env_remove("STUDIO_HOME");
|
||||
#[cfg(windows)]
|
||||
|
|
|
|||
|
|
@ -192,10 +192,8 @@ fn spawn_script(
|
|||
cmd.env_remove("PYTHONPATH");
|
||||
}
|
||||
|
||||
// Tauri only does default-root installs. install.sh / install.ps1 reject
|
||||
// UNSLOTH_STUDIO_HOME / STUDIO_HOME under --tauri; scrub them from the
|
||||
// spawned installer so an inherited shell-set value cannot trip the guard.
|
||||
// UNSLOTH_LLAMA_CPP_PATH is unrelated to the Studio root and kept as-is.
|
||||
// Tauri only does default-root installs; install.sh / install.ps1 reject
|
||||
// these under --tauri. Scrub so an inherited value can't trip the guard.
|
||||
cmd.env_remove("UNSLOTH_STUDIO_HOME");
|
||||
cmd.env_remove("STUDIO_HOME");
|
||||
|
||||
|
|
|
|||
|
|
@ -280,12 +280,9 @@ pub fn start_backend(
|
|||
cmd.env_remove("PYTHONPATH");
|
||||
}
|
||||
|
||||
// The Tauri desktop app does not honor UNSLOTH_STUDIO_HOME / STUDIO_HOME yet;
|
||||
// it always uses ~/.unsloth/studio. Scrub these from the spawned Python
|
||||
// backend so it cannot diverge from the Rust-resolved Studio root when the
|
||||
// user's shell happens to have them set. Keep UNSLOTH_LLAMA_CPP_PATH: that
|
||||
// is a pre-existing custom-llama.cpp-directory override the Python backend
|
||||
// and unsloth-zoo intentionally support, independent of the Studio root.
|
||||
// Tauri uses the legacy root regardless of UNSLOTH_STUDIO_HOME / STUDIO_HOME;
|
||||
// scrub so the spawned Python backend can't diverge. UNSLOTH_LLAMA_CPP_PATH
|
||||
// is a pre-existing user-controlled llama.cpp dir override; keep it.
|
||||
cmd.env_remove("UNSLOTH_STUDIO_HOME");
|
||||
cmd.env_remove("STUDIO_HOME");
|
||||
|
||||
|
|
|
|||
|
|
@ -58,9 +58,8 @@ fn spawn_update(
|
|||
cmd.env_remove("PYTHONPATH");
|
||||
}
|
||||
|
||||
// Tauri still manages the legacy ~/.unsloth/studio root; scrub the custom-
|
||||
// root env vars so 'unsloth studio update' updates the same install the
|
||||
// desktop app uses, not an unrelated custom root inherited from the shell.
|
||||
// Tauri manages the legacy root; scrub so 'unsloth studio update' targets
|
||||
// the same install the desktop app uses, not an inherited custom root.
|
||||
cmd.env_remove("UNSLOTH_STUDIO_HOME");
|
||||
cmd.env_remove("STUDIO_HOME");
|
||||
|
||||
|
|
|
|||
|
|
@ -21,17 +21,12 @@ import typer
|
|||
studio_app = typer.Typer(help = "Unsloth Studio commands.")
|
||||
|
||||
|
||||
# UNSLOTH_STUDIO_HOME / STUDIO_HOME (alias) override the install root, matching
|
||||
# install.sh / install.ps1. Falls back to sys.prefix inference (so direct
|
||||
# invocations of <STUDIO_HOME>/bin/unsloth still resolve correctly even after
|
||||
# the installer's env var has expired), then to the legacy ~/.unsloth/studio.
|
||||
# Returns (path, is_custom): is_custom=True only when the resolved root is a
|
||||
# real override; we use this to decide whether to re-export the env var to
|
||||
# child processes.
|
||||
# Resolve install root: UNSLOTH_STUDIO_HOME / STUDIO_HOME, then sys.prefix
|
||||
# inference (so a direct call to <root>/bin/unsloth resolves after the
|
||||
# installer's env var has expired), then legacy ~/.unsloth/studio.
|
||||
def _looks_like_installer_managed_studio_home(candidate: Path) -> bool:
|
||||
"""Heuristic: only treat a directory as an installer-managed Studio root
|
||||
if it carries installer-written sentinels (studio.conf or the bin shim).
|
||||
Avoids over-matching on a dev venv that happens to be named unsloth_studio.
|
||||
"""Sentinel check (studio.conf or bin shim) so a dev venv named
|
||||
unsloth_studio is not misidentified as a custom Studio root.
|
||||
"""
|
||||
shim_name = "unsloth.exe" if platform.system() == "Windows" else "unsloth"
|
||||
return (candidate / "share" / "studio.conf").is_file() or (
|
||||
|
|
@ -58,21 +53,16 @@ def _resolve_studio_home() -> tuple[Path, bool]:
|
|||
|
||||
|
||||
STUDIO_HOME, _STUDIO_HOME_IS_CUSTOM = _resolve_studio_home()
|
||||
# Re-export only for actual custom roots so child processes (setup script,
|
||||
# backend run.py) inherit it. Default installs MUST NOT re-export the env
|
||||
# var, because setup.sh / setup.ps1 treat its presence as "env-override
|
||||
# mode" and would relocate llama.cpp / DATA_DIR away from legacy paths.
|
||||
# UNSLOTH_LLAMA_CPP_PATH is also setdefault for custom roots so
|
||||
# unsloth-zoo's import-time LLAMA_CPP_DEFAULT_DIR binding picks up the
|
||||
# correct build dir for GGUF export.
|
||||
# Re-export only for real custom roots; default installs must NOT export
|
||||
# (setup.sh/setup.ps1 treat any non-empty UNSLOTH_STUDIO_HOME as env-mode).
|
||||
# UNSLOTH_LLAMA_CPP_PATH is set so unsloth-zoo's import-time
|
||||
# LLAMA_CPP_DEFAULT_DIR binding finds the custom build for GGUF export.
|
||||
if _STUDIO_HOME_IS_CUSTOM:
|
||||
# Use truthy-check rather than setdefault so a blank env var (e.g.
|
||||
# UNSLOTH_STUDIO_HOME=) doesn't suppress the inferred custom root.
|
||||
# Truthy-check (not setdefault) so a blank UNSLOTH_STUDIO_HOME= doesn't
|
||||
# suppress the inferred custom root.
|
||||
if not os.environ.get("UNSLOTH_STUDIO_HOME"):
|
||||
os.environ["UNSLOTH_STUDIO_HOME"] = str(STUDIO_HOME)
|
||||
# Mirror setup.sh / setup.ps1's legacy-equality check: when an env
|
||||
# override happens to equal the legacy default, llama.cpp still lives
|
||||
# at ~/.unsloth/llama.cpp (one shared build across legacy installs).
|
||||
# When override == legacy default, llama.cpp stays at ~/.unsloth/llama.cpp.
|
||||
_legacy_studio = (Path.home() / ".unsloth" / "studio").resolve()
|
||||
if STUDIO_HOME.resolve() == _legacy_studio:
|
||||
_llama_dir = Path.home() / ".unsloth" / "llama.cpp"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue