Commit graph

5,963 commits

Author SHA1 Message Date
oobabooga
2a5de505df Cancel diffusion loads on unload, mask seeds to JS-safe range, skip malformed gallery records 2026-06-24 23:30:29 -03:00
oobabooga
818ddb828f Add FLUX.2-klein-9B to the curated image models 2026-06-24 22:31:57 -03:00
oobabooga
6411f9464a Add FLUX.2-klein-4B via Flux2KleinPipeline 2026-06-24 22:09:59 -03:00
oobabooga
5d80d30168 Support Qwen-Image and FLUX.1 image models alongside Z-Image 2026-06-24 21:42:57 -03:00
oobabooga
5c4d09a1c9 Paginate the image gallery with infinite scroll 2026-06-24 20:48:07 -03:00
oobabooga
2bf9d73b4a Reuse formatEta, compute generation ETA once per step, guard re-renders 2026-06-24 19:50:10 -03:00
oobabooga
54d01a505f Add a live per-step generation progress bar with ETA 2026-06-24 19:41:15 -03:00
oobabooga
e2cd5ab90d Trim verbose comments 2026-06-24 19:21:29 -03:00
oobabooga
a87e092f59 Drop dead PNG-base64 helper and dedupe the image-gen task list 2026-06-24 19:17:49 -03:00
oobabooga
37d67c2a34 Roomier content padding and hide the negative prompt at guidance 0 2026-06-24 19:07:04 -03:00
oobabooga
af6548c86e Drop the redundant size/seed chip now that Recipe shows it 2026-06-24 18:57:27 -03:00
oobabooga
571d506c20 Refine image generation UI: aspect ratio sliders, info hints, action toolbar, and timestamped export filenames 2026-06-24 18:47:33 -03:00
oobabooga
eced3620fa Add batch size and sequential count to image generation with reproducible per-run seeds 2026-06-24 18:02:38 -03:00
oobabooga
caa7efecc0 Persist the image gallery to disk with recipes embedded in each PNG, and match official Z-Image defaults 2026-06-24 17:50:11 -03:00
oobabooga
adebdfc9f4 Fix image load progress, hide diffusion models from chat picker, and gallery polish 2026-06-24 17:17:28 -03:00
oobabooga
453efa7ae7 drop unused diffusion status 'loading' field; cap session gallery 2026-06-24 16:18:14 -03:00
oobabooga
1d42671659 match Train page slider/number-input style; restore card background on image rail 2026-06-24 16:11:34 -03:00
oobabooga
efdc5ad9a2 transparent image rail; hide fine-tuned shortcut; custom folders filtered to diffusion GGUFs 2026-06-24 16:00:17 -03:00
oobabooga
126e0f3792 hide fine-tuned, custom folders and local text models in the image picker 2026-06-24 15:49:09 -03:00
oobabooga
cf10955edb persist image gallery across tab switches; align model selector with chat 2026-06-24 15:38:26 -03:00
oobabooga
425d61e47a Z-Image-Turbo image generation with chat-style model picker 2026-06-24 15:32:56 -03:00
oobabooga
03132da8a8 Studio: move Images nav item below Hub 2026-06-24 14:17:29 -03:00
oobabooga
e8d3cfe2b5 Merge branch 'main' into image-generation 2026-06-24 14:07:59 -03:00
Long Yixing
a3954edd15
Fix Studio GGUF variant expansion crash (#6636)
* fix: handle empty GGUF variants

* fix: gate local GGUF expansion

* fix: normalize GGUF variant payload

---------

Co-authored-by: Lee Jackson <130007945+Imagineer99@users.noreply.github.com>
2026-06-24 15:39:20 +01:00
oobabooga
ab6c9ecfee
Studio: honor stream=false on the GGUF agentic tool path (#6570) (#6618)
* Studio: honor stream=false on the GGUF agentic tool path (#6570)

* Studio: dedup the #6570 non-streaming tool tests and cover cached_tokens

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

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

* Studio: cover the cached_tokens metadata fix and clarify the drain comment (#6570)

* Studio: align the GGUF tool drain naming and tighten its comment (#6570)

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Lee Jackson <130007945+Imagineer99@users.noreply.github.com>
2026-06-24 15:37:08 +01:00
Daniel Han
bd2438ea65
Verify DiffusionGemma visual-server binary against approved checksums (#6635)
ensure_diffusion_visual_server() downloaded the visual-server release
asset with the unverified download_file() and marked it executable,
bypassing the approved-checksum manifest that gates every other prebuilt
llama.cpp artifact. The backend later auto-discovers that binary and
launches it through DG_VISUAL_BIN, so a compromised or substituted
release asset could place attacker-controlled native code in the install
tree and have it executed under the Studio user.

Require the matched asset to be present in the approved checksum manifest
and download it through download_file_verified() with the published
sha256. A name-matching asset that is absent from the manifest is refused
rather than executed.

Add regression tests covering the verified-download path and the refusal
of an unapproved asset.
2026-06-24 06:37:41 -07:00
Nilay
e5cf956601
Studio: shareable per-checkpoint preview links (#6486)
* checkpoint preview endpoint

* harden new preview endpoints

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

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

* address review

* Studio preview: pin adapter, guard streaming submit, robust copy-link

Harden the public per-checkpoint preview surface:

- Pin use_adapter=True in the preview payload sanitizer. Otherwise an
  unauthenticated /p caller can POST use_adapter=false, which calls
  disable_adapter_layers() on the shared in-memory model without restoring
  it; since load_model skips reloads for the same checkpoint, every later
  visitor (the page never sends the field) keeps getting base-model output
  instead of the fine-tuned checkpoint. Forcing it on also re-enables a
  previously disabled adapter and no-ops on merged checkpoints.
- Ignore preview-page submits while a response is streaming. The send
  button was disabled but the Enter handler still called requestSubmit(),
  so a second request could start before the first reply landed in msgs and
  reorder the chat history. Both the keydown and submit handlers now honor
  the disabled button.
- Keep the cloudflare-URL polling loop alive across transient startup fetch
  errors instead of letting one rejection halt it.
- Build the copy-link from a backend preview_ref (output dir relative to
  outputs_root, gated on previewability and the two-segment /p route limit)
  so a nested output dir no longer copies a basename-only link that 404s.
  Expose preview_ref on training run summaries.

Add route-level security tests (path traversal, payload sanitization,
asset containment, CSP header, HTML title escaping, streaming lock held
until drained) and preview_ref unit tests.

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

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

* Studio preview: Safari-safe submit and adapter pin only for LoRA

Follow-ups from cross-browser and route simulations:

- Preview page: send the message from a shared send() helper called by both
  the form submit and the Enter key, instead of form.requestSubmit(). The
  latter throws on Safari < 16 and older iOS, which broke Enter-to-send there.
  Verified across Chromium, Firefox and WebKit with Playwright.
- Only pin use_adapter=True when the resolved checkpoint is a LoRA adapter
  (adapter_config.json present); for a merged checkpoint strip it to None.
  A merged model has no adapter to toggle, so forcing it on only produced a
  per-request "not a PeftModel" warning. The cross-request base-model
  contamination fix still holds for LoRA previews.

Add a merged-checkpoint test asserting use_adapter is stripped to None.

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

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

* Studio preview: trim verbose comments

Tighten comments across the preview routes, page, checkpoint helpers, and tests
to short single-line notes; drop ones that just restate the code. No behavior
change (verified comment/docstring-only with comment_tools.py check).

* Harden preview routes for PR #6486

- Return a generic 400 detail on a rejected preview path so the public /p
  route never echoes the absolute install path (the real reason is logged
  server-side instead).
- Strip confirm_tool_calls, session_id and rag_scope in the preview payload
  sanitizer so the public surface stays inert regardless of the tool gate.
- Use Path.is_relative_to for the asset containment check, matching the rest
  of the codebase.
- Add img-src 'self' and font-src 'self' to the preview page CSP.
- Preview page: on a mid-stream error keep the streamed text, flag the break,
  and restore the prompt so the user can retry; drop the unused --font-sans var.

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Lee Jackson <130007945+Imagineer99@users.noreply.github.com>
Co-authored-by: Daniel Han <danielhanchen@gmail.com>
2026-06-24 06:31:53 -07:00
Daniel Han
c7c353d740
Pin isolated Node.js installer to committed sha256 digests (#6625)
* Pin isolated Node.js installer to committed sha256 digests

The isolated Node installer verified each downloaded archive only against
SHASUMS256.txt fetched from the same nodejs.org origin as the archive, so a
compromised CDN or TLS path could serve a malicious archive plus a matching
checksum and gain code execution when the extracted node is run during the
npm floor check and version probe.

Anchor trust in studio/node_prebuilt_pins.json, a committed manifest of
per-arch sha256 digests, and verify archives against it. The default channel
installs the pinned version and never fetches the remote SHASUMS. Unpinned
lts, latest, or explicit versions fail closed via UnpinnedNodeRefused unless
UNSLOTH_NODE_ALLOW_UNVERIFIED=1, and the refusal is not swallowed by the
keep-existing-on-transient-failure path. Ship the manifest in package-data.

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

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

* Address review nits on the pinned Node installer

- Drop the unused npm_min_major field from node_prebuilt_pins.json; the floor is
  the NPM_MIN_MAJOR module constant and the dead field could silently drift.
- Reword the unpinned-refusal message so it does not tell a user already on the
  default to install it, and point the "add a pin" hint at the exact asset.
- Decode the opt-in SHASUMS body with errors="replace" so a non-UTF8 response
  yields a clean PrebuiltFallback instead of an uncaught UnicodeDecodeError.
- Tests: assert the refusal message (guards the main() catch order, not just the
  exit code), cover malformed-manifest parsing, and drive the opt-in remote-SHASUMS
  path end to end through install_prebuilt.

* Tighten comments in the pinned Node installer

Collapse multi-line rationale comments to single lines, drop docstrings on the
obvious internal helpers (load_pins, pinned_sha256), and shorten the manifest
note. Comments/docstrings only; verified code-unchanged via AST comparison.

* Address Codex review: verify pins on existing installs; tomllib fallback

- existing_install_matches now takes an expected_sha and the short-circuit passes
  the committed pin, so a version-matching but non-pinned or tampered install (e.g.
  from the old remote-SHASUMS path) is re-verified instead of kept. An unpinned
  target without opt-in no longer short-circuits on an existing install; it falls
  through to the UnpinnedNodeRefused fail-closed path.
- The package-data test uses pytest.importorskip(tomllib/tomli) so it does not
  ModuleNotFoundError on the supported 3.9/3.10 interpreters.

* Make the transient-failure keep-existing path pin-aware

The previous commit added the pinned-digest check to the existing-install
short-circuit but not to the post-download-failure fallback, which still kept any
runnable same-version install via existing_install_usable(). A same-version
install whose recorded sha256 is not the pin could therefore be kept on a
transient download failure, the exact artifact the short-circuit rejects. Refuse
to keep a same-version pin-mismatched install there too; a different usable
version is still kept for offline resilience.

* Bump pinned default Node to the current 24 LTS (24.18.0)

Node 24 LTS moved to 24.18.0; since the default channel now resolves straight to
the manifest, a frozen 24.17.0 would downgrade fresh installs and make
UNSLOTH_NODE_VERSION=lts refuse the current LTS as unpinned. Update default_version
and all six per-arch digests (verified against the official SHASUMS256.txt), and
point the test INDEX/short-circuit fixtures at the new LTS.

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-06-24 05:47:58 -07:00
Michael Han
8750d86cf7
Studio: keep the sidebar bottom fade in sync when groups collapse (#6640)
The fade is recomputed on a group's open/close state flip, but the groups
animate their height, so it measured scrollHeight mid-animation and the
fade could vanish at random. Re-measure on the collapsible animationend,
and add the missing pinnedOpen dep to the recompute effect.
2026-06-24 05:46:49 -07:00
Michael Han
61eb9eabd0
Studio: tighten the sidebar footer spacing and update-card fade (#6641)
Footer padding moves from pt-3 pb-4 to pb-3 with a conditional top: pt-1.5
when the update card is shown so the fade hugs it, pt-2.5 for the profile
on its own. When the update card is shown, shorten the fade above it
(h-10 -> h-3) so the list reads closer to the card.
2026-06-24 05:46:39 -07:00
Michael Han
0e2f9ce0b6
Studio: group the project export menu by Combined and Per chat (#6637)
* Studio: group the project export menu by Combined and Per chat

Replace the repeated (combined)/(per chat) suffix on every export row with a
section subheading, so the rows read Raw JSONL / CSV / ShareGPT JSONL under
Combined and Per chat headings.

* Studio: group export sections with DropdownMenuGroup

Wrap each Combined and Per chat section in DropdownMenuGroup for screen-reader
semantics, and drop the redundant px-3 already set by DropdownMenuLabel.
2026-06-24 05:08:15 -07:00
oobabooga
346d96d7f2
Studio: cap GGUF context to unified memory on Apple Silicon (#6622)
* Studio: cap GGUF context to unified memory on Apple Silicon

* Studio: tighten Apple ctx-cap comments and drop the overstated MLX-sync claim

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

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

* Studio: reserve flat MTP fraction and floor sparse-KV ctx in the Apple unified-memory cap

The Apple Silicon GGUF context cap mirrored the discrete-GPU auto-fit branch but
missed two protections the discrete path already applies:

- It passed the full unified-memory budget with budget_frac=1.0 without first
  reserving the flat MTP fraction the discrete path takes off via _pin_fraction.
  With an MTP draft whose KV cannot be byte-sized (e.g. Qwen3.6-MTP, #6529), the
  cap filled the whole budget and left nothing for the draft, so unified memory
  could still over-commit. Reserve _flat_mtp_reserve up front; this is a no-op
  when MTP is not engaged.

- It required _can_estimate_kv(), so a GGUF with sparse KV metadata skipped the
  cap entirely and launched at full native context. Mirror the discrete
  file-size-only fallback and floor the auto context to 4096 when the cache
  cannot be sized.

Adds regression tests for both paths.

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

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

* Studio: tighten comments in the Apple unified-memory context cap

Condense the verbose comment blocks in the Apple budget helper, the no-GPU
Metal branch, and the context-fit tests. Comments only, no code change
(verified with ast-based comment_tools check); suite still green.

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: danielhanchen <danielhanchen@gmail.com>
2026-06-24 04:39:33 -07:00
Michael Han
c3beb921f3
Studio: add Unsloth Docs to the MCP server presets (#6633)
Adds Unsloth's GitBook docs MCP endpoint as a keyless preset in the
composer MCP menu, alongside Context7, Exa and Hugging Face.
2026-06-24 04:22:31 -07:00
Daniel Han
b964d349fc
Clarify in README that studio --secure creates a public tunnel (#6632)
The Launch-section blurb described --secure as a secure HTTPS link
instead of a raw port and stressed that the raw port is never exposed,
which reads as the more private option. The Cloudflare tunnel actually
publishes Studio at a public trycloudflare.com URL, and server-side
tools let anyone with the API key run code. Reword to state the public
exposure and the code-execution caveat, matching the installer hints and
the Remote access section.
2026-06-24 04:03:12 -07:00
Saicharan Ramineni
9d53656614
Make _uv_safe_path space-safe on macOS/Linux (#6503) (#6534)
* Copy uv `-c`/`-r` paths to a space-free temp dir on macOS/Linux

uv 0.11.x truncates a constraints/requirements path passed via `-c`/`-r`
at the first space, so `unsloth studio` setup from a repo cloned under a
path containing a space (e.g. `/Users/me/Open Source/unsloth`) fails with:

    error: File not found: `/Users/me/Open`

_uv_safe_path() already worked around this on Windows via the 8.3 short
path but returned the space-containing path unchanged on macOS/Linux,
which have no 8.3 equivalent. Extend it to copy the (small, flat)
constraints/requirements file into a space-free temp dir and hand uv the
copy; the temp dirs are removed at process exit. Falls back to the
original path on any error, so it is never worse than before.

Refs unslothai/unsloth#6503

* Route UV_OVERRIDE through _uv_safe_path and fix temp-dir leak (#6503)

The -c/-r fix did not cover UV_OVERRIDE, which uv also truncates at the first
space. On Apple Silicon the overrides file is handed to uv via UV_OVERRIDE at
install time (install_python_stack.py) and during the MLX self-heal
(utils.mlx_repair), so a repo under a path containing a space still broke every
uv call there. Move _uv_safe_path into backend.utils.uv_path_safety so both
sites share it, and route UV_OVERRIDE through it.

Also stop leaking the temp dir when shutil.copyfile fails after mkdtemp, and add
tests for the UV_OVERRIDE channel, the TMPDIR-with-space fallback, the atexit
cleanup, and the no-leak path.

---------

Co-authored-by: danielhanchen <danielhanchen@gmail.com>
2026-06-24 04:02:24 -07:00
Daniel Han
d1529b1466
Tidy verbose Studio launch messages (#6628)
* Tidy verbose Studio launch messages

The reachability failure hint, the loopback deploy block, and the stop
hint were several lines longer than they needed to be, and the banner
printed a Tip line that just repeated the URL already shown above. Shorten
them while keeping the useful detail (cloud provider names, the SSH
local-forward workaround, the relaunch command, the trusted-network and
macOS Ctrl+C notes). No behavior change, output wording only.

* Refine launch-message wording after review

Apply review feedback so the launch messages read well for both experts
and general users:
- reachability hint: restore the 'from your own computer' cue and put the
  ssh command on its own line so it stops wrapping, name the cloud rules
  precisely (GCP firewall / Azure NSG rule), and restore 'in your browser'
- loopback banner: add the missing colon, drop the Ctrl+C duplication
  (the stop hint already covers it), and explain the exposure in plain
  language instead of 'exposes the API on every interface'
- stop hint: trim so it fits an 80-column terminal without wrapping
- replace two pre-existing em dashes with --
2026-06-24 03:49:19 -07:00
Daniel Han
fad89aecf9
Clarify Studio --secure hint exposes a public Cloudflare tunnel (#6615)
The installer/setup launch hints described --secure as merely allowing
HTTPS. In practice --secure forces a loopback bind and opens a public
Cloudflare quick tunnel (https://*.trycloudflare.com) to Studio, which
serves Python/terminal tools by default, so the old wording understated
the exposure. Update the hint to say it is a public Cloudflare HTTPS link
and that anyone with the API key can run code, matching the runtime
secure-mode banner.
2026-06-24 03:48:32 -07:00
Daniel Han
7a25266203
Fix _SameTaskStreamingResponse disconnect test bypassing __init__ (#6627)
* Fix _SameTaskStreamingResponse disconnect test bypassing __init__

test_same_task_response_closes_body_iterator_on_send_disconnect builds the
response via __new__ to skip Starlette's __init__, then wires body_iterator,
background, and stream_response by hand. It never set _unstarted_cleanup, so the
disconnect-before-first-chunk branch of __call__ raised AttributeError instead of
ClientDisconnect, failing the Backend CI "Repo tests (CPU)" job on main.

Set response._unstarted_cleanup = None in the manual construction, matching the
default __init__ assigns.

* Shorten the _unstarted_cleanup comment to one line
2026-06-24 03:47:35 -07:00
Michael Han
75166f2043
Studio: confirm saved Hugging Face token with a tick (#6630)
* Studio: confirm saved Hugging Face token with a tick

Pasting a token and clicking away saved it silently with no feedback.
Show a green tick in the field once a non-empty token is committed and
the input still matches the stored value, so the save is visible. Adds
the tokenSaved label to the en and zh-CN locales.

* Studio: let clicks pass through the saved-token tick

The decorative tick sat over the input and swallowed clicks, so clicking
it would not focus the field. Add pointer-events-none so clicks reach the
input; drop the now-unreachable title and keep an aria-label via role=img.
2026-06-24 03:47:32 -07:00
Michael Han
53c6ccc768
Studio: slim the GLM-5.2 thinking menu width (#6631)
* Studio: slim the GLM-5.2 thinking menu width

The high|max effort menu has short labels, so drop it from min-w-44 to
min-w-40 for GLM-5.2 only. Other models keep the wider dropdown.

* Studio: keep Preserve thinking menus at full width

Only narrow the effort menu when it has no Preserve thinking row. That
row is longer than the high|max labels and wraps to two lines at the
min-w-40 floor, so gate the skinnier width on no preserve-thinking.
2026-06-24 03:46:57 -07:00
Vineeth Sai
d42256a5c5
Fix construct_chat_template leaking {INPUT}/{OUTPUT} sentinel into the chat template (#6531)
* Fix construct_chat_template leaking {INPUT}/{OUTPUT} sentinel into the template

In construct_chat_template's inner process() helper, the branch handling a
section that starts with the {INPUT}/{OUTPUT} sentinel sliced the part from
part.find(which) (which is 0 in that branch), so the literal sentinel was
re-included in the generated Jinja chat template. The endswith branch already
slices correctly with part[:part.find(which)]; this slices past the sentinel
with part[len(which):], so a template whose input or output section begins
with the sentinel (for example a user turn that starts with {INPUT}) renders
correctly instead of emitting a literal {INPUT}/{OUTPUT}.

Added a regression test covering {INPUT}-leading and {OUTPUT}-leading sections.

* [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>
2026-06-24 00:40:53 -07:00
oobabooga
1237cd4d84
Installer: don't require cmake/Homebrew on macOS (prebuilt llama.cpp) (#6617) 2026-06-23 20:38:15 -03:00
Vineeth Sai
e3c7d4dc4c
Match IGNORED_TOKENIZER_NAMES case-insensitively (#6620) 2026-06-23 19:40:50 -03:00
Vineeth Sai
7dc0857267
Fix SyntheticDataKit.chunk_data dropping single-chunk documents (#6595)
* Fix SyntheticDataKit.chunk_data dropping single-chunk documents

chunk_data turns the n boundary points from np.linspace into n-1 ranges
via the boundaries[:-1] / [1:] pairing. When a document fits in a single
chunk (n_chunks == 1) that produces zero ranges, so the loop writes no
files and the whole document is silently dropped. Emit the full
[0, length] range when n_chunks <= 1; the multi-chunk path is unchanged.

Added a regression test covering the single-chunk and multi-chunk cases.

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

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

* chunk_data: emit nothing for an empty document (no empty chunk file)

Addresses review feedback: when the input document is empty (length == 0),
return no chunks instead of writing a single empty chunk file. Added a
regression test for the empty-document case.

* chunk_data: reject overlap >= chunk size (non-positive stride)

Per review feedback: when overlap >= max_tokens the chunk stride is
non-positive, which would divide by zero or silently emit one oversized
chunk. Raise a clear RuntimeError for that unusable configuration. Added
a regression test.

* Broaden single-chunk guard to length <= max_tokens (also fixes sub-overlap docs); expand tests

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

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

---------

Co-authored-by: oobabooga <112222186+oobabooga@users.noreply.github.com>
2026-06-23 16:39:38 -03:00
dependabot[bot]
86ec407f9b
Bump vite (#6354)
Bumps the npm-frontend-security group with 1 update in the /studio/frontend directory: [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite).


Updates `vite` from 8.0.10 to 8.0.16
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v8.0.16/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 8.0.16
  dependency-type: direct:development
  dependency-group: npm-frontend-security
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-23 16:58:59 +02:00
oobabooga
1cc785e5a0
Studio: remove OpenEnv and other unused packages (#6585)
* Studio: drop OpenEnv and unused ExecuTorch/open_spiel install deps

* Studio: drop 8 more unused install deps from extras

* Studio: restore tomli<3.11 for kernels; tidy dep-cleanup comments and tests

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

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

* Studio: refresh scan-packages baseline for scipy _external + unsloth-zoo tests

scipy moved its vendored array_api_compat from scipy/_lib to
scipy/_external, so the four allowlisted array_api_compat __init__.py
entries stopped matching and resurfaced as unsuppressed CRITICAL
"Downloads and executes remote code" findings on all three pip
scan-packages shards (extras, hf-stack, studio). Add the _external
paths next to the existing _lib ones so both scipy layouts stay covered.

Allowlist two unsloth-zoo test-file false positives now present in the
hf-stack shard: tests/test_mlx_save_export_regressions.py (writes to
/tmp dropper) and tests/test_mlx_trainer_internals.py (obfuscation plus
exec/eval).

Drop nine stale entries for packages removed from the Studio
requirements and no longer in any shard closure (evaluate, pytest,
hypothesis, kgb, langid), confirmed absent via with-deps resolution of
all three shards.

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Daniel Han <danielhanchen@gmail.com>
2026-06-23 07:20:47 -07:00
Wasim Yousef Said
8aa27f6db3
Update safe Studio Tauri cargo dependencies (#6612) 2026-06-23 16:15:00 +02:00
Daniel Han
61eef657e8
Harden MLX self-heal install against supply-chain code execution (#6599)
* Harden MLX self-heal install against supply-chain execution

The Apple Silicon MLX self-heal runs uv pip install on a daemon thread
during Studio startup, default-on with only an env opt-out, before the
post-install stack check. Two things widened the supply-chain surface:

- it accepted source distributions, whose PEP 517 build backends run
  arbitrary code at install time; and
- it forwarded the full process environment, exposing Studio secrets to
  that code and letting a poisoned env (UV_FIND_LINKS / UV_DEFAULT_INDEX)
  repoint the install at a hostile source.

Require pre-built wheels (--only-binary=:all:) and forward only an
allowlist of variables uv needs (PATH/HOME, proxy + CA settings, cache
dir), setting UV_OVERRIDE ourselves. mlx/mlx-metal ship wheels only and
mlx-lm/mlx-vlm publish py3-none-any wheels, so a healthy self-heal is
unaffected; an unavailable wheel just leaves Studio chat-only as before.

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

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

* Drop cache-dir env vars from the self-heal allowlist

Address review: a poisoned process env could set UV_CACHE_DIR / XDG_CACHE_HOME
to redirect uv at an attacker-staged cache (cache poisoning, symlink writes),
which partly undercut the index-redirect protection. Drop them from the
allowlist; uv falls back to its safe user-owned default cache, still reused
across runs, so there is no normal-path cost. Test now asserts both are
excluded from the install env.

* [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>
2026-06-23 07:02:14 -07:00
Daniel Han
b91cdc8793
Fix Qwen3 NaN loss: delegate pad_token repair to shared unsloth_zoo.pad_token (#6524)
* Fix Qwen3 NaN: self-heal vision pad_token in load_correct_tokenizer

Text-only Qwen3 (and Qwen2.5) models share Qwen3-VL's vocab, so their
Hub tokenizer configs ship <|vision_pad|> as pad_token. Padding text-only
training with a vision token corrupts attention/loss and produces NaN
losses and gradients on affected stacks.

patch_tokenizer already heals this, but only when a model with config is
passed. The standalone load_correct_tokenizer path (and custom training
loops) still returned <|vision_pad|>. This adds a model-independent guard
in load_correct_tokenizer that replaces a vision pad_token on text-only
tokenizers with the first safe text token (<|endoftext|>, <pad>, [PAD],
<unk>), falling back to eos_token only if it differs from pad_token.

The result now matches upstream Qwen configs (pad_token <|endoftext|>,
id 151643) with no new token added. Vision processors (image_processor
present) and non-vision pad tokens (Llama, Qwen2) are left untouched.

Fixes #3155

* Format pad_token helper for ruff kwarg-spacing hook (pre-commit)

* Harden vision pad_token fix: drop unk candidate, guard get_vocab, skip vision eos

* Tighten code comments (no logic change)

* Delegate pad_token fix to shared unsloth_zoo.pad_token

Generalize the narrow _fix_vision_pad_token by delegating to unsloth_zoo's
shared fix_pad_token (single source of truth, AGPL-3.0), which scans the
reserved-token families instead of only the vision-pad case. A guarded import
keeps this working against an older unsloth_zoo that has not shipped the module
yet: on ImportError it falls back to _fix_vision_pad_token.

allow_add=False is passed so the early load_correct_tokenizer call stays
side-effect free (no model here to resize embeddings); the later model-aware
patch_tokenizer call finishes the job and is idempotent.

Adds tests/python/test_pad_token_fix.py covering both dispatch paths offline.
2026-06-23 06:29:55 -07:00
Daniel Han
a963ec92e7
Fix CPOTrainer crash with multimodal processors (Gemma 4) (#6522)
* Fix CPOTrainer crash with multimodal processors

CPOTrainer shares build_tokenized_answer/tokenize_row and __init__ with
ORPOTrainer, but the ORPO replacement functions that route tokenization
through the underlying text tokenizer and resolve pad_token_id were only
registered for orpo_trainer. With a multimodal processing class (e.g.
Gemma4Processor) the positional self.processing_class(prompt, ...) call binds
prompt to images=, leaving text=None and raising
TypeError: 'NoneType' object is not subscriptable.

Register the existing orpo_trainer_text_tokenizer and
orpo_trainer_processor_pad_token under cpo_trainer as well so CPO/SimPO
fine-tuning of multimodal models works. No change for plain tokenizers.

* Add CPO processor tokenizer regression test

Static, CPU-only checks that cpo_trainer registers the same
orpo_trainer_text_tokenizer and orpo_trainer_processor_pad_token rewriters as
orpo_trainer, and that the rewriter drops the broken positional
self.processing_class(prompt, ...) call. Guards against issue #4952 regressing.

* Format CPO test assert for ruff line length (pre-commit)

* Bind CPO __init__ pad/eos token reads to underlying tokenizer

TRL 0.28+ CPOTrainer.__init__ reads bare processing_class.pad_token and
processing_class.eos_token before pad_token_id, which raises AttributeError
for multimodal processors (e.g. Gemma) where those live on .tokenizer.
Extend orpo_trainer_processor_pad_token to route that block through the
underlying tokenizer, and add a regression test.

* Tighten code comments (no logic change)

* Make CPO/ORPO rewriters reach the trainer on TRL 1.x

TRL 1.x moved CPOTrainer and ORPOTrainer out of trl.trainer into
trl.experimental.<algo> and dropped the trl.trainer.<algo>_trainer shim that
older TRL (0.26 - 0.28) kept. patch_trl_rl_trainers() discovers trainers via
dir(trl.trainer), so on TRL 1.x cpo_trainer and orpo_trainer are never found and
the multimodal-processor tokenization fix (#4952) silently stops applying, even
though the rewriters themselves still match the source.

Re-expose experimental-only trainers that Unsloth has rewriters for (RL_FUNCTIONS
keys) under trl.trainer before discovery, so the existing patch machinery and its
thin-wrapper resolution work unchanged. The alias is a no-op on older TRL where
trl.trainer.<algo>_trainer already exists.

Also rebind the patched Trainer/Config into every already-imported trl.* module
that holds the original class so the fix is visible at the experimental import
site (from trl.experimental.cpo import CPOTrainer), not only via trl.trainer.

Verified on transformers 4.57.6 + trl 0.22.2, transformers 4.57.6 + trl 0.27.1,
and transformers 5.12.1 + trl 1.6.0: CPOTrainer with a multimodal processor
tokenizes through the underlying text tokenizer with no crash on all three, and
the SFT/GRPO/DPO patch paths are unchanged.

* Format for ruff (pre-commit)

* Simplify CPO fix to mirror ORPO registrations (#4952)

Register the existing ORPO row-tokenizer/pad-token rewriters for cpo_trainer.
Under the trl<=0.24.0 pin CPOTrainer lives in trl.trainer.cpo_trainer (found by
dir(trl.trainer)), shares ORPO's build_tokenized_answer and uses
processing_class.pad_token_id, so the two registrations are sufficient.

Drop the trl 1.x experimental aliasing/rebind machinery in rl.py and the
bare-pad_token rewriter: trl 1.x (CPO in trl.experimental) and the bare
pad_token pattern (trl>=0.28) are not installable under the pin.

* CPO: route bare pad_token/eos_token default through inner tokenizer

TRL 1.x CPO/ORPO __init__ (the trl.experimental source unsloth resolves on TRL
0.26+) defaults processing_class.pad_token from processing_class.eos_token
before tokenizing. Multimodal processors (Gemma3/Gemma4 Processor) expose those
attributes on .tokenizer, not on the processor, so that bare access raises
AttributeError during __init__ even with the pad_token_id fallback registered.

Extend orpo_trainer_processor_pad_token to rewrite that defaulting block to run
on the inner tokenizer. The pinned TRL range (<=0.24.0) has no such block, so
the regex is a no-op there and only the existing pad_token_id fallback applies.

Verified the rewrite against the real trl 1.6.0 experimental CPOTrainer.__init__
(bare access removed, result compiles, a processor without pad_token no longer
raises) and added offline regression tests for both the rewrite and its no-op.

---------

Co-authored-by: Daniel Han <michaelhan2050@gmail.com>
2026-06-23 06:29:22 -07:00