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

1from typing import Any, Dict, List, Optional 

2 

3from pydantic import BaseModel, ConfigDict, field_validator 

4 

5from ...database.models.settings import SettingType 

6 

7 

8class BaseSetting(BaseModel): 

9 """Base model for all settings""" 

10 

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 

24 

25 model_config = ConfigDict(from_attributes=True) 

26 

27 

28class LLMSetting(BaseSetting): 

29 """LLM-specific settings""" 

30 

31 type: SettingType = SettingType.LLM 

32 

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 

39 

40 

41class SearchSetting(BaseSetting): 

42 """Search-specific settings""" 

43 

44 type: SettingType = SettingType.SEARCH 

45 

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 

52 

53 

54class ReportSetting(BaseSetting): 

55 """Report generation settings""" 

56 

57 type: SettingType = SettingType.REPORT 

58 

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 

65 

66 

67class AppSetting(BaseSetting): 

68 """Application-wide settings""" 

69 

70 type: SettingType = SettingType.APP 

71 

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 

78 

79 

80class ChatSetting(BaseSetting): 

81 """Chat-mode settings (chat.* keys). 

82 

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 """ 

89 

90 type: SettingType = SettingType.CHAT 

91 

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 

97 

98 

99class SettingsGroup(BaseModel): 

100 """A group of related settings""" 

101 

102 name: str 

103 description: Optional[str] = None 

104 settings: List[BaseSetting]