From 6370433ac37a4593a9d964e14cf41e60d0c83cb4 Mon Sep 17 00:00:00 2001 From: MaxMagician Date: Thu, 11 Dec 2025 01:47:47 -0800 Subject: [PATCH 1/2] Integration: Add proper Ollama support with Qwen3-VL default - Added Ollama provider support to LLM API layer. - Implemented to fix multimodal message formatting compatibility (resolves 400 Bad Request). - Fixed in agent retry logic. - Fixed in multimodal token counting. - Updated default model configuration to in , (hardcoded default), and . - Added new models to frontend settings list. - Updated default model state. --- frontend/src/App.js | 63 +++++++++++----------- frontend/src/components/SettingsPanel.js | 16 +++++- mirix/agent/agent.py | 1 + mirix/agent/agent_wrapper.py | 16 +++++- mirix/agent/app_constants.py | 10 ++++ mirix/configs/mirix.yaml | 6 +++ mirix/configs/mirix_monitor.yaml | 6 +++ mirix/configs/mirix_ollama.yaml | 6 +++ mirix/llm_api/llm_api_tools.py | 69 +++++++++++++++++++++++- mirix/llm_api/ollama_helpers.py | 40 ++++++++++++++ mirix/schemas/message.py | 6 ++- mirix/utils.py | 29 ++++++++-- 12 files changed, 228 insertions(+), 40 deletions(-) create mode 100644 mirix/configs/mirix_ollama.yaml create mode 100644 mirix/llm_api/ollama_helpers.py diff --git a/frontend/src/App.js b/frontend/src/App.js index 7273dcde..6920f06d 100644 --- a/frontend/src/App.js +++ b/frontend/src/App.js @@ -16,6 +16,7 @@ function App() { const [activeTab, setActiveTab] = useState('chat'); const [settings, setSettings] = useState({ model: 'gpt-4o-mini', + memoryModel: 'gpt-4o-mini', persona: 'helpful_assistant', timezone: 'America/New_York', serverUrl: 'http://localhost:47283' @@ -57,7 +58,7 @@ function App() { if (response.ok) { const data = await response.json(); console.log('API key status:', data); - + if (forceOpen || (data.requires_api_key && data.missing_keys.length > 0)) { if (forceOpen) { console.log('Manual API key update requested'); @@ -88,10 +89,10 @@ function App() { // Refresh backend-dependent data after successful connection const refreshBackendData = useCallback(async () => { console.log('🔄 Refreshing backend-dependent data...'); - + // Check API keys after successful backend connection await checkApiKeys(); - + // Trigger refresh of other backend-dependent components // This will cause components like SettingsPanel to re-fetch their data setSettings(prev => ({ ...prev, lastBackendRefresh: Date.now() })); @@ -101,7 +102,7 @@ function App() { const checkBackendHealth = useCallback(async () => { let shouldProceed = true; let currentVisibility = false; - + // Check if health check is already in progress and capture current visibility setBackendLoading(prev => { if (prev.isChecking) { @@ -133,7 +134,7 @@ function App() { if (response.ok) { console.log('✅ Backend is healthy - hiding loading modal'); - + setBackendLoading(prev => ({ ...prev, isVisible: false, @@ -148,7 +149,7 @@ function App() { console.log('🔄 Backend reconnected - refreshing data...'); await refreshBackendData(); } - + return true; } else { throw new Error(`Health check failed with status: ${response.status}`); @@ -187,15 +188,15 @@ function App() { useEffect(() => { const performInitialHealthCheck = async () => { // Show loading modal immediately for initial startup - setBackendLoading(prev => ({ - ...prev, - isVisible: true, + setBackendLoading(prev => ({ + ...prev, + isVisible: true, isReconnection: false // This is initial startup, not reconnection })); - + // Wait a moment for the UI to update await new Promise(resolve => setTimeout(resolve, 500)); - + // Check backend health (will automatically refresh data if modal was visible) await checkBackendHealth(); }; @@ -208,17 +209,17 @@ function App() { const interval = setInterval(() => { setBackendLoading(prev => { const timeSinceLastCheck = Date.now() - (prev.lastCheckTime || 0); - + // Check more frequently when modal is visible, less frequently when not - const shouldCheck = prev.isVisible + const shouldCheck = prev.isVisible ? !prev.isChecking // Every 5 seconds when modal is visible : timeSinceLastCheck > 30000 && !prev.isChecking; // Every 30 seconds when modal is hidden - + if (shouldCheck) { console.log('🔄 Periodic health check triggered. Modal visible:', prev.isVisible); checkBackendHealth(); } - + return prev; // Don't actually update state, just check conditions }); }, 5000); // Check every 5 seconds @@ -230,7 +231,7 @@ function App() { useEffect(() => { const handleWindowFocus = async () => { console.log('🔍 Window focused - checking backend health silently...'); - + // Check backend health silently - only show modal if it actually fails const healthCheckResult = await checkBackendHealth(); // Loading modal will be shown automatically by checkBackendHealth if it fails @@ -239,7 +240,7 @@ function App() { const handleVisibilityChange = async () => { if (!document.hidden) { console.log('🔍 Document became visible - checking backend health silently...'); - + // Check backend health silently - only show modal if it actually fails const healthCheckResult = await checkBackendHealth(); // Loading modal will be shown automatically by checkBackendHealth if it fails @@ -264,7 +265,7 @@ function App() { const handleApiKeySubmit = async () => { // Refresh API key status after submission await checkApiKeys(); - + // If there's a pending model change, retry it now if (pendingModelChange.retryFunction) { console.log(`Retrying ${pendingModelChange.type} model change to '${pendingModelChange.model}' after API key update`); @@ -285,7 +286,7 @@ function App() { useEffect(() => { // Listen for menu events from Electron const cleanupFunctions = []; - + if (window.electronAPI) { const cleanupNewChat = window.electronAPI.onMenuNewChat(() => { setActiveTab('chat'); @@ -309,7 +310,7 @@ function App() { // Handle Electron window events - check backend health silently const cleanupWindowShow = window.electronAPI.onWindowShow(async () => { console.log('🔍 Electron window shown - checking backend health silently...'); - + // Check backend health silently - only show modal if it actually fails const healthCheckResult = await checkBackendHealth(); // Loading modal will be shown automatically by checkBackendHealth if it fails @@ -318,7 +319,7 @@ function App() { const cleanupAppActivate = window.electronAPI.onAppActivate(async () => { console.log('🔍 Electron app activated - checking backend health silently...'); - + // Check backend health silently - only show modal if it actually fails const healthCheckResult = await checkBackendHealth(); // Loading modal will be shown automatically by checkBackendHealth if it fails @@ -344,32 +345,32 @@ function App() {
- v0.1.5
- - - -