Prepare for stable release 2025.12.09

- Remove all DEBUG print statements from AIAssistant plugin
- Update version to 2025.12.09 across all build files
  - src/cthulhu/cthulhuVersion.py
  - meson.build
  - distro-packages/Arch-Linux/PKGBUILD
- Add OCR optional dependencies to meson.build
  - pdf2image: PDF processing for OCR
  - scipy: Scientific computing for OCR analysis
  - webcolors: Color name resolution for OCR
- Add explicit OCR Python packages to PKGBUILD optdepends
  - python-pdf2image
  - python-scipy
  - python-webcolors
- Remove temporary test files from repository root
  - test_atspi_version.py
  - test_axtext_basic.py
  - test_modern_atspi_keystroke.py

All changes validated with successful local build.
Ready for final testing before stable release tag.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Storm Dragon
2025-12-09 09:21:52 -05:00
parent 11240bfcbc
commit 53614b13b9
5 changed files with 509 additions and 68 deletions

View File

@@ -23,5 +23,5 @@
# Fork of Orca Screen Reader (GNOME)
# Original source: https://gitlab.gnome.org/GNOME/orca
version = "2025.08.22"
version = "2025.12.09"
codeName = "testing"

View File

@@ -46,9 +46,7 @@ class AIAssistant(Plugin):
def __init__(self, *args, **kwargs):
"""Initialize the AI Assistant plugin."""
super().__init__(*args, **kwargs)
# Use print to ensure we see this message
print("DEBUG: AI ASSISTANT __init__ called")
logger.info("AI ASSISTANT: Plugin __init__ starting")
logger.info("AI ASSISTANT: Plugin initialized successfully")
@@ -79,51 +77,40 @@ class AIAssistant(Plugin):
# Prevent multiple activations
if self._enabled:
logger.info("AI ASSISTANT: Already activated, skipping")
print("DEBUG: AI ASSISTANT already activated, skipping")
return
try:
logger.info("AI ASSISTANT: === Plugin activation starting ===")
print("DEBUG: AI ASSISTANT activation starting")
# Check if AI Assistant is enabled in settings
enabled = self._settings_manager.getSetting('aiAssistantEnabled')
logger.info(f"AI ASSISTANT: Enabled setting: {enabled}")
print(f"DEBUG: AI ASSISTANT enabled setting: {enabled}")
if not enabled:
logger.info("AI Assistant is disabled in settings, skipping activation")
print("DEBUG: AI Assistant disabled, skipping activation")
return
# Load AI settings
self._load_ai_settings()
print(f"DEBUG: AI settings loaded - provider: {self._provider_type}")
# Check if we have valid configuration
config_valid = self._validate_configuration()
logger.info(f"AI Assistant configuration valid: {config_valid}")
print(f"DEBUG: AI Assistant configuration valid: {config_valid}")
# Initialize AI provider (may fail but we still want menu access)
if config_valid:
provider_init = self._initialize_ai_provider()
print(f"DEBUG: AI provider initialization: {provider_init}")
else:
logger.warning("AI Assistant configuration invalid, menu will show error messages")
print("DEBUG: AI Assistant configuration invalid, menu will show error messages")
provider_init = False
# Always register keybindings so menu is accessible even with config issues
self._register_keybindings()
print("DEBUG: AI keybindings registered")
self._enabled = True
logger.info("AI Assistant plugin activated successfully")
print("DEBUG: AI Assistant plugin activated successfully")
except Exception as e:
logger.error(f"Error activating AI Assistant plugin: {e}")
print(f"DEBUG: Error activating AI Assistant plugin: {e}")
import traceback
logger.error(traceback.format_exc())
@@ -144,44 +131,35 @@ class AIAssistant(Plugin):
"""Refresh plugin settings and reinitialize provider. Called when settings change."""
try:
logger.info("AI Assistant: Refreshing settings")
print("DEBUG: AI Assistant refreshing settings")
# Reload settings
self._load_ai_settings()
# Validate new configuration
config_valid = self._validate_configuration()
print(f"DEBUG: New configuration valid: {config_valid}")
# Reinitialize provider if configuration is valid
if config_valid:
old_provider = self._ai_provider
provider_init = self._initialize_ai_provider()
print(f"DEBUG: Provider reinitialization: {provider_init}")
if provider_init:
logger.info(f"AI Assistant provider changed to: {self._provider_type}")
print(f"DEBUG: Provider successfully changed to: {self._provider_type}")
else:
logger.warning("Failed to initialize new provider")
print("DEBUG: Failed to initialize new provider")
self._ai_provider = None
else:
logger.warning("New configuration invalid, clearing provider")
print("DEBUG: New configuration invalid, clearing provider")
self._ai_provider = None
except Exception as e:
logger.error(f"Error refreshing AI Assistant settings: {e}")
print(f"DEBUG: Error refreshing settings: {e}")
def _load_ai_settings(self):
"""Load AI Assistant settings from Cthulhu configuration."""
try:
# Get provider
provider = self._settings_manager.getSetting('aiProvider')
print(f"DEBUG: Raw provider setting: '{provider}'")
self._provider_type = provider or settings.AI_PROVIDER_CLAUDE_CODE
print(f"DEBUG: Final provider type: '{self._provider_type}'")
# Load API key from file
api_key_file = self._settings_manager.getSetting('aiApiKeyFile')
@@ -308,10 +286,9 @@ class AIAssistant(Plugin):
"Show AI Assistant menu",
'kb:cthulhu+shift+control+a'
)
logger.info("AI Assistant menu keybinding registered")
print(f"DEBUG: AI Assistant menu keybinding registered: {self._kb_binding_menu}")
except Exception as e:
logger.error(f"Error registering AI menu keybinding: {e}")
@@ -325,22 +302,18 @@ class AIAssistant(Plugin):
"""Show the AI Assistant menu."""
try:
logger.info("AI ASSISTANT: _show_ai_menu called!")
print("DEBUG: AI ASSISTANT _show_ai_menu called!")
# IMPORTANT: Capture screen data BEFORE showing menu
# This ensures we get the actual screen content, not the menu itself
self._pre_menu_screen_data = self._collect_ai_data()
logger.info("Pre-captured screen data for menu actions")
print("DEBUG: Pre-captured screen data for menu actions")
# Now show the menu
self._menu_gui = AIAssistantMenu(self._handle_menu_selection)
self._menu_gui.show_gui()
print("DEBUG: AI menu GUI shown")
return True
except Exception as e:
logger.error(f"Error showing AI menu: {e}")
print(f"DEBUG: Error showing AI menu: {e}")
import traceback
traceback.print_exc()
return False
@@ -407,22 +380,17 @@ class AIAssistant(Plugin):
"""Handle browsing for an image file to analyze."""
try:
logger.info("AI image file browsing requested")
print("DEBUG: _handle_browse_image_file called")
if not self._enabled:
print("DEBUG: AI Assistant not enabled")
self._present_message("AI Assistant is not enabled")
return True
if not self._ai_provider:
print("DEBUG: AI provider not available")
self._present_message("AI provider not available. Check configuration.")
return True
# Show file chooser dialog
print("DEBUG: About to show file chooser")
image_file = self._show_image_file_chooser()
print(f"DEBUG: File chooser returned: {image_file}")
if image_file:
provider_name = self._provider_type.replace('_', ' ').title()
@@ -536,10 +504,8 @@ class AIAssistant(Plugin):
"""Handle main AI Assistant activation - now shows action dialog."""
try:
logger.info("AI Assistant activation requested")
print("DEBUG: AI Assistant activation keybinding triggered!")
if not self._enabled:
print("DEBUG: AI Assistant not enabled, presenting message")
self._present_message("AI Assistant is not enabled")
return True
@@ -2077,13 +2043,9 @@ class AIAssistantMenu(Gtk.Dialog):
# Connect keyboard events for Enter key handling
self.connect("key-press-event", self._on_key_press)
print("DEBUG: AIAssistantMenu dialog created with radio buttons")
def _on_response(self, dialog, response_id):
"""Handler for dialog response."""
print(f"DEBUG: Dialog response: {response_id}")
if response_id == Gtk.ResponseType.OK:
# Determine which radio button is selected
if self.radio_ask.get_active():
@@ -2098,9 +2060,8 @@ class AIAssistantMenu(Gtk.Dialog):
action_id = "browse_image_file"
else:
action_id = None
if action_id:
print(f"DEBUG: Selected action: {action_id}")
self.on_option_selected(action_id)
self.destroy()
@@ -2116,15 +2077,12 @@ class AIAssistantMenu(Gtk.Dialog):
def show_gui(self):
"""Shows the AI Assistant dialog."""
try:
print("DEBUG: Starting dialog show_gui")
self.show_all()
print("DEBUG: Dialog show_all() called - should be visible and accessible now")
# Present the dialog to ensure it gets focus
self.present()
print("DEBUG: Dialog presented")
except Exception as e:
print(f"DEBUG: Error in show_gui: {e}")
logger.error(f"Error in show_gui: {e}")
import traceback
traceback.print_exc()