feat: add multi-provider support to chat widget

- Added support for multiple AI providers (Ollama, Gemini, OpenRouter, Copilot) with provider abstraction layer
- Created settings view with provider configuration and API key management
- Updated UI to show current provider status and handle provider-specific availability
- Modified reasoning mode to work exclusively with Ollama provider
- Added provider switching functionality with persistent settings
- Updated error messages and placeholders to be
This commit is contained in:
Melvin Ragusa
2025-10-31 00:08:04 +01:00
parent 55aad289bc
commit 6cc11fc9e4
4 changed files with 1396 additions and 57 deletions

View File

@@ -15,6 +15,14 @@ class PreferencesState:
reasoning_enabled: bool = False
default_model: str | None = None
theme: str = "default"
provider: str = "ollama" # AI provider: "ollama", "gemini", "openrouter", "copilot"
api_keys: Dict[str, str] = None # API keys for providers (gemini, openrouter)
copilot_oauth_token: str | None = None # GitHub Copilot OAuth token
def __post_init__(self):
"""Initialize api_keys if None."""
if self.api_keys is None:
self.api_keys = {}
class ReasoningController:
@@ -66,6 +74,10 @@ class ReasoningController:
Returns:
Dictionary of model-specific parameters
"""
# Only return options for Ollama (other providers don't use these)
if self._preferences.provider != "ollama":
return {}
if self._preferences.reasoning_enabled:
# Thinking model settings
return {
@@ -85,6 +97,33 @@ class ReasoningController:
"num_predict": 32768,
}
def get_provider(self) -> str:
"""Get the current AI provider."""
return self._preferences.provider
def set_provider(self, provider: str) -> None:
"""Set the AI provider."""
self._preferences.provider = provider
self._save_preferences()
def get_api_key(self, provider: str) -> str | None:
"""Get API key for a provider."""
return self._preferences.api_keys.get(provider)
def set_api_key(self, provider: str, api_key: str) -> None:
"""Set API key for a provider."""
self._preferences.api_keys[provider] = api_key
self._save_preferences()
def get_copilot_token(self) -> str | None:
"""Get GitHub Copilot OAuth token."""
return self._preferences.copilot_oauth_token
def set_copilot_token(self, token: str | None) -> None:
"""Set GitHub Copilot OAuth token."""
self._preferences.copilot_oauth_token = token
self._save_preferences()
def _load_preferences(self) -> PreferencesState:
"""Load preferences from disk or create defaults.
@@ -101,6 +140,9 @@ class ReasoningController:
reasoning_enabled=data.get("reasoning_enabled", False),
default_model=data.get("default_model"),
theme=data.get("theme", "default"),
provider=data.get("provider", "ollama"),
api_keys=data.get("api_keys", {}),
copilot_oauth_token=data.get("copilot_oauth_token"),
)
except (json.JSONDecodeError, OSError):
# If file is corrupted or unreadable, return defaults