Fixes#3931. After patching a TRL trainer, also patch the sibling config module (e.g. trl.trainer.grpo_config.GRPOConfig) to the Unsloth-patched config, so importing the config from its own module returns the patched class carrying unsloth_grpo_mini_batch. Defensive (try/except + hasattr) so it safely no-ops when no sibling config module exists.
Addresses review feedback on #5971. _reset_password_command() already
shell-quotes the launcher path on POSIX (shlex.quote), so wrapping the result in
another pair of single quotes in the error string produced a mangled hint for
installs / home dirs containing spaces, e.g.
Run ''/tmp/Unsloth Studio/.../unsloth' studio reset-password' in your terminal
which a shell mis-parses. Drop the outer quotes and put the command at the end of
the message so it is unambiguous and copy-pasteable in every case:
Incorrect password. To reset it, run this in your terminal: <cmd>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
* studio: redesign chat composer
Reworks the new-chat composer and the compare composer into a single
rounded pill surface with a softer, lighter look.
- New welcome screen with a time-of-day sloth mascot and a lighter
heading.
- One rounded composer surface with a soft drop shadow. The input grows
inline as you type and collapses back to a single row when cleared.
- Tools and attachments live in a single plus menu; the thinking control
is a compact pill with a reasoning-effort submenu.
- Inlined glyphs for the thinking, send, and dictate controls, kept in
sync across the main and compare composers.
- Toast notifications match the composer surface: no border line, the
same drop shadow, and the same dark surface color, with a ring-less
close button.
- Dark mode: the side-menu shadow blends into the background, hovered
menu rows read clearly, and their roundness matches light mode.
- Composer styles use dedicated unsloth- prefixed classes so compare
mode keeps its own stacked layout.
* studio: sync compare-composer reasoning state and harden compare id
- Compare composer: keep "Preserve thinking" consistent with reasoning,
matching the main composer. Enabling it now turns reasoning on, and
disabling reasoning (the None option or the Thinking toggle) turns it
off, so the invalid "preserve on while thinking off" state can't occur.
- Guard crypto.randomUUID in the Compare action. It is undefined in
non-secure contexts (HTTP over a LAN IP) and would throw; fall back to
a timestamped random id, matching createNavigationNonce.
* studio: reflect pre-selected Search/Code tools when no model is loaded
The Search and Code pills only lit up when the tool was usable right now
(a model loaded and capable), so a tool turned on from the + menu showed
as off in the pill while the menu showed it on. toolsEnabled is persisted
and takes effect once a capable model loads, so the pill should reflect it.
The pills now disable only when a loaded model lacks the capability, and
otherwise reflect the selected state. Applied to the main and compare
composers.
* Studio: link MCP Servers heading to its PR and fix composer pill cursors
Make the "MCP Servers" heading in the chat Configuration sheet link to the
MCP PR, keeping the chevron as the toggle. The label and chevron are rendered
as siblings so we don't nest an <a> inside a <button>.
Also add cursor-pointer to the composer pills and the thinking pill so hovering
a clickable pill shows the hand cursor instead of the default arrow.
* Studio: refine chat composer and add compare-mode parity
- Composer expands to two rows only once the input wraps to a second line,
not on the first keystroke. Re-measure the autosize textarea on the width
swap so expanding no longer leaves a stray blank row.
- Light-mode composer shadow now matches Gemini's soft elevation.
- Plus menu: replace Canvas with a More submenu (Canvas, Compare chat, RAG)
and add Code above MCP. Active Web search/Code items use medium weight.
- Compare mode: the plus side menu, Search/Code toggles, and a Compare exit
pill now match single chat, with the thinking control on the right.
- Projects menu entries link to their tracking PR (#5725).
- Add cursor-pointer to the composer plus button.
* studio: refine composer controls and chat search shadow
- Active tool pills show an x on hover to signal click-to-disable
- Plus button rotates into an x when the tools menu opens
- Composer surface uses a 32px radius and a taller single-line height
- Even, ChatGPT-style spacing between the plus and tool pills in both the single and compare composers
- Send and mic circles resized and spaced, with the arrow centered in the circle
- Chat search box gets a borderless, soft Gemini-style shadow
* studio: size the pill hover x to match the icon it replaces
Cross-engine checks (Chromium, Firefox, WebKit) flagged the active-pill
hover x as a fixed 14px, so it popped smaller than the 19px Code icon.
Fill the glyph slot instead so the x tracks whatever icon it covers.
* studio: do not persist Kimi search/thinking mutual-exclusion in single composer
The single-chat composer flipped the other control off when toggling
search or thinking on Kimi, but without { persist: false }, so it
overwrote the user's saved preference. Match shared-composer and keep
the side effect session-only.
* studio: pointer cursor on model selector trigger and menu items
Add scoped marker classes so the model picker trigger and every
clickable element in its menu (tabs, model rows, delete, eject) show a
pointer cursor; disabled items stay not-allowed.
* studio: pass baseUrl when resolving reasoning caps in single composer
The docked composer omitted baseUrl, so a custom Gemini OpenAI-compat
gateway still advertised the native thinking ladder the backend cannot
honor. Pass selectedExternalProvider.baseUrl like the compare composer
so the resolver hides it.
* studio: grey side-menu hover, green pill hover, thinking hover x
- Plus side-menu items hover grey in light mode, not the green accent
- Thinking pill hovers green like the Search and Code pills
- The plain Thinking toggle shows an x on hover when active, matching
Search and Code; the effort dropdown trigger keeps its bulb
* studio: make the pill hover x a uniform size
The x filled the icon slot, so the wider Code chevron gave a bigger x
than Search and Compare. Pin it to a fixed 15px, centered, so every
pill's x matches.
* studio: broaden chat attachments, fix active hover color, gemini shadow
- Accept svg, source code and many text/config files as drag-and-drop
or picked attachments, matched by extension since their MIME is
unreliable; html keeps its own adapter
- Active (green) side-menu items keep their text and icon color on
hover instead of switching to the accent color
- Composer surface uses Gemini's soft centered shadow 0 0 20px rgba(0,0,0,0.04)
* studio: keep the thinking pill full height when icon-only
The inactive thinking pill has no label, so its flex row collapsed to
the icon height and the hover box looked short. Reserve one text line
(min-height: 1lh + padding) so it matches the Search and Code pills.
* studio: refine composer menu, drop overlay and greetings
- Open the MCP servers dialog directly from the composer plus menu
- Redesign the drag-and-drop affordance Gemini style, drop the badge and border, make the whole chat page a drop target
- Swap in Hugeicons for the RAG, attachment chip and new project icons
- Add time-based randomized welcome greetings, each matched to a fitting sloth
* studio: rename artifacts toggle to Canvas and make it opt-in
- Label the toggle Canvas everywhere, matching the plus menu
- Stop greying out the Canvas menu item; it toggles like the other items
- Only show the Canvas pill in the composer row once it is turned on, since it is less central than Search and Code
* studio: wire Canvas and MCP composer toggles, even out the pill row
- Open the MCP servers dialog from the menu, or toggle MCP on/off once a server is enabled
- Force MCP off when no server is enabled, so the toggle stays honest
- Show Canvas and MCP as opt-in pills that appear in the order they were toggled on
- Expand the composer and light up the pill when Canvas or MCP is on, like Search and Code
- Keep Compare directly after Code in the compare composer
- Use the same Code icon on both composers and give every pill an even icon slot
* studio: tidy composer toggle row and fix MCP enable/disable lifecycle
- Enable MCP automatically after a server is configured via the toggle flow
- Force MCP off everywhere once the last enabled server is removed
- Collapse the pill labels to icons only when more than 4 pills show, keeping Compare labelled
- Order Compare first in compare mode, before Search and Code
- Use the same Code icon and an even 19px icon slot across both composers
- Match the compare composer surface padding and send button inset to normal chat
* studio: revert compare composer padding change that cramped the input
Matching the surface padding to normal chat clipped the textarea text and
left a white strip on top. Restore the compare composer's own padding, which
gives proper top spacing. The send button inset fix stays.
* studio: center welcome greeting and soften composer scrollbar
Center the sloth and title together over the composer instead of
shifting the row left, which left the greeting sitting off to the side.
Keep the composer textarea scroll thumb faint by default and only darken
it when the thumb is hovered or dragged, so a tall draft no longer shows
a heavy dark rail.
* studio: match composer plus-menu tool gating to the pills
The new plus-menu tool entries did not carry the gating the visible pills
already enforce, so the menu and pills could disagree about a loaded
model's capabilities.
- Web search and Code menu items now disable when a loaded model lacks
the capability, while still allowing preselection with no model loaded.
- Enabling Web search from the menu on a Kimi model now flips thinking
off as a session-only change, since Kimi forbids search and thinking
together. This matches the Search pill.
- Added an Images menu item, shown only for image-generation models and
disabled until a model loads, so a short prompt has an entry point.
Applied to both the single-chat and compare composers.
* studio: round the active-pill hover x and even out pill padding
The hover x sat bare and the trailing label was tighter to the pill edge
than the leading icon, so the pill looked lopsided.
- Give the hover x a soft circular background that fills the icon slot,
matching the ChatGPT-style toggle and the icon it replaces.
- Add a little more trailing padding so the label and the leading icon
have even breathing room, and keep icon-only compact pills symmetric.
* studio: nudge the thinking bulb icon up by 0.5px
Bump the thinking lightbulb from 15px to 15.5px in the single-chat and
compare composers so it sits a touch larger next to the other controls.
* studio: drop the hover x circle on icon-only pills
When pills collapse to icon-only, the circle around the hover x is too
cramped in the small chip, so show a bare x there and keep the circle
only on the full-width labelled pills.
* studio: space the compare send button like normal chat
In compare mode the Thinking control sat right against the send button.
Match the normal composer's control spacing (gap-1.5 plus a send margin)
so Thinking has the same breathing room before send. The send button
keeps its 14px inset, so its position is unchanged.
* studio: make collapsed pill hover a circle, not a wide pill
Icon-only pills were wider than tall, so their rounded-full hover
highlight read as a fat rounded rectangle. Make the compact button a
square and center the glyph so the hover (and the x it reveals) sits in
a clean circle.
* studio: fix compare pane drops and audio picker lifetime
- Skip the page-level drop handler when the composer is hidden, so files
dropped on a compare pane are not swallowed by a hidden composer; the
shared compare composer keeps handling drops through its own dropzone.
- Build the audio file input on document.body instead of inside the plus
menu, so the menu closing on select no longer unmounts the input before
the OS picker returns and drops the file.
* studio/chat: stop projects list from white-screening on older backends
The projects list API returned data.projects directly, so a backend that
omits the field handed back undefined. useChatProjects cached that value,
then the next mount read undefined.length and crashed the whole chat page.
Default the projects and threads list APIs to an empty array and keep the
hook null-safe so a bad response can never poison the cache.
* studio/chat: align MCP dropdown with the + menu and add a chevron
Reuse the + menu surface (unsloth-plus-menu) for the MCP dropdown: rounded
corners, narrower width, neutral grey hover, and enabled rows shown as green
text with a right-aligned check instead of the emerald underlay. Add a
chevron to the MCP pill so it reads as openable, matching the Thinking pill.
* studio/chat: make MCP an opt-in pill and fix its dropdown placement
- MCP is back in the + menu as a toggle. The pill now only shows in the
composer when MCP is on, matching Canvas, instead of always sitting there.
- The dropdown follows the composer side like the + menu (opens down in the
welcome composer, up when docked) rather than always opening upward.
- Drop the dropdown caret when pills collapse so the icon is not squished.
- Stop force-syncing mcpEnabledForChat to the server count; the + menu owns it.
* studio/chat: MCP expands the composer, drop sidebar Compare, tidy scrollbars
- Toggling MCP now expands the composer and shows the tool pills, the same as
Canvas, instead of leaving the row collapsed.
- Remove the Compare item from the sidebar now that it lives in the + menu, and
point the compare tour step at the side-by-side view instead of the old button.
- Both sidebars only show their scrollbar on hover, and run settings reserves
the scrollbar gutter so the close button no longer shifts when it appears.
* studio/chat: tighten toggle gap, fix run-settings close button, collapsed Train
- Reduce the composer toggle gap by 2px (gap-1 to gap-0.5) in both composers.
- Move the run settings header out of the scroll area so the close button keeps
its position whether or not the scrollbar shows, and sits flush with the
topbar open button again instead of shifting left.
- Surface Train as an icon in the collapsed sidebar (it already has a labelled
section when expanded).
* studio/chat: tighten Thinking pill X padding, create projects inline
- The Thinking pill used px-2.5, so the hover X sat further in than the left
pills. Match their pl-2 so the X lines up.
- The + menu New project now opens a create dialog and jumps straight to the
new project, instead of routing to the projects list. Shared by both
composers via a small NewProjectDialog.
* studio/chat: soften account menu, hover scrollbars, show collapsed chevrons
- Account menu drops its border ring for the composer's soft shadow and opens
centered over its trigger.
- Settings and search reuse the hover-only scrollbar via a shared
hover-scrollbar class, matching the sidebars.
- Train and Recents keep their chevron visible while collapsed so it is clear
they can be expanded.
* studio/chat: roomier, more rounded account menu
Widen the account menu, add more left and right padding on the rows, bump the
row height and text a touch, and round the corners more, closer to the GPT
account menu.
* studio/chat: trim account menu width and nudge it up 2px
Pull the account menu in slightly on the left and right (narrower box, a touch
less row padding) and lift it 2px higher above the trigger.
* studio/settings: drop outline ring, circular close hover, pointer cursors
- Remove the settings dialog outline ring, keeping just the soft shadow.
- The close button hover is now a circle instead of a rounded rectangle.
- Every clickable control in the settings dialog uses a pointer cursor.
* studio/chat: bump MCP pill icon to 14.5px
Nudge the MCP icon up 0.5px so it sits even with the other pill glyphs.
* studio/chat: bump MCP pill icon to 15px
Nudge the MCP icon up another 0.5px.
* studio/settings: add a Settings title above the tabs
Put a Settings heading at the top of the sidebar so the tabs sit below it,
matching the Claude settings layout. Hidden on mobile where the nav is a row.
* studio/settings: rounder tab hover, bigger title, less-round search dialog
* studio/sidebar: round nav row hover boxes 2px more (10px to 12px)
* studio: drop settings dark shadow + divider, add tab left padding, tune hover roundness
* studio/model-selector: roomier padding, borderless box, rounder hover rows; settings divider light-only
* studio/search: match chat box shadow (soft light, none dark)
* studio/sidebar: borderless chat context menus, rename submenu to Projects with folder-export icon
* studio/model-selector: match light corner radius in dark, drop dark shadow, more visible dark hover
* studio/sidebar: chat context menu matches + side menu styling; relabel submenu Move to project
* studio: borderless message export menu (no dark shadow), match dark corner radius to light on export menu and settings
* studio/sidebar: open chat options menu GPT-style (down-right) and widen so Move to project fits one line
* studio/chat: message export menu uses the chatbox shadow in light mode
* studio/sidebar: narrow chat options menu slightly (w-60 to w-56)
* studio: unify all download icons to Hugeicons download-01; round profile button hover 1px more
* studio/run-settings: bump header to 16px
* studio/sidebar: trim chat options menu width slightly (w-56 to 216px)
* studio/sidebar: trim chat options menu width to w-52
* studio/profile: camera-01 Hugeicons glyph and chatbox shadow on avatar button
* studio: match dark-mode corner radius to light globally (single --radius token)
* studio/recipes: borderless New Recipe menu with chatbox shadow in light, none in dark
* studio: borderless dropdowns globally, chatbox shadow in light, none in dark
* studio: extend borderless + chatbox/none shadow to select, combobox and popover overlays
* studio/mcp: nudge MCP dropdown radius to 20px so its wider box reads as round as the + menu
* studio: restore dark dropdown shadow to avoid same-color merge; greet name ~1/3 of lines; bigger sloth + more gap
* studio/train: active tab is a borderless pill (no underline), roomier padding, more tab gap and bottom spacing
* studio/chat: nudge welcome up ~5px (still vh-based) and trim sloth image to 44px
* studio/train: active tab pill is white with chatbox shadow in light, taller padding
* studio/chat: welcome offset to calc(30vh - 10px)
* studio/chat: welcome offset to 28vh (drop the -10px)
* studio/chat: tighten sloth-to-text gap by 1px (16px to 15px)
* studio/train: revert light active pill to grey fill, drop white bg + shadow
* studio: app-wide hand cursor on every clickable control (disabled excluded)
* studio/chat: welcome offset to 26vh
* studio/chat: welcome offset to 28vh
* studio/chat: harden project and thread list guards against non-array payloads
* studio/sidebar: give the profile row more height and breathing room
* studio/sidebar: trim the profile row top and bottom padding slightly
* studio/sidebar: reduce Train and Recents section label size slightly
* studio/sidebar: trim the profile row top and bottom padding a touch more
* studio/sidebar: enlarge the profile hover area top and bottom
* studio/sidebar: increase profile hover roundness by 1px
* studio/sidebar: trim the profile row top and bottom padding slightly
* studio/sidebar: trim the profile row top and bottom padding slightly
* studio/chat: cache composer line metrics so wrap detection runs once, not per keystroke
* studio/chat: restore the prior view when exiting compare opened from the + menu
* studio/tests: drive Compare from the composer + menu after it moved out of the sidebar
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* studio/tests: open Compare from the composer + menu in the extra UI suite too
* studio: fix chat dictation microphone access
* studio: snappier plus-to-x spin and steady composer expand gap
Speed up the composer plus icon morph from 480ms to 300ms.
Add row-gap on the expanded composer line so the space between the text
and the controls row stays the same whether the box expanded from
wrapped text or from a toggle being on. The gap sits on the line, not the
input, so the placeholder max-height clamp never crops it.
* studio: only show composer tool pills once a model is loaded
Persisted Search/Code/Canvas/MCP toggles were surfacing the composer pill row on a fresh page load before any model was selected, so an empty composer looked different from the clean just-ejected state. Gate the composerExpanded tool checks on modelLoaded so a model-less composer stays collapsed, while saved preferences still apply the moment a model loads.
* studio: hide RAG composer menu item temporarily
Hide the placeholder RAG entry from the composer plus menu in both single chat and compare until the feature is ready, and drop the now-unused DatabaseIcon import.
* studio: let composer tools pre-select before a model loads
Selecting Web search, Code, Canvas or MCP from the + menu with no model
loaded did nothing visible: the toggle turned on but the composer never
expanded, so the pill stayed hidden. Drop the model-loaded gate from the
expand check so an active tool always surfaces its pill.
Align MCP with the Search/Code pattern too: grey it out only when a loaded
model lacks tool support, so MCP stays toggleable and the pill stays
clickable before a model is loaded instead of looking disabled.
---------
Co-authored-by: Unsloth <michaelhan@Michaels-MacBook-Pro.local>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: wasimysaid <wasimysdev@gmail.com>
Co-authored-by: Lee Jackson <130007945+Imagineer99@users.noreply.github.com>
Co-authored-by: Daniel Han <23090290+danielhanchen@users.noreply.github.com>
* Logging cleanup
* [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>
* Update Install Scripts
Add SPDX AGPL-3.0 headers to the installer scripts and let the piped web
installs take their common options from the environment.
- install.sh / install.ps1: read UNSLOTH_NO_TORCH (and UNSLOTH_PYTHON for
install.sh) so a piped install needs no positional flags. Flags and the
pipe forms still work; an explicit flag wins.
- Fix the UNSLOTH_STUDIO_HOME example so the variable sits after the pipe
and reaches sh instead of curl.
- Add SPDX headers to install.sh, install.ps1, the uninstall scripts, and
the MLX install scripts.
- Drop the internal test package names from the studio install comments.
* Mirror UNSLOTH_PYTHON env var to install.ps1
install.ps1 now reads UNSLOTH_PYTHON to pin the Python version, matching
install.sh, and lists all three env vars (UNSLOTH_NO_TORCH, UNSLOTH_PYTHON,
UNSLOTH_STUDIO_HOME) in the header examples. The requested version is
preferred during detection and used as the winget install target; behavior
is unchanged when the variable is unset.
Add copyable per-platform examples for UNSLOTH_NO_TORCH, UNSLOTH_PYTHON and
UNSLOTH_STUDIO_HOME (curl | sh after the pipe; $env: before irm | iex), and
move the UNSLOTH_CPU_THREADS note to the end of the section.
The Studio login error rewrote the backend's PATH-based command into a relative Windows path (.\unsloth_studio\Scripts\unsloth.exe ...) that only resolves from inside the Studio home dir and fails with CommandNotFoundException elsewhere. Removes the Windows-only rewrite and the now-unused usePlatformStore import so the backend's unsloth studio reset-password command is shown as-is on all platforms.
Clears the safe set of Dependabot advisories.
Frontend (overrides, all transitive; npm audit now 0):
mermaid 11.14.0->11.15.0, hono 4.12.17->4.12.18, qs 6.15.1->6.15.2,
ip-address 10.1.0->10.1.1 (also clears express-rate-limit), and
brace-expansion 5.0.5->5.0.6 (scoped, the 1.1.14 line is untouched).
Desktop: tauri 2.10.3->2.11.1, pulling the runtime crates it requires
(tao, wry, tauri-runtime, tauri-build, tray-icon).
Backend (test-only): pytest <9.0 -> >=9.0.3,<10, and the pinned
pytest-rerunfailures==15.1 -> >=16.2,<17 (16.2 is the first release with
pytest 9 support). Verified pytest 9.0.3 + rerunfailures 16.3 +
pytest-json-report + pytest-xdist run reruns, fixtures, json reports and
xdist together.
Left out intentionally: transformers (stays 4.x for unsloth compat; patch
is 5.0.0rc3), sqlfluff (major 3->4), glib/rand (stack-coupled transitive).
Fixes#5572. Replaces cmdk's default fuzzy filter with a strict substring-token filter so threads that do not match the query are hidden and the empty state shows. Each item uses its unique thread id as the cmdk value, with the searchable title and preview supplied via keywords.
Adds studio/backend/utils/datasets/dataset_none_detect.py, a standalone scanner that reports None/empty content turns in alpaca, chatml, sharegpt, and gptoss datasets without modifying data, plus generator and runner scripts under tests/utils. Depends only on the datasets library and is not wired into the package init, so it stays import-light.
* Studio: persist Tauri window size and maximized state across launches
* Studio: keep window state under the app home dir, not ~/.config
* Undo an unnecessary change
* Address Gemini's feedback
* Revert to tauri-plugin-window-state implementation
* fix(Studio): restore saved window size before default layout
* Fix cross-platform window-state restore
* fix(Studio): avoid clobbering saved window size
---------
Co-authored-by: Wasim Yousef Said <wasimysdev@gmail.com>
Co-authored-by: Lee Jackson <130007945+Imagineer99@users.noreply.github.com>
* studio: cap training dataset uploads
* studio: clean up failed dataset uploads
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* studio: raise upload limits to 500MB
* studio: make upload limit configurable
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* studio: stream upload routes
* studio: split recipe upload caps
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* studio: tighten upload limit handling
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* studio: import settings router directly
* studio: polish upload cap setting control
* studio: cap settings request bodies
* studio: stub settings route in desktop auth test
---------
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
* fix: toast cancel and style
* fix: align model load toast Cancel and dismiss on the right
* fix: show short cased model name in loaded toast and removed prefix org
* revert: chat load toast refactor to visual-only changes
* fix: align model load toast close button
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* Studio: guard empty toast label and dedupe toast padding CSS
---------
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Roland Tannous <rolandtannous@gravityq.ai>
Co-authored-by: Roland Tannous <115670425+rolandtannous@users.noreply.github.com>
* feat: align project sidebar UX with ChatGPT
* feat: align project sidebar UX with ChatGPT
* feat(chat): load stored project list
* feat(chat): add project sidebar workflows
* fix: stabilize project page navigation
* fix: projects chat loading
* fix: show project chat thread
* style: sidebar project spacing and hover clipping
* style: add expandable project chat history and move-to-project submenu
* feat: polish project sidebar
* feat: persist project sandbox paths
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* fix: only create sandbox project workspace dir
* feat: add optional project workspace deletion from delete dialog
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* fix: stabilize chat projects CI failures
* fix: polish project chat navigation
* Studio: manage chat history with projects
Group chats into projects with a dedicated projects page and route.
Sidebar shows recents with per-row actions and a vertical more-vertical
menu, and the sidebar scrollbar stays hidden so rows never shift on
hover. Includes chat settings and composer refinements.
* Studio: projects sidebar and breadcrumb polish
Sidebar:
- Remove the Compare nav item.
- Widen the sidebar to match the projects layout.
- Replace the scroll-gated bottom fade with a static fade pinned above
the profile box, so it no longer attaches to Recents or lags the
collapse and expand animation.
Topbar breadcrumb (chat-page):
- On a project landing show "Projects" linking to the projects list.
- Inside a project chat show the project name and chat title, with the
project name linking back to that specific project page.
- Drop the divider between the model selector and the breadcrumb.
* Studio: make project workspace delete test cross-platform
test_chat_project_delete_files_removes_workspace rooted the project under
pytest tmp_path, which resolves to /private/tmp on macOS. The workspace
delete guard refuses paths under the system denylist by design, so the
test passed on Linux CI but failed on macOS.
Add a workspace_projects_home fixture that keeps tmp_path on Linux and
Windows (CI unchanged) and falls back to a home subdir only when the temp
root is on the platform denylist. Derive the workspace path from the
created project so it tracks the projects home.
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* Studio: satisfy import-hoist check for new path re-exports
documents_root and project_workspaces_root are re-exported from
utils.paths but only referenced as __all__ string literals, which the
import-hoist safety net does not count as a use. It flagged the two newly
added re-exports as unused imports and failed Source lint.
Name-load both via a module-level _REEXPORTED tuple so the check sees
them used. No behaviour change; consumers still import them from
utils.paths.
* fix: avoid projects empty-state flash
* fix: batch chat search indexing
* Studio: polish chat sidebar, run settings, and search
- Use the native OS scrollbar for the chat sidebar, Run settings panel, and chat search list instead of a custom scrollbar
- Highlight the active run in the sidebar and keep chat search available during training
- Stop the training log view from replaying when navigating back to a run
- Rename the chat settings panel to Run settings and align its toggle icon and position
- Tighten heading and sidebar letter spacing and lighten the Train and Recents labels
- Match the search dialog corner style across light and dark and drop the stray border
- Make the MCP Servers section header plain text instead of a link
- Remove a stray .orig backup file
* studio/frontend: restore Compare entry point in the sidebar
The chat-projects sidebar redesign dropped the Compare nav item and moved
it to thread-sidebar.tsx, which is not imported or rendered anywhere. That
left no way for a user to start a new model comparison (enterCompare only
fired from the guided tour and the training handoff), and broke the
Compare/Recipes/Export UI smoke test that clicks [data-tour="chat-compare"].
Re-add the Compare NavItem to the New Chat / Search group, carrying
data-tour="chat-compare" and the same new-comparison navigation as before.
* studio/frontend: use Unsloth green for the fallback profile avatar
Switch the initials-avatar background from blue to #14b789 so the sidebar
and edit-profile avatar match the Unsloth brand colour.
* studio/frontend: turn project breadcrumb into a project switcher dropdown
* studio/frontend: stop project card kebab clicks from opening the project
* studio/frontend: hide project switcher outside projects
* studio/frontend: stabilize project switcher loading
* style: project switcher alignment
---------
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: shimmyshimmer <107991372+shimmyshimmer@users.noreply.github.com>
Co-authored-by: Unsloth <michaelhan@Michaels-MacBook-Pro.local>
Co-authored-by: Roland Tannous <rolandtannous@gravityq.ai>
Co-authored-by: Roland Tannous <115670425+rolandtannous@users.noreply.github.com>
* fix: support connected models in compare mode
* fix: support connected models in compare mode
* studio/frontend: wait for compare prompt append
---------
Co-authored-by: Roland Tannous <115670425+rolandtannous@users.noreply.github.com>
Improve the rejection message when an MCP server address is not an http(s) URL. It now points to the expected http(s):// form with an example, and only mentions that local commands are disabled when the value contains whitespace (a reliable command signal), since a lone token may just be a scheme-less URL. Wording is host-scoped rather than desktop-only because self-hosted hosts can opt in via an env var. Backend only, with tests; accepted input is unchanged.
Move MCP from the chat settings sidebar to a composer pill next to Artifacts. The dropdown lists keyless presets (Context7, Exa, Hugging Face), all off by default, created on first enable and deduped by URL. Add custom MCP opens the existing manage dialog. Enabled rows show a green underlay and a tick that becomes an X on hover to remove; enabling Exa turns off the built-in Web Search and shows a hover tooltip. Reconciles the per-chat MCP flag on load so already-enabled servers activate the pill. No backend changes.
* Studio: cover B300 (sm_103) with the Linux prebuilt bundles
sm_103 (B300 / GB300 Blackwell Ultra) was in no bundle's supported_sms,
so those hosts fell through to a slow source compile. The newer and
portable bundles already ship base compute_100 PTX, which the driver
JIT-compiles forward to sm_103, so list sm_103 alongside sm_100 in those
bundles and let B300 install the prebuilt.
* [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>
setup.ps1 already forwards --has-rocm whenever AMD is detected regardless
of whether gfx resolved. setup.sh only forwarded --rocm-gfx, so a Linux
host where AMD was detected but gfx resolution failed would forward nothing,
leaving the installer with has_rocm=False and falling back to a source build.
Add the elif branch to forward --has-rocm when _setup_amd_detected is true
but _setup_gfx is empty, matching setup.ps1 parity. Add a source-level test
to verify both flags are present in setup.sh.
The 'Collect llama-server logs' diagnostic step copies llama-server stdout into
the workspace for debugging. On the Windows runners it intermittently dies with
exit code -1073741502 (0xC0000142, STATUS_DLL_INIT_FAILED) when spawning the
copy, which failed the whole Tool calling Tests job even though the tests had
already run.
It is a diagnostic-only step, so mark it continue-on-error in all three jobs, the
same treatment #5913 gave the artifact-upload steps. A transient log-collection
crash no longer turns a green job red.
Refs #5913.
setup.sh and setup.ps1 resolve the AMD gfx target (rocminfo/hipinfo/amd-smi,
name inference, or UNSLOTH_ROCM_GFX_ARCH) but never passed it to
install_llama_prebuilt.py. The installer re-probed on its own and, on hosts where
hipinfo/amd-smi cannot report the arch (amd-smi-only Linux, HIP-runtime-only
Strix Halo, name-inferred GPUs), left rocm_gfx_target unset. The lemonade HIP
prebuilt selection needs that arch, so those hosts got no GPU prebuilt and fell
back to a source build.
Add a --rocm-gfx argument (defaulting to UNSLOTH_ROCM_GFX_ARCH) and fold it into
the host profile via _apply_host_overrides: a forwarded gfx is authoritative
(setup already applied visible-device selection) and implies has_rocm. setup.sh
and setup.ps1 now forward their resolved arch.
Add unit tests for _normalize_forwarded_gfx and _apply_host_overrides, plus
source checks that both setup scripts forward --rocm-gfx.
The deferred Windows CUDA Toolkit check (Resolve-CudaToolkit in setup.ps1) has a
pwsh unit test but nothing ran it. Rather than add a separate workflow, fold a
fast GPU-free gate into the existing Windows GGUF CI: parse setup.ps1 and run
tests/studio/test_resolve_cuda_toolkit.ps1 right after checkout, before the heavy
GGUF smoke, so a setup.ps1 regression fails fast on the runner that is already
spun up.
Refs #5912.
* Studio: fall back to source build for arm64 Linux GPU hosts
setup.sh routes a Linux host with any GPU tool to the unslothai/llama.cpp fork,
which publishes only linux-x64 bundles. On an arm64 host with a GPU (GH200,
GB200, DGX Spark) the resolver then selected an x64 CUDA bundle, which cannot run
on aarch64. Routing those hosts to ggml-org instead would install a CPU-only
arm64 build, silently losing the GPU.
Guard resolve_simple_install_release_plans so an arm64 Linux host on the fork
raises PrebuiltFallback before any release is fetched, letting setup.sh do a
source build that actually targets the GPU. x86_64 hosts and arm64 CPU hosts
(which route to ggml-org) are unaffected.
Add tests covering the arm64 fork raise, the x86_64 pass-through, and the arm64
CPU ggml-org path.
* Studio: install ggml-org arm64 CPU prebuilt when the arm64 GPU source build fails
Per review of #5924: arm64 Linux GPU hosts have no CUDA prebuilt anywhere (the
unslothai fork is x64 only, ggml-org ships no Linux CUDA build), so they source
build for the GPU. If that build produces no binary, the host was left without
llama.cpp.
Add a --cpu-fallback flag to install_llama_prebuilt.py that drops the host GPU
attributes so the CPU prebuilt for the host arch is selected (a GPU host cannot
otherwise pick the CPU bundle). setup.sh calls it against ggml-org as a last
resort for arm64 Linux when the source build degraded, installing the
ubuntu-arm64 CPU build instead of leaving the host with no llama.cpp.
Add tests: force_cpu drops GPU attrs before planning, a CPU-forced arm64 host
selects the ggml-org ubuntu-arm64 bundle, and setup.sh wires the fallback.
* [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>
The pinned b9360 cuda-13.1 Windows fallback for Blackwell (sm_120) only fired
when the driver advertised CUDA >= 13.1. The mainstream Blackwell branch ships
the r580 driver that reports CUDA 13.0, so those hosts missed the pin, were
gated off the in-release 13.3 build, and dropped to the CPU-only cuda-12.4
build.
b9360's binary is native sm_120a SASS (no PTX, so no JIT) and its bundled
runtime is cuda-13.1 cudart; both run on a 13.0 r580+ driver under CUDA
minor-version compatibility. Lower _PINNED_BLACKWELL_DRIVER_FLOOR to (13, 0) so
the pin covers the 13.0 branch too. The generic published-runtime gate stays
conservative (an unverified in-release 13.1 build is still gated off 13.0); only
the specific, hash-pinned, SASS-verified b9360 build is extended.
Refs #5887.
* Studio: match the Linux llama.cpp prebuilt to the runtime cudart major
* [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>
* Studio: defer the Windows CUDA Toolkit check so prebuilt users are not blocked
setup.ps1 section 1e validated the installed CUDA Toolkit against the driver in
Phase 1 and hard-exited when the toolkit was newer than the driver supports.
That ran before the prebuilt llama.cpp install (Phase 3.4), which is
self-contained and needs no local toolkit. A Blackwell host (sm_120) on a driver
that advertises CUDA 13.2 with CUDA Toolkit 13.3 installed was blocked entirely,
even though the prebuilt selector would have given it a working GPU build.
The toolkit (nvcc) is only consumed by the Phase 4 source build. Move section 1e
into a Resolve-CudaToolkit function and call it lazily at the source-compile
branch, gated on $HasNvidiaSmi. The prebuilt path no longer touches the toolkit;
forced/source builds keep the identical requirement, winget auto-install, and
error text via -RequireOrExit.
Add a pwsh unit test that extracts the real function and runs it against a
spoofed Blackwell sm_120 / driver 13.2 / toolkit 13.3 host: the prebuilt path
defers, the forced build still fails fast.
Refs #5879.
* Studio: correct a stale Phase-1 prerequisites comment (CUDA Toolkit is now resolved lazily)
* Studio: retrigger Windows GGUF CI (artifact upload flake)
Extracts the real guard block from install.sh and asserts: clean arm64 venv
untouched, x86_64 venv rebuilt as arm64, the x86_64-then-3.13.8 corner case,
arm64 3.13.8 downgrade preserved, --python skip, and Intel/Rosetta no-op.
Co-authored-by: Ramakrishna Bachu <ramankrishna10@gmail.com>
On Apple Silicon, uv can create the venv from a cached x86_64 (Rosetta)
Python, so the venv reports x86_64 to wheel resolvers and the torch install
never resolves (the CPU index ships no macOS wheels). Detect an x86_64 venv
on an arm64 host and recreate it with an arch-explicit arm64 CPython,
re-inspecting before the existing 3.13.8 check so both invariants hold.
Skipped when --python is set; non-macOS, Intel, and healthy arm64 venvs are
unaffected.
Co-authored-by: Daniel Han <danielhanchen@gmail.com>
* Studio: pin the last pre-macOS-26 llama.cpp prebuilt instead of walking back
ggml-org moved their macOS build runner to macOS 26 (Tahoe) at b9428, so
b9428 and every newer upstream prebuilt is stamped minos 26 and fails to
dyld-load on macOS 14 / 15. #5883 handled this by walking back release by
release at install time.
Replace that with a deterministic pin: a host below macOS 26 selects b9415
directly (the last upstream build stamped below 26: arm64 minos 14, x64
minos 13.3), so it loads on macOS 13.3 / 14 / 15 / 26. Hosts on macOS 26+
and unknown-version hosts keep latest selection unchanged.
Only the ggml-org upstream path is pinned; the unslothai/llama.cpp fork
ships its own minos-13.3 prebuilts (#5893), so the pin is a no-op there and
goes dormant once macOS routes to the fork. The Mach-O minos preflight from
#5883 stays as a post-download backstop.
Refs #5883, #5893.
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* docs: fork ships arm64 minos 14 / x64 minos 13.3, not uniform 13.3
The per-slice fork producer pins arm64 to 14.0 and x64 to 13.3; update the
pinned_macos_release_tag docstring to match. No behavior change.
---------
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: danielhanchen <michaelhan2050@gmail.com>
The SourcesGroup measurement container renders every citation badge
off-screen with `invisible absolute` so we can measure how many fit in
two rows. Absolute descendants still contribute to the parent's
scrollable overflow region, so long source lists added hundreds of
pixels of phantom scroll space below the assistant message that the
user could scroll into.
Wrap the measurement container in an absolute, `h-0`, `overflow-hidden`
box so the off-screen pills are clipped out of the scrollable overflow
region. Measurement still works because offsetTop is read relative to
the positioned wrapper.
* Studio: harden stdio MCP gating and fix transport edge cases
- Gate the Data Recipe stdio path behind UNSLOTH_STUDIO_ALLOW_STDIO_MCP so a hosted deployment cannot spawn local processes through recipes
- Enforce the gate inside _client() so the transport sink cannot spawn when disabled
- keep_alive=False so stdio probes/calls do not leave orphan subprocesses
- Force OAuth off for stdio servers on create and update
- Drop stored headers when a server switches transport type
- Reject a command whose first token is a URL scheme
- Add MCP gate and improvement tests
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* tests: skip Data Recipe stdio tests when data_designer is absent
The data_designer plugin is only installed in the Studio test job, so guard
the two build_mcp_providers tests with importorskip so the core matrix skips
them instead of failing on ModuleNotFoundError.
---------
Co-authored-by: Daniel Han <michaelhan2050@gmail.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Classify llama-server startup failures so diffusion/image GGUFs (FLUX, Qwen-Image, LTX, ERNIE-Image, Z-Image, ...) point users to the Images page instead of a misleading out-of-memory error. Other unknown architectures get a precise unsupported message; Ollama and OOM fallbacks are preserved.
Architecture is matched exactly against general.architecture, covering the arches Unsloth ships as GGUF: flux, qwen_image, ltxv, wan, lumina2.
Fixes#5842.
Make the network-touching install and download steps in the security-audit workflow resilient to transient failures without relaxing any integrity check.
- Add top-level retry and backoff env knobs for pip, cargo, and npm.
- Wrap the pip-audit + cargo install and npm ci steps in an exponential-backoff retry helper, preserving --locked and --ignore-scripts.
- Re-pin swatinem/rust-cache to the v2.9.1 commit so the SHA matches its comment.
- Split the OSV-Scanner download and SHA-256 verification into a hard-gated step: a checksum mismatch fails the job, while a transient download failure skips the scan; the advisory scan stays non-blocking.