Files
niri-ai-sidebar/ollama_monitor.py
Melvin Ragusa 239242e2fc refactor(aisidebar): restructure project and implement reasoning mode toggle
- Reorganize project structure and file locations
- Add ReasoningController to manage model selection and reasoning mode
- Update design and requirements for reasoning mode toggle
- Implement model switching between Qwen3-4B-Instruct and Qwen3-4B-Thinking models
- Remove deprecated files and consolidate project layout
- Add new steering and specification documentation
- Clean up and remove unnecessary files and directories
- Prepare for enhanced AI sidebar functionality with more flexible model handling
2025-10-26 09:10:31 +01:00

104 lines
3.5 KiB
Python

"""Monitor for tracking Ollama availability and notifying on state changes."""
from __future__ import annotations
from typing import Callable
from gi.repository import GLib
from .ollama_client import OllamaClient
class OllamaAvailabilityMonitor:
"""Monitors Ollama availability and notifies callbacks on state changes."""
def __init__(self, client: OllamaClient, check_interval_seconds: int = 30) -> None:
"""
Initialize the availability monitor.
Args:
client: OllamaClient instance to monitor
check_interval_seconds: How often to check availability (default: 30s)
"""
self._client = client
self._check_interval_ms = check_interval_seconds * 1000
self._callbacks: list[Callable[[bool], None]] = []
self._last_state: bool | None = None
self._timeout_id: int | None = None
self._is_running = False
def add_callback(self, callback: Callable[[bool], None]) -> None:
"""
Add a callback to be notified when availability changes.
Args:
callback: Function that takes a bool (True if available, False if not)
"""
if callback not in self._callbacks:
self._callbacks.append(callback)
def remove_callback(self, callback: Callable[[bool], None]) -> None:
"""Remove a previously registered callback."""
if callback in self._callbacks:
self._callbacks.remove(callback)
def start(self) -> None:
"""Start monitoring Ollama availability."""
if self._is_running:
return
self._is_running = True
# Do an immediate check
self._check_availability()
# Schedule periodic checks
self._timeout_id = GLib.timeout_add(
self._check_interval_ms,
self._check_availability
)
def stop(self) -> None:
"""Stop monitoring Ollama availability."""
if not self._is_running:
return
self._is_running = False
if self._timeout_id is not None:
GLib.source_remove(self._timeout_id)
self._timeout_id = None
def _check_availability(self) -> bool:
"""
Check current availability and notify callbacks if state changed.
Returns:
True to continue periodic checks, False to stop
"""
# Force a connection check
self._client._check_connection()
current_state = self._client.is_available
# Only notify if state changed
if self._last_state is None or self._last_state != current_state:
self._last_state = current_state
self._notify_callbacks(current_state)
# Return True to continue periodic checks
return True
def _notify_callbacks(self, is_available: bool) -> None:
"""Notify all registered callbacks of the availability state."""
for callback in self._callbacks:
try:
callback(is_available)
except Exception as e:
# Log error but don't let one callback failure affect others
print(f"Error in availability callback: {e}")
@property
def is_running(self) -> bool:
"""Check if the monitor is currently running."""
return self._is_running
@property
def current_state(self) -> bool | None:
"""Get the last known availability state (None if never checked)."""
return self._last_state