From fac2dc09b0fdf0c38a81f5bad889d58f6706d672 Mon Sep 17 00:00:00 2001
From: Lee Jackson <130007945+Imagineer99@users.noreply.github.com>
Date: Wed, 6 May 2026 12:55:37 +0100
Subject: [PATCH 1/3] fix: restore API and Help menu labels (#5310)
---
studio/frontend/src/components/app-sidebar.tsx | 15 +++++++++++----
.../src/features/settings/settings-dialog.tsx | 8 ++++----
.../src/features/settings/tabs/api-keys-tab.tsx | 2 +-
3 files changed, 16 insertions(+), 9 deletions(-)
diff --git a/studio/frontend/src/components/app-sidebar.tsx b/studio/frontend/src/components/app-sidebar.tsx
index 171b4eb92d..13b8adfa48 100644
--- a/studio/frontend/src/components/app-sidebar.tsx
+++ b/studio/frontend/src/components/app-sidebar.tsx
@@ -37,12 +37,13 @@ import {
Delete02Icon,
Download03Icon,
GemIcon,
+ Globe02Icon,
+ HelpCircleIcon,
Search01Icon,
PowerIcon,
PencilEdit02Icon,
LayoutAlignLeftIcon,
Settings02Icon,
- SourceCodeSquareIcon,
ZapIcon,
} from "@hugeicons/core-free-icons";
import {
@@ -527,7 +528,7 @@ export function AppSidebar() {
{displayTitle}
- Studio
+ Unsloth
@@ -548,8 +549,8 @@ export function AppSidebar() {
useSettingsDialogStore.getState().openDialog("api-keys")}
>
-
- Developer
+
+ API
New
@@ -578,6 +579,12 @@ export function AppSidebar() {
+ useSettingsDialogStore.getState().openDialog("about")}
+ >
+
+ Help
+
setShutdownOpen(true)}>
Shutdown
diff --git a/studio/frontend/src/features/settings/settings-dialog.tsx b/studio/frontend/src/features/settings/settings-dialog.tsx
index 376af06e9d..63c0a9d388 100644
--- a/studio/frontend/src/features/settings/settings-dialog.tsx
+++ b/studio/frontend/src/features/settings/settings-dialog.tsx
@@ -10,11 +10,11 @@ import {
import { cn } from "@/lib/utils";
import {
Cancel01Icon,
+ Globe02Icon,
+ HelpCircleIcon,
Message01Icon,
PaintBrush02Icon,
Settings02Icon,
- SourceCodeSquareIcon,
- SparklesIcon,
UserIcon,
} from "@hugeicons/core-free-icons";
import { HugeiconsIcon } from "@hugeicons/react";
@@ -40,8 +40,8 @@ const TABS: TabDef[] = [
{ id: "profile", label: "Profile", icon: UserIcon },
{ id: "appearance", label: "Appearance", icon: PaintBrush02Icon },
{ id: "chat", label: "Chat", icon: Message01Icon },
- { id: "api-keys", label: "Developer", icon: SourceCodeSquareIcon, badge: "New" },
- { id: "about", label: "Help", icon: SparklesIcon },
+ { id: "api-keys", label: "API", icon: Globe02Icon, badge: "New" },
+ { id: "about", label: "Help", icon: HelpCircleIcon },
];
function renderTab(tab: SettingsTab) {
diff --git a/studio/frontend/src/features/settings/tabs/api-keys-tab.tsx b/studio/frontend/src/features/settings/tabs/api-keys-tab.tsx
index 64c6f520c0..ac9ec40543 100644
--- a/studio/frontend/src/features/settings/tabs/api-keys-tab.tsx
+++ b/studio/frontend/src/features/settings/tabs/api-keys-tab.tsx
@@ -63,7 +63,7 @@ export function ApiKeysTab() {
return (
- Developer
+ API
Access Unsloth programmatically via the OpenAI-compatible API.{" "}
Date: Wed, 6 May 2026 22:16:20 +0530
Subject: [PATCH 2/3] [studio]: Fix tool reasoning trace in UI (#5314)
* fix thought for 1 second issue
* gemini suggesion
---
.../src/components/assistant-ui/reasoning.tsx | 23 +++++++++++++++----
1 file changed, 18 insertions(+), 5 deletions(-)
diff --git a/studio/frontend/src/components/assistant-ui/reasoning.tsx b/studio/frontend/src/components/assistant-ui/reasoning.tsx
index 387f8cd458..fe913baf2a 100644
--- a/studio/frontend/src/components/assistant-ui/reasoning.tsx
+++ b/studio/frontend/src/components/assistant-ui/reasoning.tsx
@@ -316,15 +316,28 @@ const ReasoningGroupImpl: ReasoningGroupComponent = ({
if (message.status?.type !== "running") {
return false;
}
- const lastIndex = message.parts.length - 1;
- if (lastIndex < 0) {
+ const parts = message.parts;
+ const len = parts.length;
+ if (len === 0) {
return false;
}
- const lastType = message.parts[lastIndex]?.type;
- if (lastType !== "reasoning") {
+
+ let groupHasReasoning = false;
+ for (let i = startIndex; i <= endIndex && i < len; i += 1) {
+ if (parts[i]?.type === "reasoning") {
+ groupHasReasoning = true;
+ break;
+ }
+ }
+ if (!groupHasReasoning) {
return false;
}
- return lastIndex >= startIndex && lastIndex <= endIndex;
+ for (let i = endIndex + 1; i < len; i += 1) {
+ if (parts[i]?.type !== "tool-call") {
+ return false;
+ }
+ }
+ return true;
});
const persistedDuration = useAuiState(({ message }) => {
From 948ce43584c272be016f6c7210d99a6a0bddc26a Mon Sep 17 00:00:00 2001
From: Daniel Han
Date: Thu, 7 May 2026 00:12:09 -0700
Subject: [PATCH 3/3] =?UTF-8?q?fix:=203=20patch=5F*=20helpers=20=E2=80=94?=
=?UTF-8?q?=20fast=5Flora=20import,=20sft=5Ftrainer=20Union,=20openenv=20O?=
=?UTF-8?q?SError=20(#5319)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* fix: import fast_lora_forward inside patch_fast_lora
patch_fast_lora has referenced an unbound `fast_lora_forward` since
ddf118a8f (2024-11-21). The function is defined at
unsloth/kernels/fast_lora.py:652 and re-exported through
unsloth/kernels/__init__.py:45, but it was never imported into
unsloth/models/_utils.py, so calling patch_fast_lora() raises
NameError: name 'fast_lora_forward' is not defined.
The bug went unnoticed because no production code path calls
patch_fast_lora() unconditionally. Surfaced by a new CPU-CI check that
invokes every zero-arg patch_* helper across unsloth + unsloth_zoo
(consolidated-tests-ci.yml on PR #5312).
Importing inside the function (rather than at module top) keeps the
import surface narrow and avoids a circular-import risk if
unsloth.kernels.fast_lora ever needs to import from
unsloth.models._utils.
* fix: inject typing imports into patch_sft_trainer_tokenizer's exec namespace
patch_sft_trainer_tokenizer rewrites the source of TRL's SFTTrainer
methods (_prepare_non_packed_dataloader, _prepare_dataset) and re-execs
them. With TRL 1.x, those methods carry `Union[...]` type hints in
their signatures. The current rewrite only injects identifiers found by
`dir(trl.trainer.sft_trainer)` into the exec namespace, which does not
include `Union`, so exec(function, ...) raises NameError: name 'Union'
is not defined.
Fix: import Union, Optional, List, Any, Callable, Tuple, Dict, Iterator
inside the function. exec receives `locals()` as its globals dict, so
those names are visible to the executed source body. Same pattern as
unsloth/models/_utils.py:patch_linear_scaling, which already injects
`from typing import Union, Optional, List, Any, Callable, Tuple` into
its own exec_code.
Surfaced by the consolidated CPU-CI runtime patch_* check on PR #5312
in the matrix cell `transformers>=5,<6 + trl>=1,<2`.
* fix: guard openenv_vllm_reload_weights against OSError from inspect.getsource
TRL 0.29.1 and the 1.x line ship some openenv helpers as compiled
bytecode without accessible source on disk. inspect.getsource(patch_target)
raises OSError("could not get source code") in that case, which surfaces
as a hard failure in patch_trl_openenv() and aborts the rest of the
RL_ADDITIONAL_FUNCTIONS["openenv"] iteration.
Wrap the getsource call in a try/except OSError and log a warning
instead. The wake_up(tags=...) rewrite is the only thing skipped; the
core weight-reload patch path stays functional.
Surfaced by the consolidated CPU-CI runtime patch_* check on PR #5312
in matrix cells running TRL 0.29.1 (latest <1.0.0) and TRL 1.3.0
(latest 1.x). The pyproject pin (TRL 0.18.2-0.24.0) still gets source
for this function so the original code path runs unchanged there.
---
unsloth/models/_utils.py | 1 +
unsloth/models/rl_replacements.py | 15 ++++++++++++++-
unsloth/tokenizer_utils.py | 6 ++++++
3 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/unsloth/models/_utils.py b/unsloth/models/_utils.py
index 34fec53504..d3eee03325 100644
--- a/unsloth/models/_utils.py
+++ b/unsloth/models/_utils.py
@@ -2483,6 +2483,7 @@ def patch_tokenizer(model, tokenizer):
def patch_fast_lora():
import peft.tuners.lora.bnb
+ from ..kernels.fast_lora import fast_lora_forward
peft.tuners.lora.bnb.Linear4bit.forward = fast_lora_forward
diff --git a/unsloth/models/rl_replacements.py b/unsloth/models/rl_replacements.py
index 0f10847282..c2be1bf74a 100755
--- a/unsloth/models/rl_replacements.py
+++ b/unsloth/models/rl_replacements.py
@@ -1780,7 +1780,20 @@ def openenv_vllm_reload_weights():
patch_target_name = "generate_rollout_completions"
patch_target = getattr(openenv_utils, patch_target_name)
- src = inspect.getsource(patch_target)
+ # TRL 0.29.1+ ships some openenv helpers as compiled bytecode without
+ # accessible source on disk; inspect.getsource raises OSError("could
+ # not get source code") in that case. Skip the source-rewrite patch
+ # rather than crashing -- the core unsloth weight-reload path stays
+ # functional, only the wake_up tag rewrite is skipped.
+ try:
+ src = inspect.getsource(patch_target)
+ except OSError as e:
+ logger.warning(
+ f"Unsloth: Could not retrieve source for trl openenv "
+ f"{patch_target_name} ({e}); skipping rewrite. "
+ f"Weight reload still functional."
+ )
+ return
src = textwrap.dedent(src)
original_src = src
diff --git a/unsloth/tokenizer_utils.py b/unsloth/tokenizer_utils.py
index 130894e385..67edc41d52 100644
--- a/unsloth/tokenizer_utils.py
+++ b/unsloth/tokenizer_utils.py
@@ -1580,6 +1580,12 @@ def patch_sft_trainer_tokenizer():
except:
return
all_imports = dir(trl.trainer.sft_trainer)
+ # Make typing names available to the exec'd source bodies. TRL >= 1.x
+ # type-hints _prepare_dataset / _prepare_non_packed_dataloader with
+ # `Union[...]` and friends; without these imports in the exec namespace
+ # those become NameErrors at exec time. Mirrors the pattern used in
+ # unsloth/models/_utils.py:patch_linear_scaling.
+ from typing import Union, Optional, List, Any, Callable, Tuple, Dict, Iterator # noqa: F401
for (
function_name,