Compare commits
2 commits
main
...
studio-upd
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d75fa36832 | ||
|
|
84cf03c015 |
11 changed files with 72 additions and 70 deletions
|
|
@ -3651,8 +3651,9 @@ class LlamaCppBackend:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
"Requested MTP speculative decoding but "
|
"Requested MTP speculative decoding but "
|
||||||
"llama-server lacks --spec-type mtp/draft-mtp; "
|
"llama-server lacks --spec-type mtp/draft-mtp; "
|
||||||
"run `unsloth studio update`. Loading without "
|
"update by running curl -fsSL https://unsloth.ai/install.sh | sh "
|
||||||
"speculative decoding."
|
"(macOS/Linux) or irm https://unsloth.ai/install.ps1 | iex "
|
||||||
|
"(Windows). Loading without speculative decoding."
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
draft_n_max = _resolved_draft_n_max()
|
draft_n_max = _resolved_draft_n_max()
|
||||||
|
|
|
||||||
|
|
@ -344,7 +344,9 @@ async def lifespan(app: FastAPI):
|
||||||
if _caps.get("found") and not _caps.get("supports_mtp"):
|
if _caps.get("found") and not _caps.get("supports_mtp"):
|
||||||
_msg = (
|
_msg = (
|
||||||
"llama.cpp prebuilt lacks MTP support "
|
"llama.cpp prebuilt lacks MTP support "
|
||||||
"(--spec-type mtp/draft-mtp). Run `unsloth studio update`. "
|
"(--spec-type mtp/draft-mtp). Update by running "
|
||||||
|
"curl -fsSL https://unsloth.ai/install.sh | sh (macOS/Linux) or "
|
||||||
|
"irm https://unsloth.ai/install.ps1 | iex (Windows). "
|
||||||
"MTP GGUFs will load without speculative decoding."
|
"MTP GGUFs will load without speculative decoding."
|
||||||
)
|
)
|
||||||
_log.warning(_msg)
|
_log.warning(_msg)
|
||||||
|
|
|
||||||
|
|
@ -317,7 +317,8 @@ def test_format_stale_warning_contains_actionable_command():
|
||||||
assert "b9190" in msg
|
assert "b9190" in msg
|
||||||
assert "b9300" in msg
|
assert "b9300" in msg
|
||||||
assert "5 days" in msg
|
assert "5 days" in msg
|
||||||
assert "unsloth studio update" in msg
|
assert "install.sh" in msg
|
||||||
|
assert "install.ps1" in msg
|
||||||
|
|
||||||
|
|
||||||
def test_format_stale_warning_singular_day():
|
def test_format_stale_warning_singular_day():
|
||||||
|
|
|
||||||
|
|
@ -233,8 +233,9 @@ def format_stale_warning(info: dict) -> str:
|
||||||
age_str = f"{age} day{'s' if age != 1 else ''}" if age is not None else "some time"
|
age_str = f"{age} day{'s' if age != 1 else ''}" if age is not None else "some time"
|
||||||
return (
|
return (
|
||||||
f"llama.cpp prebuilt is {age_str} behind: installed "
|
f"llama.cpp prebuilt is {age_str} behind: installed "
|
||||||
f"{installed}, latest {latest}. Run `unsloth studio update` "
|
f"{installed}, latest {latest}. Update to refresh by running "
|
||||||
f"to refresh."
|
f"curl -fsSL https://unsloth.ai/install.sh | sh (macOS/Linux) or "
|
||||||
|
f"irm https://unsloth.ai/install.ps1 | iex (Windows)."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ export function UpdateBanner({
|
||||||
: isManualLinuxPackage
|
: isManualLinuxPackage
|
||||||
? "Open the GitHub release page to install the Linux package"
|
? "Open the GitHub release page to install the Linux package"
|
||||||
: isExternalServer
|
: isExternalServer
|
||||||
? "Run `unsloth studio update` from your terminal"
|
? "To update, run curl -fsSL https://unsloth.ai/install.sh | sh (macOS/Linux) or irm https://unsloth.ai/install.ps1 | iex (Windows) from your terminal"
|
||||||
: "A new app update is available"}
|
: "A new app update is available"}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,11 @@ import { copyToClipboard } from "@/lib/copy-to-clipboard";
|
||||||
import { AnimatePresence, motion } from "motion/react";
|
import { AnimatePresence, motion } from "motion/react";
|
||||||
import { type ReactElement, useEffect, useRef, useState } from "react";
|
import { type ReactElement, useEffect, useRef, useState } from "react";
|
||||||
|
|
||||||
const STUDIO_UPDATE_CMD = "unsloth studio update";
|
const STUDIO_UPDATE_UNIX_CMD = "curl -fsSL https://unsloth.ai/install.sh | sh";
|
||||||
|
const STUDIO_UPDATE_WINDOWS_CMD = "irm https://unsloth.ai/install.ps1 | iex";
|
||||||
|
// Match "windows" (every Windows UA carries "Windows NT") rather than "win",
|
||||||
|
// which also matches "Darwin" and would mis-detect macOS as Windows.
|
||||||
|
const WINDOWS_UA_RE = /windows/i;
|
||||||
const RELEASE_NOTES_URL = "https://unsloth.ai/docs/new/changelog";
|
const RELEASE_NOTES_URL = "https://unsloth.ai/docs/new/changelog";
|
||||||
const EASE_OUT_QUART: [number, number, number, number] = [0.165, 0.84, 0.44, 1];
|
const EASE_OUT_QUART: [number, number, number, number] = [0.165, 0.84, 0.44, 1];
|
||||||
|
|
||||||
|
|
@ -36,7 +40,15 @@ export function WebUpdateBanner({
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleCopyCommand() {
|
async function handleCopyCommand() {
|
||||||
if (!(await copyToClipboard(STUDIO_UPDATE_CMD))) {
|
// Copy only the command for the user's OS: pasting both (Unix + PowerShell)
|
||||||
|
// into a single terminal runs the wrong one and errors out.
|
||||||
|
const isWindows =
|
||||||
|
typeof navigator !== "undefined" &&
|
||||||
|
WINDOWS_UA_RE.test(navigator.userAgent || "");
|
||||||
|
const command = isWindows
|
||||||
|
? STUDIO_UPDATE_WINDOWS_CMD
|
||||||
|
: STUDIO_UPDATE_UNIX_CMD;
|
||||||
|
if (!(await copyToClipboard(command))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setCopiedVersion(status?.latestVersion ?? null);
|
setCopiedVersion(status?.latestVersion ?? null);
|
||||||
|
|
@ -90,8 +102,23 @@ export function WebUpdateBanner({
|
||||||
</p>
|
</p>
|
||||||
<p className="mt-1 text-xs leading-relaxed text-muted-foreground">
|
<p className="mt-1 text-xs leading-relaxed text-muted-foreground">
|
||||||
Installed package: {status.currentVersion}. To update Studio,
|
Installed package: {status.currentVersion}. To update Studio,
|
||||||
run this in your terminal, then restart Studio.
|
run the command for your OS in a terminal, then restart
|
||||||
|
Studio.
|
||||||
</p>
|
</p>
|
||||||
|
<div className="mt-2 space-y-1">
|
||||||
|
<p className="text-[10px] font-medium uppercase tracking-wide text-muted-foreground/70">
|
||||||
|
macOS / Linux
|
||||||
|
</p>
|
||||||
|
<code className="block overflow-x-auto rounded bg-muted/60 px-2 py-1 font-mono text-[11px] text-foreground">
|
||||||
|
{STUDIO_UPDATE_UNIX_CMD}
|
||||||
|
</code>
|
||||||
|
<p className="text-[10px] font-medium uppercase tracking-wide text-muted-foreground/70">
|
||||||
|
Windows (PowerShell)
|
||||||
|
</p>
|
||||||
|
<code className="block overflow-x-auto rounded bg-muted/60 px-2 py-1 font-mono text-[11px] text-foreground">
|
||||||
|
{STUDIO_UPDATE_WINDOWS_CMD}
|
||||||
|
</code>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
// Copyright 2026-present the Unsloth AI Inc. team. All rights reserved. See /studio/LICENSE.AGPL-3.0
|
// Copyright 2026-present the Unsloth AI Inc. team. All rights reserved. See /studio/LICENSE.AGPL-3.0
|
||||||
|
|
||||||
import { copyToClipboard } from "@/lib/copy-to-clipboard";
|
|
||||||
import { useT } from "@/i18n";
|
import { useT } from "@/i18n";
|
||||||
|
import { copyToClipboard } from "@/lib/copy-to-clipboard";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { Copy01Icon, Tick02Icon } from "@hugeicons/core-free-icons";
|
import { Copy01Icon, Tick02Icon } from "@hugeicons/core-free-icons";
|
||||||
import { HugeiconsIcon } from "@hugeicons/react";
|
import { HugeiconsIcon } from "@hugeicons/react";
|
||||||
|
|
@ -10,13 +10,9 @@ import { AnimatePresence, motion, useReducedMotion } from "motion/react";
|
||||||
import type { ReactElement } from "react";
|
import type { ReactElement } from "react";
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
|
|
||||||
const STUDIO_UPDATE_CMD = "unsloth studio update";
|
const STUDIO_UPDATE_UNIX_CMD = "curl -fsSL https://unsloth.ai/install.sh | sh";
|
||||||
const STUDIO_UPDATE_FALLBACK_UNIX_CMD =
|
const STUDIO_UPDATE_WINDOWS_CMD = "irm https://unsloth.ai/install.ps1 | iex";
|
||||||
"curl -fsSL https://unsloth.ai/install.sh | sh";
|
|
||||||
const STUDIO_UPDATE_FALLBACK_WINDOWS_CMD =
|
|
||||||
"irm https://unsloth.ai/install.ps1 | iex";
|
|
||||||
const STUDIO_LOCAL_PULL_CMD = "git pull --ff-only";
|
const STUDIO_LOCAL_PULL_CMD = "git pull --ff-only";
|
||||||
const STUDIO_LOCAL_UPDATE_CMD = "unsloth studio update --local";
|
|
||||||
const STUDIO_LOCAL_FALLBACK_UNIX_CMD = "./install.sh --local";
|
const STUDIO_LOCAL_FALLBACK_UNIX_CMD = "./install.sh --local";
|
||||||
const STUDIO_LOCAL_FALLBACK_WINDOWS_CMD = ".\\install.ps1 --local";
|
const STUDIO_LOCAL_FALLBACK_WINDOWS_CMD = ".\\install.ps1 --local";
|
||||||
|
|
||||||
|
|
@ -145,6 +141,9 @@ export function UpdateStudioInstructions({
|
||||||
const shell = shellOverride ?? defaultShell;
|
const shell = shellOverride ?? defaultShell;
|
||||||
const prefersReducedMotion = useReducedMotion();
|
const prefersReducedMotion = useReducedMotion();
|
||||||
const windows = shell === "windows";
|
const windows = shell === "windows";
|
||||||
|
const updateCmd = windows
|
||||||
|
? STUDIO_UPDATE_WINDOWS_CMD
|
||||||
|
: STUDIO_UPDATE_UNIX_CMD;
|
||||||
const localInstallSource = isLocalInstallSource(installSource);
|
const localInstallSource = isLocalInstallSource(installSource);
|
||||||
const checkoutInstallSource =
|
const checkoutInstallSource =
|
||||||
installSource === "editable" || installSource === "local_repo";
|
installSource === "editable" || installSource === "local_repo";
|
||||||
|
|
@ -224,16 +223,9 @@ export function UpdateStudioInstructions({
|
||||||
command={STUDIO_LOCAL_PULL_CMD}
|
command={STUDIO_LOCAL_PULL_CMD}
|
||||||
copyLabel={t("settings.about.update.gitPullCommand")}
|
copyLabel={t("settings.about.update.gitPullCommand")}
|
||||||
/>
|
/>
|
||||||
<CopyableCommand
|
|
||||||
command={STUDIO_LOCAL_UPDATE_CMD}
|
|
||||||
copyLabel={t("settings.about.update.localUpdateCommand")}
|
|
||||||
/>
|
|
||||||
<p className="text-xs text-muted-foreground leading-relaxed">
|
|
||||||
{t("settings.about.update.localInstallerFallback")}
|
|
||||||
</p>
|
|
||||||
<AnimatePresence mode="wait" initial={false}>
|
<AnimatePresence mode="wait" initial={false}>
|
||||||
<motion.div
|
<motion.div
|
||||||
key={`local-fallback-${shell}`}
|
key={`local-update-${shell}`}
|
||||||
initial={fadeInitial}
|
initial={fadeInitial}
|
||||||
animate={fadeAnimate}
|
animate={fadeAnimate}
|
||||||
exit={fadeExit}
|
exit={fadeExit}
|
||||||
|
|
@ -245,7 +237,7 @@ export function UpdateStudioInstructions({
|
||||||
? STUDIO_LOCAL_FALLBACK_WINDOWS_CMD
|
? STUDIO_LOCAL_FALLBACK_WINDOWS_CMD
|
||||||
: STUDIO_LOCAL_FALLBACK_UNIX_CMD
|
: STUDIO_LOCAL_FALLBACK_UNIX_CMD
|
||||||
}
|
}
|
||||||
copyLabel={t("settings.about.update.localInstallerCommand")}
|
copyLabel={t("settings.about.update.localUpdateCommand")}
|
||||||
/>
|
/>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
</AnimatePresence>
|
</AnimatePresence>
|
||||||
|
|
@ -291,17 +283,20 @@ export function UpdateStudioInstructions({
|
||||||
<p className="text-xs text-muted-foreground leading-relaxed">
|
<p className="text-xs text-muted-foreground leading-relaxed">
|
||||||
{t("settings.about.update.curlOrPypi")}
|
{t("settings.about.update.curlOrPypi")}
|
||||||
</p>
|
</p>
|
||||||
<CopyableCommand
|
<AnimatePresence mode="wait" initial={false}>
|
||||||
command={STUDIO_UPDATE_CMD}
|
<motion.div
|
||||||
copyLabel={t("settings.about.update.updateCommand")}
|
key={`unknown-update-${shell}`}
|
||||||
/>
|
initial={fadeInitial}
|
||||||
<p className="text-xs text-muted-foreground leading-relaxed">
|
animate={fadeAnimate}
|
||||||
{t("settings.about.update.localCheckout")}
|
exit={fadeExit}
|
||||||
</p>
|
transition={fadeTransition}
|
||||||
<CopyableCommand
|
>
|
||||||
command={STUDIO_LOCAL_UPDATE_CMD}
|
<CopyableCommand
|
||||||
copyLabel={t("settings.about.update.localUpdateCommand")}
|
command={updateCmd}
|
||||||
/>
|
copyLabel={t("settings.about.update.updateCommand")}
|
||||||
|
/>
|
||||||
|
</motion.div>
|
||||||
|
</AnimatePresence>
|
||||||
<p className="text-xs text-muted-foreground leading-relaxed">
|
<p className="text-xs text-muted-foreground leading-relaxed">
|
||||||
{t("settings.about.update.restartAfterUpdate")}
|
{t("settings.about.update.restartAfterUpdate")}
|
||||||
</p>
|
</p>
|
||||||
|
|
@ -320,28 +315,17 @@ export function UpdateStudioInstructions({
|
||||||
{getStudioUpdateInstructionLine(shell, t)}
|
{getStudioUpdateInstructionLine(shell, t)}
|
||||||
</motion.p>
|
</motion.p>
|
||||||
</AnimatePresence>
|
</AnimatePresence>
|
||||||
<CopyableCommand
|
|
||||||
command={STUDIO_UPDATE_CMD}
|
|
||||||
copyLabel={t("settings.about.update.updateCommand")}
|
|
||||||
/>
|
|
||||||
<p className="text-xs text-muted-foreground leading-relaxed">
|
|
||||||
{t("settings.about.update.fallbackInstruction")}
|
|
||||||
</p>
|
|
||||||
<AnimatePresence mode="wait" initial={false}>
|
<AnimatePresence mode="wait" initial={false}>
|
||||||
<motion.div
|
<motion.div
|
||||||
key={`fallback-${shell}`}
|
key={`update-${shell}`}
|
||||||
initial={fadeInitial}
|
initial={fadeInitial}
|
||||||
animate={fadeAnimate}
|
animate={fadeAnimate}
|
||||||
exit={fadeExit}
|
exit={fadeExit}
|
||||||
transition={fadeTransition}
|
transition={fadeTransition}
|
||||||
>
|
>
|
||||||
<CopyableCommand
|
<CopyableCommand
|
||||||
command={
|
command={updateCmd}
|
||||||
windows
|
copyLabel={t("settings.about.update.updateCommand")}
|
||||||
? STUDIO_UPDATE_FALLBACK_WINDOWS_CMD
|
|
||||||
: STUDIO_UPDATE_FALLBACK_UNIX_CMD
|
|
||||||
}
|
|
||||||
copyLabel={t("settings.about.update.fallbackCommand")}
|
|
||||||
/>
|
/>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
</AnimatePresence>
|
</AnimatePresence>
|
||||||
|
|
|
||||||
|
|
@ -71,8 +71,8 @@ function externalConflictMessage(preflight: DesktopPreflightResult) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return preflight.port
|
return preflight.port
|
||||||
? `A Studio server for this install is already running from a terminal on port ${preflight.port}. Stop that server, or run \`unsloth studio update\` from that terminal before using the desktop app.`
|
? `A Studio server for this install is already running from a terminal on port ${preflight.port}. Stop that server, or update by running curl -fsSL https://unsloth.ai/install.sh | sh (macOS/Linux) or irm https://unsloth.ai/install.ps1 | iex (Windows) from that terminal before using the desktop app.`
|
||||||
: "A Studio server for this install is already running from a terminal. Stop that server, or run `unsloth studio update` from that terminal before using the desktop app.";
|
: "A Studio server for this install is already running from a terminal. Stop that server, or update by running curl -fsSL https://unsloth.ai/install.sh | sh (macOS/Linux) or irm https://unsloth.ai/install.ps1 | iex (Windows) from that terminal before using the desktop app.";
|
||||||
}
|
}
|
||||||
|
|
||||||
async function waitForManagedServerReady(
|
async function waitForManagedServerReady(
|
||||||
|
|
@ -248,8 +248,8 @@ export function useTauriBackend() {
|
||||||
} else {
|
} else {
|
||||||
setBackendError(
|
setBackendError(
|
||||||
preflight.disposition === "owned_stale"
|
preflight.disposition === "owned_stale"
|
||||||
? "Desktop-owned Studio backend is too old for this desktop app. Run `unsloth studio update`, then restart Studio."
|
? "Desktop-owned Studio backend is too old for this desktop app. Update by running curl -fsSL https://unsloth.ai/install.sh | sh (macOS/Linux) or irm https://unsloth.ai/install.ps1 | iex (Windows), then restart Studio."
|
||||||
: "Managed Studio install is too old. Run `unsloth studio update`.",
|
: "Managed Studio install is too old. Update by running curl -fsSL https://unsloth.ai/install.sh | sh (macOS/Linux) or irm https://unsloth.ai/install.ps1 | iex (Windows).",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -307,8 +307,6 @@ export const en = {
|
||||||
"Pull latest changes from your Unsloth repo checkout, then update Studio locally:",
|
"Pull latest changes from your Unsloth repo checkout, then update Studio locally:",
|
||||||
gitPullCommand: "git pull command",
|
gitPullCommand: "git pull command",
|
||||||
localUpdateCommand: "local update command",
|
localUpdateCommand: "local update command",
|
||||||
localInstallerFallback:
|
|
||||||
"If the Studio update command is unavailable, run the local installer from that checkout:",
|
|
||||||
localInstallerCommand: "local installer command",
|
localInstallerCommand: "local installer command",
|
||||||
sourceInstallDetected:
|
sourceInstallDetected:
|
||||||
"This looks like a source or VCS package install. Reinstall from the original local path or Git URL you used.",
|
"This looks like a source or VCS package install. Reinstall from the original local path or Git URL you used.",
|
||||||
|
|
@ -320,11 +318,6 @@ export const en = {
|
||||||
"Studio could not detect how it was installed. Check how you installed Studio first, then choose the matching update path.",
|
"Studio could not detect how it was installed. Check how you installed Studio first, then choose the matching update path.",
|
||||||
curlOrPypi: "For curl or PyPI installs, run:",
|
curlOrPypi: "For curl or PyPI installs, run:",
|
||||||
updateCommand: "update command",
|
updateCommand: "update command",
|
||||||
localCheckout:
|
|
||||||
"For local checkout installs, update from that checkout instead and use the local update command:",
|
|
||||||
fallbackInstruction:
|
|
||||||
"If that fails or unsloth studio update is unavailable, run:",
|
|
||||||
fallbackCommand: "fallback command",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -288,8 +288,6 @@ export const zhCN = {
|
||||||
"从你的 Unsloth 仓库 checkout 拉取最新变更,然后本地更新 Studio:",
|
"从你的 Unsloth 仓库 checkout 拉取最新变更,然后本地更新 Studio:",
|
||||||
gitPullCommand: "git pull 命令",
|
gitPullCommand: "git pull 命令",
|
||||||
localUpdateCommand: "本地更新命令",
|
localUpdateCommand: "本地更新命令",
|
||||||
localInstallerFallback:
|
|
||||||
"如果 Studio 更新命令不可用,请从该 checkout 运行本地安装器:",
|
|
||||||
localInstallerCommand: "本地安装器命令",
|
localInstallerCommand: "本地安装器命令",
|
||||||
sourceInstallDetected:
|
sourceInstallDetected:
|
||||||
"这看起来是源码或 VCS 包安装。请从最初使用的本地路径或 Git URL 重新安装。",
|
"这看起来是源码或 VCS 包安装。请从最初使用的本地路径或 Git URL 重新安装。",
|
||||||
|
|
@ -300,11 +298,6 @@ export const zhCN = {
|
||||||
"Studio 无法检测安装方式。请先确认你如何安装 Studio,然后选择匹配的更新方式。",
|
"Studio 无法检测安装方式。请先确认你如何安装 Studio,然后选择匹配的更新方式。",
|
||||||
curlOrPypi: "对于 curl 或 PyPI 安装,请运行:",
|
curlOrPypi: "对于 curl 或 PyPI 安装,请运行:",
|
||||||
updateCommand: "更新命令",
|
updateCommand: "更新命令",
|
||||||
localCheckout:
|
|
||||||
"对于本地 checkout 安装,请改为从该 checkout 更新并使用本地更新命令:",
|
|
||||||
fallbackInstruction:
|
|
||||||
"如果失败,或 unsloth studio update 不可用,请运行:",
|
|
||||||
fallbackCommand: "备用命令",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ fn external_conflict_message(conflict: &crate::preflight::ExternalBackendConflic
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
format!(
|
format!(
|
||||||
"A Studio server for this install is already running from a terminal on port {}. Stop that server, or run `unsloth studio update` from that terminal before using desktop repair/update.",
|
"A Studio server for this install is already running from a terminal on port {}. Stop that server, or update by running curl -fsSL https://unsloth.ai/install.sh | sh (macOS/Linux) or irm https://unsloth.ai/install.ps1 | iex (Windows) from that terminal before using desktop repair/update.",
|
||||||
conflict.port
|
conflict.port
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue