diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py
index 89f8e8109..058a8cb13 100644
--- a/backend/open_webui/utils/middleware.py
+++ b/backend/open_webui/utils/middleware.py
@@ -2618,7 +2618,10 @@ async def process_chat_payload(request, form_data, user, metadata, model):
# Resolve terminal tools if terminal_id is set (outside tool_ids check
# so system terminals work even when no other tools are selected)
- if terminal_id:
+ terminal_capability = (model.get('info', {}).get('meta', {}).get('capabilities') or {}).get(
+ 'terminal', True
+ )
+ if terminal_id and terminal_capability:
try:
terminal_result = await get_terminal_tools(
request,
diff --git a/src/lib/components/chat/Chat.svelte b/src/lib/components/chat/Chat.svelte
index a3fd62d3b..55d88c1f3 100644
--- a/src/lib/components/chat/Chat.svelte
+++ b/src/lib/components/chat/Chat.svelte
@@ -2306,6 +2306,9 @@
// Use the user-selected terminal from the dropdown
const activeTerminalId = $selectedTerminalId ?? null;
+ // Only send terminal_id if the model has terminal capability enabled
+ const terminalEnabled = model.info?.meta?.capabilities?.terminal ?? true;
+
const res = await generateOpenAIChatCompletion(
localStorage.token,
{
@@ -2323,7 +2326,7 @@
filter_ids: selectedFilterIds.length > 0 ? selectedFilterIds : undefined,
tool_ids: toolIds.length > 0 ? toolIds : undefined,
skill_ids: skillIds.length > 0 ? skillIds : undefined,
- terminal_id: activeTerminalId ?? undefined,
+ terminal_id: terminalEnabled ? (activeTerminalId ?? undefined) : undefined,
tool_servers: [
...($toolServers ?? []).filter(
(server, idx) => toolServerIds.includes(idx) || toolServerIds.includes(server?.id)
diff --git a/src/lib/components/chat/MessageInput.svelte b/src/lib/components/chat/MessageInput.svelte
index ef8d2d4cb..b9bb534d8 100644
--- a/src/lib/components/chat/MessageInput.svelte
+++ b/src/lib/components/chat/MessageInput.svelte
@@ -495,6 +495,14 @@
$models.find((m) => m.id === model)?.info?.meta?.capabilities?.code_interpreter ?? true
);
+ let terminalCapableModels = [];
+ $: terminalCapableModels = (
+ atSelectedModel?.id ? [atSelectedModel.id] : selectedModels
+ ).filter(
+ (model) =>
+ $models.find((m) => m.id === model)?.info?.meta?.capabilities?.terminal ?? true
+ );
+
let toggleFilters = [];
$: toggleFilters = (atSelectedModel?.id ? [atSelectedModel.id] : selectedModels)
.map((id) => ($models.find((model) => model.id === id) || {})?.filters ?? [])
@@ -530,6 +538,11 @@
codeInterpreterEnabled = false;
}
+ // Clear selected terminal when model doesn't support terminal
+ $: if ($selectedTerminalId && terminalCapableModels.length === 0) {
+ selectedTerminalId.set(null);
+ }
+
const scrollToBottom = () => {
const element = document.getElementById('messages-container');
element.scrollTo({
@@ -1908,7 +1921,7 @@
{#if !history?.currentId || history.messages[history.currentId]?.done == true}
- {#if ($terminalServers ?? []).length > 0 || ($settings?.terminalServers ?? []).some((s) => s.url)}
+ {#if terminalCapableModels.length > 0 && (($terminalServers ?? []).length > 0 || ($settings?.terminalServers ?? []).some((s) => s.url))}