From 7b84cd749221c1c42298265414194fab0ad5ce46 Mon Sep 17 00:00:00 2001 From: Storm Dragon Date: Mon, 11 Aug 2025 12:10:21 -0400 Subject: [PATCH] Ollama AI can now have customized api endpoint instead of always using localhost. --- distro-packages/Arch-Linux/PKGBUILD | 2 +- src/cthulhu/cthulhu-setup.ui | 32 +++++++++++++++++++++-- src/cthulhu/cthulhuVersion.py | 2 +- src/cthulhu/cthulhu_gui_prefs.py | 16 ++++++++++-- src/cthulhu/plugins/AIAssistant/plugin.py | 23 ++++++++++------ src/cthulhu/settings.py | 2 ++ 6 files changed, 63 insertions(+), 14 deletions(-) diff --git a/distro-packages/Arch-Linux/PKGBUILD b/distro-packages/Arch-Linux/PKGBUILD index fbfa809..cd3bd24 100644 --- a/distro-packages/Arch-Linux/PKGBUILD +++ b/distro-packages/Arch-Linux/PKGBUILD @@ -1,7 +1,7 @@ # Maintainer: Storm Dragon pkgname=cthulhu -pkgver=2025.08.06 +pkgver=2025.08.10 pkgrel=1 pkgdesc="Desktop-agnostic screen reader with plugin system, forked from Orca" url="https://git.stormux.org/storm/cthulhu" diff --git a/src/cthulhu/cthulhu-setup.ui b/src/cthulhu/cthulhu-setup.ui index cec0d39..e275007 100644 --- a/src/cthulhu/cthulhu-setup.ui +++ b/src/cthulhu/cthulhu-setup.ui @@ -3571,6 +3571,34 @@ 4 + + + True + False + start + Ollama _Endpoint: + True + aiOllamaEndpointEntry + + + 0 + 5 + + + + + True + True + True + http://localhost:11434 + Ollama API endpoint URL (e.g., http://192.168.1.100:11434) + + + + 1 + 5 + + True @@ -3582,7 +3610,7 @@ 0 - 5 + 6 @@ -3600,7 +3628,7 @@ 1 - 5 + 6 diff --git a/src/cthulhu/cthulhuVersion.py b/src/cthulhu/cthulhuVersion.py index 6045de0..5a95374 100644 --- a/src/cthulhu/cthulhuVersion.py +++ b/src/cthulhu/cthulhuVersion.py @@ -23,5 +23,5 @@ # Fork of Orca Screen Reader (GNOME) # Original source: https://gitlab.gnome.org/GNOME/orca -version = "2025.08.10" +version = "2025.08.11" codeName = "testing" diff --git a/src/cthulhu/cthulhu_gui_prefs.py b/src/cthulhu/cthulhu_gui_prefs.py index 9fb9f0d..0de0159 100644 --- a/src/cthulhu/cthulhu_gui_prefs.py +++ b/src/cthulhu/cthulhu_gui_prefs.py @@ -1855,6 +1855,7 @@ class CthulhuSetupGUI(cthulhu_gtkbuilder.GtkBuilderWrapper): self.aiProviderCombo = self.get_widget("aiProviderCombo") self.aiApiKeyEntry = self.get_widget("aiApiKeyEntry") self.aiOllamaModelEntry = self.get_widget("aiOllamaModelEntry") + self.aiOllamaEndpointEntry = self.get_widget("aiOllamaEndpointEntry") self.aiConfirmationCheckButton = self.get_widget("aiConfirmationCheckButton") self.aiScreenshotQualityCombo = self.get_widget("aiScreenshotQualityCombo") @@ -1883,6 +1884,10 @@ class CthulhuSetupGUI(cthulhu_gtkbuilder.GtkBuilderWrapper): ollamaModel = prefs.get("aiOllamaModel", settings.aiOllamaModel) self.aiOllamaModelEntry.set_text(ollamaModel) + # Set Ollama endpoint + ollamaEndpoint = prefs.get("aiOllamaEndpoint", settings.aiOllamaEndpoint) + self.aiOllamaEndpointEntry.set_text(ollamaEndpoint) + # Set confirmation checkbox confirmationRequired = prefs.get("aiConfirmationRequired", settings.aiConfirmationRequired) self.aiConfirmationCheckButton.set_active(confirmationRequired) @@ -1904,6 +1909,7 @@ class CthulhuSetupGUI(cthulhu_gtkbuilder.GtkBuilderWrapper): self.aiProviderCombo.set_sensitive(enabled) self.aiApiKeyEntry.set_sensitive(enabled) self.aiOllamaModelEntry.set_sensitive(enabled) + self.aiOllamaEndpointEntry.set_sensitive(enabled) self.aiConfirmationCheckButton.set_sensitive(enabled) self.aiScreenshotQualityCombo.set_sensitive(enabled) try: @@ -1929,8 +1935,10 @@ class CthulhuSetupGUI(cthulhu_gtkbuilder.GtkBuilderWrapper): except: pass # Button might not exist - # Ollama model entry (only for Ollama) - self.aiOllamaModelEntry.set_sensitive(provider == settings.AI_PROVIDER_OLLAMA) + # Ollama model and endpoint entries (only for Ollama) + ollama_enabled = provider == settings.AI_PROVIDER_OLLAMA + self.aiOllamaModelEntry.set_sensitive(ollama_enabled) + self.aiOllamaEndpointEntry.set_sensitive(ollama_enabled) # Update labels based on provider if provider == settings.AI_PROVIDER_CLAUDE_CODE: @@ -3701,6 +3709,10 @@ class CthulhuSetupGUI(cthulhu_gtkbuilder.GtkBuilderWrapper): """AI Ollama model entry changed handler""" self.prefsDict["aiOllamaModel"] = widget.get_text() + def aiOllamaEndpointChanged(self, widget): + """AI Ollama endpoint entry changed handler""" + self.prefsDict["aiOllamaEndpoint"] = widget.get_text() + def aiGetClaudeKeyClicked(self, widget): """Get Claude API Key button clicked handler""" import subprocess diff --git a/src/cthulhu/plugins/AIAssistant/plugin.py b/src/cthulhu/plugins/AIAssistant/plugin.py index 3616a8c..d6e046f 100644 --- a/src/cthulhu/plugins/AIAssistant/plugin.py +++ b/src/cthulhu/plugins/AIAssistant/plugin.py @@ -61,6 +61,7 @@ class AIAssistant(Plugin): self._ai_provider = None self._api_key = None self._ollama_model = None + self._ollama_endpoint = None self._settings_manager = settings_manager.getManager() # Plugin enabled state @@ -153,14 +154,19 @@ class AIAssistant(Plugin): else: self._api_key = None - # Load Ollama model + # Load Ollama model and endpoint self._ollama_model = self._settings_manager.getSetting('aiOllamaModel') if not self._ollama_model: self._ollama_model = settings.aiOllamaModel + self._ollama_endpoint = self._settings_manager.getSetting('aiOllamaEndpoint') + if not self._ollama_endpoint: + self._ollama_endpoint = settings.aiOllamaEndpoint + logger.info(f"AI settings loaded: provider={self._provider_type}, " f"api_key_configured={bool(self._api_key)}, " - f"ollama_model={self._ollama_model}") + f"ollama_model={self._ollama_model}, " + f"ollama_endpoint={self._ollama_endpoint}") except Exception as e: logger.error(f"Error loading AI settings: {e}") @@ -195,16 +201,17 @@ class AIAssistant(Plugin): """Check if Ollama is available and has vision models.""" try: import requests - # Check if Ollama is running - response = requests.get('http://localhost:11434/api/version', timeout=5) + # Check if Ollama is running at the configured endpoint + endpoint_url = f"{self._ollama_endpoint}/api/version" + response = requests.get(endpoint_url, timeout=5) if response.status_code == 200: - logger.info("Ollama service is available") + logger.info(f"Ollama service is available at {self._ollama_endpoint}") return True else: - logger.warning("Ollama service not responding") + logger.warning(f"Ollama service not responding at {self._ollama_endpoint}") return False except Exception as e: - logger.warning(f"Ollama not available: {e}") + logger.warning(f"Ollama not available at {self._ollama_endpoint}: {e}") return False def _check_claude_code_availability(self): @@ -242,7 +249,7 @@ class AIAssistant(Plugin): elif self._provider_type == settings.AI_PROVIDER_CLAUDE_CODE: self._ai_provider = create_provider("claude_code") elif self._provider_type == settings.AI_PROVIDER_OLLAMA: - self._ai_provider = create_provider("ollama", model=self._ollama_model) + self._ai_provider = create_provider("ollama", model=self._ollama_model, base_url=self._ollama_endpoint) else: logger.error(f"Unsupported provider type: {self._provider_type}") return False diff --git a/src/cthulhu/settings.py b/src/cthulhu/settings.py index b5758d7..bfac14d 100644 --- a/src/cthulhu/settings.py +++ b/src/cthulhu/settings.py @@ -153,6 +153,7 @@ userCustomizableSettings = [ "aiProvider", "aiApiKeyFile", "aiOllamaModel", + "aiOllamaEndpoint", "aiConfirmationRequired", "aiActionTimeout", "aiScreenshotQuality", @@ -439,6 +440,7 @@ aiAssistantEnabled = True aiProvider = AI_PROVIDER_CLAUDE_CODE aiApiKeyFile = "" aiOllamaModel = "llama3.2-vision" +aiOllamaEndpoint = "http://localhost:11434" aiConfirmationRequired = True aiActionTimeout = 30 aiScreenshotQuality = AI_SCREENSHOT_QUALITY_MEDIUM