diff --git a/app/frontend/src/components/ModelManager.jsx b/app/frontend/src/components/ModelManager.jsx
index 5ef227b..c3a84ab 100644
--- a/app/frontend/src/components/ModelManager.jsx
+++ b/app/frontend/src/components/ModelManager.jsx
@@ -398,6 +398,7 @@ function ModelManager({
backendMode: sdStatus.settings?.backendMode || sdStatus.loading?.backendMode || "",
backendBinary: sdStatus.settings?.backendBinary || sdStatus.loading?.backendBinary || "",
backendDevice: sdStatus.settings?.backendDevice || sdStatus.loading?.device || "",
+ llmBackendMode: llmStatus.settings?.backendMode || llmStatus.settings?.backendBinary || "",
});
if (llmStatus.ready) {
@@ -1002,6 +1003,13 @@ function ModelManager({
The local C++ llama.cpp server is running. Chat requests can be sent via the Text Chat interface.
+ {backendInfo.llmBackendMode && (
+
+
+ {backendInfo.llmBackendMode}
+
+
+ )}
diff --git a/app/frontend/src/components/Settings.jsx b/app/frontend/src/components/Settings.jsx
index 3b3ca4a..fd23622 100644
--- a/app/frontend/src/components/Settings.jsx
+++ b/app/frontend/src/components/Settings.jsx
@@ -1,6 +1,6 @@
-import React, { memo, useEffect } from "react";
+import React, { memo, useEffect, useState } from "react";
import { Crop, Sliders, Cpu, Info, MessageSquare, SlidersHorizontal, Zap } from "lucide-react";
-import { stopServer, formatBytes } from "../services/api";
+import { stopServer, formatBytes, getLlmStatus } from "../services/api";
const ASPECT_RATIOS = [
{ id: "1:1", label: "1:1 Square", width: 512, height: 512, sdxl_width: 1024, sdxl_height: 1024, desc: "Social posts & avatars" },
@@ -55,6 +55,26 @@ function Settings({
const cleanupBytes = (cleanupItems || []).reduce((sum, item) => sum + Number(item.sizeBytes || 0), 0);
const showReadinessPanel = Boolean(health && (readinessIssues.length > 0 || (cleanupItems && cleanupItems.length > 0)));
+ const [llmStatus, setLlmStatus] = useState({ ready: false, settings: {} });
+
+ useEffect(() => {
+ let cancelled = false;
+ const fetchLlmStatus = async () => {
+ try {
+ const status = await getLlmStatus();
+ if (!cancelled) setLlmStatus(status);
+ } catch (_) {}
+ };
+ fetchLlmStatus();
+ const interval = setInterval(fetchLlmStatus, 3000);
+ return () => {
+ cancelled = true;
+ clearInterval(interval);
+ };
+ }, []);
+
+ const supportsThinking = Boolean(llmStatus.ready && llmStatus.settings?.supportsThinking);
+
useEffect(() => {
if (isOpenVinoNpu && constraints.steps > 8) {
setConstraints((prev) => ({ ...prev, steps: 8, npuSteps: 8 }));
@@ -523,7 +543,8 @@ function Settings({
- {/* Show Thinking Process toggle */}
+ {/* Show Thinking Process toggle - only for models that support it */}
+ {supportsThinking && (
+ )}
+ {!supportsThinking && llmStatus.ready && (
+
+ Thinking not supported. The loaded model does not support reasoning/thinking output. DeepThink is only available for models like DeepSeek-R1, Qwen3, Gemma-4-E2B, and other reasoning-capable models.
+
+ )}
{/* Temperature slider */}
diff --git a/app/frontend/src/components/TextChat.jsx b/app/frontend/src/components/TextChat.jsx
index 5c2c7d9..2e0ccba 100644
--- a/app/frontend/src/components/TextChat.jsx
+++ b/app/frontend/src/components/TextChat.jsx
@@ -147,6 +147,7 @@ function TextChat({
const [attachments, setAttachments] = useState([]);
const fileInputRef = useRef(null);
const supportsVision = Boolean(status.ready && status.settings?.supportsVision);
+ const supportsThinking = Boolean(status.ready && status.settings?.supportsThinking);
const isImage = (file) => {
return /\.(jpe?g|png|webp)$/i.test(file.name) || file.type.startsWith("image/");
@@ -888,7 +889,7 @@ function TextChat({
rows={1}
/>
- {status.ready && (
+ {status.ready && supportsThinking && (
{
diff --git a/scripts/serve.cjs b/scripts/serve.cjs
index b54e081..9ab0e3e 100644
--- a/scripts/serve.cjs
+++ b/scripts/serve.cjs
@@ -2181,6 +2181,7 @@ async function startLlm(settings = {}) {
backendMode: backend.mode,
backendBinary: path.basename(backend.path),
enableThinking: settings.enableThinking !== false,
+ supportsThinking: /deepseek|qwen3|gemma-4|gemma4|think|r1|e2b|reasoning/i.test(filename),
};
let mmprojPath = null;