Coverage for src/local_deep_research/web/models/settings.py: 92%
51 statements
« prev ^ index » next coverage.py v7.14.1, created at 2026-06-03 23:15 +0000
« prev ^ index » next coverage.py v7.14.1, created at 2026-06-03 23:15 +0000
1from typing import Any, Dict, List, Optional
3from pydantic import BaseModel, ConfigDict, field_validator
5from ...database.models.settings import SettingType
8class BaseSetting(BaseModel):
9 """Base model for all settings"""
11 key: str
12 value: Any
13 type: SettingType
14 name: str
15 description: Optional[str] = None
16 category: Optional[str] = None
17 ui_element: Optional[str] = "text" # text, select, checkbox, slider, etc.
18 options: Optional[List[Dict[str, Any]]] = None # For select elements
19 min_value: Optional[float] = None # For numeric inputs
20 max_value: Optional[float] = None # For numeric inputs
21 step: Optional[float] = None # For sliders
22 visible: bool = True
23 editable: bool = True
25 model_config = ConfigDict(from_attributes=True)
28class LLMSetting(BaseSetting):
29 """LLM-specific settings"""
31 type: SettingType = SettingType.LLM
33 @field_validator("key")
34 def validate_llm_key(cls, v):
35 # Ensure LLM settings follow a convention
36 if not v.startswith("llm."):
37 return f"llm.{v}"
38 return v
41class SearchSetting(BaseSetting):
42 """Search-specific settings"""
44 type: SettingType = SettingType.SEARCH
46 @field_validator("key")
47 def validate_search_key(cls, v):
48 # Ensure search settings follow a convention
49 if not v.startswith("search."):
50 return f"search.{v}"
51 return v
54class ReportSetting(BaseSetting):
55 """Report generation settings"""
57 type: SettingType = SettingType.REPORT
59 @field_validator("key")
60 def validate_report_key(cls, v):
61 # Ensure report settings follow a convention
62 if not v.startswith("report."):
63 return f"report.{v}"
64 return v
67class AppSetting(BaseSetting):
68 """Application-wide settings"""
70 type: SettingType = SettingType.APP
72 @field_validator("key")
73 def validate_app_key(cls, v):
74 # Ensure app settings follow a convention
75 if not v.startswith("app."):
76 return f"app.{v}"
77 return v
80class ChatSetting(BaseSetting):
81 """Chat-mode settings (chat.* keys).
83 Mirrors the other typed wrappers so chat settings retain their
84 ``SettingType.CHAT`` type and ``category="chat"`` when they pass
85 through the settings UI save/edit cycle. Without this class, chat
86 keys were misclassified as ``AppSetting`` by the manager's prefix
87 dispatch and lost their category on save.
88 """
90 type: SettingType = SettingType.CHAT
92 @field_validator("key")
93 def validate_chat_key(cls, v):
94 if not v.startswith("chat."):
95 return f"chat.{v}"
96 return v
99class SettingsGroup(BaseModel):
100 """A group of related settings"""
102 name: str
103 description: Optional[str] = None
104 settings: List[BaseSetting]