@@ -70,9 +70,9 @@ def get_all(self) -> dict[str, str]:
7070 settings [row ["key" ]] = row ["value" ]
7171 return settings
7272
73- def get_provider (self ) -> AIProviderType :
74- """Get the current AI provider."""
75- return AIProviderType ( self .get ("ai_provider" ) )
73+ def get_provider (self ) -> str :
74+ """Return the active provider name as a string ."""
75+ return self .get ("ai_provider" )
7676
7777 def get_model (self ) -> str :
7878 """Get the current AI model override."""
@@ -104,3 +104,47 @@ def set_weights(self, weights: dict[str, int]) -> None:
104104 def reset_weights (self ) -> None :
105105 """Reset recommendation weights to defaults."""
106106 self .set_weights (DEFAULT_WEIGHTS )
107+
108+ # Reserved names that cannot be used for custom providers
109+ RESERVED_PROVIDERS = {"gemini" , "claude" , "openai" , "ollama" , "opencode" , "custom" }
110+
111+ def get_custom_providers (self ) -> list :
112+ """Return all custom providers as list of CustomProviderConfig."""
113+ from ..core .models import CustomProviderConfig
114+
115+ with get_connection () as conn :
116+ rows = conn .execute (
117+ "SELECT name, preset, command_template, default_model FROM custom_providers ORDER BY name"
118+ ).fetchall ()
119+ return [
120+ CustomProviderConfig (
121+ name = r ["name" ],
122+ preset = r ["preset" ],
123+ command_template = r ["command_template" ],
124+ default_model = r ["default_model" ] or "" ,
125+ )
126+ for r in rows
127+ ]
128+
129+ def add_custom_provider (
130+ self , name : str , preset : str , command_template : str , default_model : str = ""
131+ ) -> None :
132+ """Register a custom provider. Raises ValueError if name is reserved or duplicate."""
133+ if name .lower () in self .RESERVED_PROVIDERS :
134+ raise ValueError (f"'{ name } ' is a reserved provider name" )
135+ with get_connection () as conn :
136+ conn .execute (
137+ "INSERT OR REPLACE INTO custom_providers (name, preset, command_template, default_model) "
138+ "VALUES (?, ?, ?, ?)" ,
139+ (name , preset , command_template , default_model ),
140+ )
141+ conn .commit ()
142+
143+ def remove_custom_provider (self , name : str ) -> None :
144+ """Remove a custom provider. If it's the active provider, switch to gemini."""
145+ with get_connection () as conn :
146+ conn .execute ("DELETE FROM custom_providers WHERE name = ?" , (name ,))
147+ conn .commit ()
148+ # If active provider was deleted, reset to gemini
149+ if self .get ("ai_provider" ) == name :
150+ self .set ("ai_provider" , "gemini" )
0 commit comments