Commit graph

10 commits

Author SHA1 Message Date
Daniel Han
8e0d082c92
Reap Studio child processes when the parent dies abnormally (#6425)
* Reap Studio child processes when the parent dies abnormally

Standalone `unsloth studio` launches orphaned cloudflared and llama-server when
the parent exited without running the cooperative shutdown path (terminal-window
close, Task Manager End Task, SIGKILL): the children reparented to init and kept
running, leaving an authenticated Cloudflare tunnel up for days.

Add utils/process_lifetime.py: a parent-owned Windows Job Object
(JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE, children auto-inherit) plus Linux
PR_SET_PDEATHSIG, behind a best-effort helper that mirrors the desktop app's
windows_job.rs. initialize_parent_lifetime() runs at the top of run_server;
long-lived spawns (cloudflared, llama-server, RAG embedder, llama.cpp updater)
get the PDEATHSIG preexec, multiprocessing workers are adopted into the job, and
_graceful_shutdown plus atexit gain a terminate_all() backstop sweep. The
cooperative shutdown path is otherwise unchanged.

Verified on Linux: killing the parent now reaps cloudflared and llama-server
within ~2s instead of orphaning them.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* test: add real Windows kill-on-job-close integration test

Spawn a parent that installs the job and a child that inherits it, terminate
the parent, and assert the child is reaped. Skipped off Windows. Also make the
liveness probe Windows-safe (os.kill(pid, 0) terminates on Windows).

* Fix Win64 handle truncation in the Job Object calls

Set explicit argtypes so the 64-bit job/process handles are not marshaled as
c_int (which truncated them on Win64, failing AssignProcessToJobObject). Assert
install success in the Windows integration test.

* Bind multiprocessing workers to parent death; harden the sweep

Review follow-ups:
- Multiprocessing workers (inference/export/training/data-recipe/Xet) cannot be
  given a preexec_fn by the parent, so adopt_pid alone left them orphanable on a
  Linux SIGKILL. They now bind themselves with PR_SET_PDEATHSIG at startup via
  bind_current_process_to_parent_lifetime(), wired into the shared
  run_without_native_path_secret entrypoint and the Xet child entry.
- Wire the previously-missed data-recipe worker through adopt_pid.
- terminate_all now honors its timeout: SIGTERM, wait, then SIGKILL the
  survivors, so cooperative children can exit cleanly.
- Track adopted pids with a /proc starttime identity and add forget_pid, so the
  shutdown sweep never signals a recycled pid.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: Michael Han <michaelhan2050@gmail.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-06-18 05:51:22 -07:00
Daniel Han
6c02af8618
Studio: stop the llama.cpp update banner flickering and show the download size (#6338)
* Studio: stop the llama.cpp update banner flickering and show the download size

The banner animated in and out with a motion opacity + scale + translate
transition. That transform/opacity transition promotes a GPU compositing
layer whose first and last frame can flash for a moment on real displays,
which reads as a flicker on appear and again on dismiss/snooze. Drop the
animation and render the banner as a plain conditional mount: it appears
and leaves cleanly with nothing to flash.

Also surface the download size. update-status now reports the size of the
prebuilt that Update would fetch (the latest-release asset matching this
host's bundle), and the banner shows it as whole MB next to the no-restart
note, so the cost of the update is clear before clicking.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Show llama.cpp update size for upstream and source-build installs

update_download_size_bytes now accepts the upstream ggml-org ubuntu-/win-
asset suffixes and falls back to the marker's binary_repo, so the size
resolves for CPU/ROCm prebuilts (the fork publish repo only carries the
app-* and macOS bundles). The source-build update path now populates
update_size_bytes from the resolved asset, matching the marker path.

Both fail open to null. Adds regression tests for the upstream and
source-build size lookups and the route field round-trip.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: danielhanchen <michaelhan2050@gmail.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-06-17 21:28:54 -07:00
oobabooga
785d446fc1
Studio: show llama.cpp version and GPU specs in the About panel (#6261)
* Studio: show llama.cpp version and GPU specs in the About panel

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Studio: run the hardware endpoint off the event loop

* Studio: show the full llama.cpp release tag (incl -mix-<sha>) in the About panel

* Studio: order About-panel GPUs by visible ordinal and skip the llama.cpp probe during updates

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Fix hardware info refresh and endpoint scope

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Daniel Han <danielhanchen@gmail.com>
Co-authored-by: Etherll <61019402+Etherll@users.noreply.github.com>
2026-06-15 15:25:08 +03:00
Michael Han
bd9324b634
Studio: offer llama.cpp update for same-base mix builds on source installs (#6280)
The update banner is driven by update_available from
/api/llama/update-status. Prebuilt (marker) installs decide this via
freshness.is_behind, which is mix-aware: a release at the same upstream
base build but with a new -mix-<sha> suffix counts as behind.

Source-build installs went through _source_build_status, which compared
only the numeric base build (installed_build < latest_build). When a new
prebuilt shared the installed upstream base (our usual mix re-tag at the
same base), it returned update_available=False and the banner never
showed. This is the common macOS case, where a failed prebuilt fetch
falls back to a source build that lacks the mix patches.

Make the source-build path mix-aware to match the marker path: same base
plus a -mix-<sha> tag now offers the update (and displays the mix tag),
a bare same-base rebuild does not, and the downgrade guard and unknown
-version fallback are unchanged.
2026-06-13 04:14:36 -07:00
oobabooga
5300c047b6
Installer: drop the lemonade ROCm fallback now the fork ships identical per-gfx prebuilts (#6225)
---------

Co-authored-by: Daniel Han <danielhanchen@gmail.com>
2026-06-12 11:53:26 -03:00
Daniel Han
6a0a62ef65
Studio: drop the on-disk freshness cache after a llama.cpp update (#6234)
The post-install path cleared only the in-memory freshness caches and then
re-primed the 24h disk cache with a forced GitHub refresh. When that refresh
cannot reach GitHub, latest_published_release falls back to the last-good disk
value, so a still-fresh same-base mix tag cached before the swap (b9596-mix-aaa
vs the just-installed b9596-mix-bbb) is replayed and the prebuilt reads as
behind, surfacing a false update banner that points back at the build that was
just replaced.

Give reset_caches a drop_disk option and use it on the update path: with the
disk cache gone, an offline post-install refresh leaves latest as None and the
banner fails open (off) instead of lingering on the stale same-base value. The
no-arg form stays in-memory only. Adds regression coverage for the drop, the
default no-op, and the fail-open vs stale-replay contrast.
2026-06-12 02:43:55 -07:00
oobabooga
fb56b82a38
Studio: fix llama.cpp update banner offering a downgrade / sticking on mix releases (#6219) 2026-06-11 23:23:14 -03:00
Michael Han
b2b1dcd6ad
Studio: llama.cpp update banner redesign, About tab license info, UI polish (#6196)
* Studio: llama.cpp update banner redesign, About tab license info, inline system prompt editing, naming cleanup

- Redesign the llama.cpp update banner to match the chat composer surface
  (borderless rounded card, composer shadow, Hellix Medium title), rename
  actions to Update and add a 15 minute Remind me later snooze
- Keep the banner up until the user explicitly acts on it; drop the
  outside click dismissal
- Add a Settings > General > Notifications toggle to disable the banner
  for training-only setups (on by default)
- Rename the Help settings tab to About and add a License section
  (Unsloth Studio AGPL-3.0, Unsloth Core Apache-2.0) linking to the
  license files in this repo
- Make the run settings system prompt box an inline editable textarea;
  the popup editor opens when the prompt overflows the box
- Pointer cursor on the preset dropdown chevron
- Dark mode toasts use the chat composer surface color
- Replace standalone Studio with Unsloth in user facing strings; keep
  Unsloth Studio, LM Studio, Fine-tuning Studio, Recipe Studio and CLI
  commands unchanged

* Studio: open the system prompt popup on box click, balance banner padding

- The system prompt box opens the Edit System Prompt dialog on click,
  matching the pencil action
- Slightly more bottom padding on the llama.cpp update banner so the
  spacing reads even next to the action pills

* Studio: replace unsloth studio update with the installer commands in update guidance

- The unsloth studio update command no longer works, so the About tab
  update section now shows the one-line installer (curl or irm) for
  PyPI and unknown installs, and git pull plus the local installer for
  checkouts
- Add a short note that unsloth studio update is no longer supported
- Link the Installation, Updating and Windows install docs pages
- The package update banner now copies the platform installer command
  instead of unsloth studio update

* Studio: rounder account menu, inline system prompt box with popup from the label

- Account menu corners go from 14px to 18px via a specific override,
  since list menus pin border-radius globally
- llama.cpp banner bottom padding 22px
- System prompt is an inline editable textarea again; clicking the
  System Prompt label opens the popup editor, and an overflowing
  prompt opens it on box click

* Studio: show the standard install commands in the About update section

- Both one-line install commands (MacOS/Linux/WSL and Windows
  PowerShell) are always shown, labeled like the docs, since running
  them again updates an existing install
- Drop the unsloth studio update deprecation note
- Add the Mac install guide to the docs links

* Studio: clearer platform toggle and layout in the About update section

- Section heading is Update
- Platform picker is a pair of pill buttons, MacOS / Linux and Windows,
  and only the selected platform's install command is shown
- Intro reads: To install or update Unsloth
- Local update heading separates checkout guidance from the standard
  install command

* Studio: report GitHub branch instead of dev for source checkouts

A source checkout not on an exact release tag now shows
GitHub <branch> (e.g. GitHub main) as the Studio version in About.
Detached or unusual HEADs still fall back to dev.

* Studio: tighten the About update section copy and toggle styling

- Platform toggle buttons are borderless pills
- Shorter local update wording and restart note
- Docs links read Mac and Windows

* Studio: tighten line spacing in the sidebar account button

* Studio: fix vanishing compact MCP icon on hover, single line pill tooltips

- Compact caret pills (MCP, RAG) keep their icon on hover for inactive
  pills too; the off switch hover rules hid the icon while compact mode
  hid the X, leaving an empty slot
- Compact icon tooltips and single line compact tooltips render as full
  pills; wrapped tooltips keep the 9px corners. TooltipContent measures
  line count in a ref callback since Radix mounts portal content
  without re-rendering the wrapper
- 1px gap between the name and Unsloth lines in the sidebar account
  button

* Studio: Projects hover plus button, align recents with the label

- Hovering the Projects nav item reveals a plus button that opens the
  New project dialog, with the same circular hover treatment as the
  chat row actions
- Recent chat titles start at the same x as the Recents label
- The system prompt overflow lock only engages for a non-empty prompt
  with a laid-out box, so a mis-measure cannot turn clicks into the
  popup

* Clip system prompt overflow inside the rounded box

Wrap the inline system prompt textarea in a rounded overflow-hidden
surface so scrolled text and the scrollbar stay inside the box. The
focus ring moves to the wrapper via focus-within.

* Add updating progress bar to llama banner and shorten settings copy

While an update is applying, the banner action row becomes an
indeterminate progress bar that keeps animating under reduced motion,
matching the other loading indicators. Settings descriptions across
General, Profile, Appearance, Chat, Connections, API, and About are
trimmed without losing meaning.

* Address review: desktop update note, server platform detection, zh-CN keys

The About tab no longer shows terminal install commands in the desktop
app, where the bundled backend updates through the built-in updater;
it shows a short note and the docs links instead.

fetchDeviceType now sends the auth token to /api/health, which only
reports the server platform to authed callers, and caches only a
server-reported value. Copied install commands then match the host
platform rather than the browser when they differ (WSL, SSH).

zh-CN gains translations for the new notification and license keys,
the renamed About tab title, and the desktop update note.

* Real download progress for llama.cpp updates, prompt and sidebar polish

The update worker now streams the installer output and parses its
download percent lines into job progress, exposed via the update-status
API. The installer emits finer non-tty milestones when
UNSLOTH_PROGRESS_PERCENT_STEP is set; the worker requests 5 percent
steps. The banner renders a determinate bar from the reported fraction
and falls back to the sweep until the first percent arrives.

Also removes the focus ring on the inline system prompt box and
slightly shrinks the Projects hover plus icon.
2026-06-11 09:27:34 -07:00
Daniel Han
898d3dd0b5
Studio: offer the in-app llama.cpp update for source-build (markerless) installs (#6188)
* Studio: offer the in-app llama.cpp update for source-build (markerless) installs

Source-build installs have no UNSLOTH_PREBUILT_INFO.json marker, so freshness
reported supported=False and the Update button never showed (notably on macOS,
where the fork shipped no prebuilt before b9585 and setup fell back to a source
build). When an install has no marker but an official prebuilt now exists for
the host, surface the update and let one click swap it in place.

- install_llama_prebuilt.py: published_repo_for_host() (the setup.sh host->repo
  rule in Python) and a --resolve-prebuilt mode that reports whether a prebuilt
  exists for this host without downloading.
- llama_cpp_update.py: markerless branch in get_update_status/start_update,
  version-suppressed so source builds already newer than latest are not nagged;
  fail-open throughout.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Studio: run llama update detection off the event loop, expose source_build

The markerless source-build check probes the host and reads GitHub, so run
get_update_status and start_update in a worker thread to keep the API
responsive. Expose source_build in the status response so the banner can label
the source-build switch.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Keep the llama-route auth stub out of sys.modules for the rest of the suite

test_llama_route.py replaced sys.modules['auth.authentication'] with a
bare stub at collection time and never restored it, so every later test
importing create_access_token got the stub: 17 failures across
test_desktop_auth, test_middleware, test_openai_tool_passthrough and
test_rag_preview on all four Backend CI Python versions. Import the
real module when its deps are available and only stub in minimal envs,
popping the stubs after the standalone route load either way.

* Studio: address review on the source-build update path

- published_repo_for_host: route CPU-only Windows to ggml-org too (mirrors
  setup.ps1; the fork ships no win-cpu bundle), macOS always the fork.
- markerless detection compares/display the upstream llama_tag, not a possible
  fork wrapper release_tag, so a source build is not wrongly judged newer.
- do not offer when there is no resolvable install root (a pinned
  LLAMA_SERVER_PATH outside a managed dir): an apply would not take effect.

* Ignore version probes in the update tests' subprocess capture

The status polls in these tests trigger the new source-build detection,
which shells out to llama-server --version through the same patched
subprocess.run. On slow runners that probe lands after the installer
call and clobbers the single captured argv, failing the flag
assertions (seen on the 3.10/3.11 Backend CI jobs). Skip probe calls
in all three fakes so only the installer invocation is captured.

* Skip markerless re-detection while the update job is swapping the tree

On a source-build install the frontend polls update-status every 3s
during an apply, and each poll ran _source_build_status, which execs
the very llama-server binary the job is concurrently replacing. On
Windows that exec can hold the exe long enough to fail the installer's
os.replace; everywhere it is a per-poll subprocess spawn for a status
the poller does not read (it only consumes job progress). Gate the
markerless branch on the job not running; the marked path is probe-free
and still returns the live job state.

* Studio: tighten source-build update root, repo routing, and downgrade guard

Only manage a markerless install when the active binary lives under a
resolvable llama.cpp root (marker dir, UNSLOTH_LLAMA_CPP_PATH it sits in,
or a llama.cpp ancestor); a pinned LLAMA_SERVER_PATH or a PATH/system
binary is left alone so an apply cannot install where it would not take
effect. Gate start_update on the same suppression as detection so a
direct POST cannot downgrade a source build newer than the latest
prebuilt. Route Linux hosts with AMD tooling (rocminfo/amd-smi/hipconfig/
hipinfo) to the fork in --resolve-prebuilt, matching setup.sh, so a HIP
source build is not offered an upstream CPU prebuilt.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Studio: cover inactive env root and pinned llama.cpp checkout in update root tests

---------

Co-authored-by: danielhanchen <michaelhan2050@gmail.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-06-11 02:45:12 -07:00
Daniel Han
dab0b77673
Studio: in-app Update llama.cpp button to install the latest prebuilt (#6097)
Adds an in-app "Update llama.cpp" banner and button to Unsloth Studio. When the installed prebuilt is behind the latest published release, a non-invasive banner appears; clicking Update downloads the latest prebuilt for this host and swaps it in place in the background, with no restart.

Detection reuses the freshness check from #5529. The update re-runs install_llama_prebuilt.py the same way setup.sh and setup.ps1 do after #5963: it forwards the published repo and the AMD gfx target derived from the install marker, and does not pass the removed --simple-policy or the arm64-only --cpu-fallback.

While the installer swaps binaries the backend enters a maintenance state (flag set under the serial load lock, active server unloaded) so a concurrent load cannot start a server from a half-swapped binary; the next load uses the new build. The banner also handles refused responses and jobs started in another tab so it never sticks on "Updating...".

Verified end to end on an NVIDIA B200: installed b9493, detected the update, applied it, and confirmed the binary at the same path advanced to b9585 in the same process. Hermetic backend tests and the frontend type-check pass.
2026-06-10 10:04:26 -07:00