diff --git a/web-app/src/containers/Capabilities.tsx b/web-app/src/containers/Capabilities.tsx index e2e09030a..07f3bf0d6 100644 --- a/web-app/src/containers/Capabilities.tsx +++ b/web-app/src/containers/Capabilities.tsx @@ -10,6 +10,7 @@ import { IconAtom, IconWorld, IconCodeCircle2, + IconSparkles, } from '@tabler/icons-react' import { Fragment } from 'react/jsx-runtime' @@ -29,6 +30,8 @@ const Capabilities = ({ capabilities }: CapabilitiesProps) => { icon = } else if (capability === 'tools') { icon = + } else if (capability === 'proactive') { + icon = } else if (capability === 'reasoning') { icon = } else if (capability === 'embeddings') { @@ -54,7 +57,11 @@ const Capabilities = ({ capabilities }: CapabilitiesProps) => {

- {capability === 'web_search' ? 'Web Search' : capability} + {capability === 'web_search' + ? 'Web Search' + : capability === 'proactive' + ? 'Proactive' + : capability}

diff --git a/web-app/src/containers/ChatInput.tsx b/web-app/src/containers/ChatInput.tsx index 564e295c4..5a29d5928 100644 --- a/web-app/src/containers/ChatInput.tsx +++ b/web-app/src/containers/ChatInput.tsx @@ -108,6 +108,7 @@ const ChatInput = ({ const [connectedServers, setConnectedServers] = useState([]) const [isDragOver, setIsDragOver] = useState(false) const [hasMmproj, setHasMmproj] = useState(false) + const [hasProactive, setHasProactive] = useState(false) const [hasActiveModels, setHasActiveModels] = useState(false) const attachmentsEnabled = useAttachments((s) => s.enabled) // Determine whether to show the Attach documents button (simple gating) @@ -206,6 +207,29 @@ const ChatInput = ({ checkMmprojSupport() }, [selectedModel, selectedModel?.capabilities, selectedProvider, serviceHub]) + // Check for proactive capability when model changes + useEffect(() => { + const checkProactiveSupport = () => { + if (selectedModel && selectedModel?.id) { + // Proactive mode requires both tools and vision capabilities + const hasTools = selectedModel?.capabilities?.includes('tools') + const hasVision = selectedModel?.capabilities?.includes('vision') + const hasProactiveCapability = selectedModel?.capabilities?.includes('proactive') + + if (hasTools && hasVision && hasProactiveCapability) { + setHasProactive(true) + // TODO: Implement proactive mode template insertion + // This is where we'll add the proactive mode prompt/template + // when sending messages with models that have proactive capability enabled + } else { + setHasProactive(false) + } + } + } + + checkProactiveSupport() + }, [selectedModel, selectedModel?.capabilities]) + // Check if there are active MCP servers const hasActiveMCPServers = connectedServers.length > 0 || tools.length > 0 diff --git a/web-app/src/containers/ModelInfoHoverCard.tsx b/web-app/src/containers/ModelInfoHoverCard.tsx index 63f5f3183..25edff914 100644 --- a/web-app/src/containers/ModelInfoHoverCard.tsx +++ b/web-app/src/containers/ModelInfoHoverCard.tsx @@ -152,12 +152,19 @@ export const ModelInfoHoverCard = ({ {/* Features Section */} - {(model.num_mmproj > 0 || model.tools) && ( + {(model.num_mmproj > 0 || model.tools || (model.num_mmproj > 0 && model.tools)) && (
Features
+ {model.tools && ( +
+ + Tools + +
+ )} {model.num_mmproj > 0 && (
@@ -165,10 +172,10 @@ export const ModelInfoHoverCard = ({
)} - {model.tools && ( + {model.num_mmproj > 0 && model.tools && (
- Tools + Proactive
)} diff --git a/web-app/src/containers/__tests__/EditModel.test.tsx b/web-app/src/containers/__tests__/EditModel.test.tsx index 6c0dfd059..345bc91d6 100644 --- a/web-app/src/containers/__tests__/EditModel.test.tsx +++ b/web-app/src/containers/__tests__/EditModel.test.tsx @@ -82,6 +82,7 @@ vi.mock('@tabler/icons-react', () => ({ IconEye: () =>
, IconTool: () =>
, IconLoader2: () =>
, + IconSparkles: () =>
, })) describe('DialogEditModel - Basic Component Tests', () => { @@ -189,7 +190,7 @@ describe('DialogEditModel - Basic Component Tests', () => { { id: 'test-model.gguf', displayName: 'Test Model', - capabilities: ['vision', 'tools'], + capabilities: ['vision', 'tools', 'proactive'], }, ], settings: [], @@ -226,7 +227,7 @@ describe('DialogEditModel - Basic Component Tests', () => { { id: 'test-model.gguf', displayName: 'Test Model', - capabilities: ['vision', 'tools', 'completion', 'embeddings', 'web_search', 'reasoning'], + capabilities: ['vision', 'tools', 'proactive', 'completion', 'embeddings', 'web_search', 'reasoning'], }, ], settings: [], @@ -240,7 +241,7 @@ describe('DialogEditModel - Basic Component Tests', () => { ) // Component should render without errors even with extra capabilities - // The capabilities helper should only extract vision and tools + // The capabilities helper should only extract vision, tools, and proactive expect(container).toBeInTheDocument() }) }) diff --git a/web-app/src/containers/dialogs/EditModel.tsx b/web-app/src/containers/dialogs/EditModel.tsx index f7dec06eb..78f6e93c2 100644 --- a/web-app/src/containers/dialogs/EditModel.tsx +++ b/web-app/src/containers/dialogs/EditModel.tsx @@ -17,6 +17,7 @@ import { IconTool, IconAlertTriangle, IconLoader2, + IconSparkles, } from '@tabler/icons-react' import { useState, useEffect } from 'react' import { useTranslation } from '@/i18n/react-i18next-compat' @@ -45,6 +46,7 @@ export const DialogEditModel = ({ const [capabilities, setCapabilities] = useState>({ vision: false, tools: false, + proactive: false, }) // Initialize with the provided model ID or the first model if available @@ -67,6 +69,7 @@ export const DialogEditModel = ({ const capabilitiesToObject = (capabilitiesList: string[]) => ({ vision: capabilitiesList.includes('vision'), tools: capabilitiesList.includes('tools'), + proactive: capabilitiesList.includes('proactive'), }) // Initialize capabilities and display name from selected model @@ -268,6 +271,23 @@ export const DialogEditModel = ({ disabled={isLoading} />
+ +
+
+ + + {t('providers:editModel.proactive')} + +
+ + handleCapabilityChange('proactive', checked) + } + disabled={isLoading || !(capabilities.tools && capabilities.vision)} + /> +
diff --git a/web-app/src/locales/de-DE/providers.json b/web-app/src/locales/de-DE/providers.json index 39c52e047..9f75f4cde 100644 --- a/web-app/src/locales/de-DE/providers.json +++ b/web-app/src/locales/de-DE/providers.json @@ -61,6 +61,7 @@ "capabilities": "Fähigkeiten", "tools": "Werkzeuge", "vision": "Vision", + "proactive": "Proaktiv (Experimentell)", "embeddings": "Einbettungen", "notAvailable": "Noch nicht verfügbar", "warning": { diff --git a/web-app/src/locales/en/providers.json b/web-app/src/locales/en/providers.json index 2683432f9..48eb30e12 100644 --- a/web-app/src/locales/en/providers.json +++ b/web-app/src/locales/en/providers.json @@ -61,6 +61,7 @@ "capabilities": "Capabilities", "tools": "Tools", "vision": "Vision", + "proactive": "Proactive (Experimental)", "embeddings": "Embeddings", "notAvailable": "Not available yet", "warning": { diff --git a/web-app/src/locales/id/providers.json b/web-app/src/locales/id/providers.json index 5f89d69c6..1679b5b45 100644 --- a/web-app/src/locales/id/providers.json +++ b/web-app/src/locales/id/providers.json @@ -61,6 +61,7 @@ "capabilities": "Kemampuan", "tools": "Alat", "vision": "Visi", + "proactive": "Proaktif (Eksperimental)", "embeddings": "Embedding", "notAvailable": "Belum tersedia", "warning": { diff --git a/web-app/src/locales/pl/providers.json b/web-app/src/locales/pl/providers.json index c1c03434e..6100db994 100644 --- a/web-app/src/locales/pl/providers.json +++ b/web-app/src/locales/pl/providers.json @@ -61,6 +61,7 @@ "capabilities": "Możliwości", "tools": "Narzędzia", "vision": "Wizja", + "proactive": "Proaktywny (Eksperymentalny)", "embeddings": "Osadzenia", "notAvailable": "Jeszcze niedostępne", "warning": { diff --git a/web-app/src/locales/vn/providers.json b/web-app/src/locales/vn/providers.json index 8c0e6d1b8..adf7e6528 100644 --- a/web-app/src/locales/vn/providers.json +++ b/web-app/src/locales/vn/providers.json @@ -61,6 +61,7 @@ "capabilities": "Khả năng", "tools": "Công cụ", "vision": "Thị giác", + "proactive": "Chủ động (Thử nghiệm)", "embeddings": "Nhúng", "notAvailable": "Chưa có", "warning": { diff --git a/web-app/src/locales/zh-CN/providers.json b/web-app/src/locales/zh-CN/providers.json index 2ca2beb2e..c4e6b03cb 100644 --- a/web-app/src/locales/zh-CN/providers.json +++ b/web-app/src/locales/zh-CN/providers.json @@ -61,6 +61,7 @@ "capabilities": "功能", "tools": "工具", "vision": "视觉", + "proactive": "主动模式(实验性)", "embeddings": "嵌入", "notAvailable": "尚不可用", "warning": { diff --git a/web-app/src/locales/zh-TW/providers.json b/web-app/src/locales/zh-TW/providers.json index 39580818b..094c0f245 100644 --- a/web-app/src/locales/zh-TW/providers.json +++ b/web-app/src/locales/zh-TW/providers.json @@ -61,6 +61,7 @@ "capabilities": "功能", "tools": "工具", "vision": "視覺", + "proactive": "主動模式(實驗性)", "embeddings": "嵌入", "notAvailable": "尚不可用", "warning": {