Coverage for src / local_deep_research / web / warning_checks / __init__.py: 88%
80 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-14 23:55 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-14 23:55 +0000
1"""Warning calculation for the settings UI.
3Thin orchestrator: reads settings from a single DB session,
4delegates to pure check functions in hardware.py and context.py.
5"""
7from typing import List
9from flask import session
10from loguru import logger
12from ...database.session_context import get_user_db_session
13from ...utilities.db_utils import get_settings_manager
14from .context import (
15 check_context_below_history,
16 check_context_truncation_history,
17)
18from .backup import (
19 check_backup_disabled,
20 check_backup_healthy,
21 check_no_backups_exist,
22)
23from .hardware import (
24 LOCAL_PROVIDERS,
25 check_high_context,
26 check_legacy_server_config,
27 check_model_mismatch,
28)
31def _safe_check(check_fn, *args, **kwargs):
32 """Run a single warning check, returning None on failure."""
33 try:
34 return check_fn(*args, **kwargs)
35 except Exception:
36 name = getattr(check_fn, "__name__", repr(check_fn))
37 logger.exception(f"Warning check {name} failed")
38 return None
41def calculate_warnings() -> List[dict]:
42 """Calculate current warning conditions based on settings.
44 Uses a single DB session for all setting reads and history queries.
45 """
46 warnings: List[dict] = []
48 try:
49 username = session.get("username")
50 with get_user_db_session(username) as db_session:
51 if not db_session:
52 return []
54 settings_manager = get_settings_manager(db_session, username)
56 # Read all needed settings in one session
57 provider = settings_manager.get_setting(
58 "llm.provider", "ollama"
59 ).lower()
60 local_context = settings_manager.get_setting(
61 "llm.local_context_window_size", 8192
62 )
63 current_model = settings_manager.get_setting("llm.model", "")
64 dismiss_high_context = settings_manager.get_setting(
65 "app.warnings.dismiss_high_context", False
66 )
67 dismiss_model_mismatch = settings_manager.get_setting(
68 "app.warnings.dismiss_model_mismatch", False
69 )
70 dismiss_context_warning = settings_manager.get_setting(
71 "app.warnings.dismiss_context_reduced", False
72 )
73 dismiss_legacy_config = settings_manager.get_setting(
74 "app.warnings.dismiss_legacy_config", False
75 )
76 backup_enabled = settings_manager.get_setting(
77 "backup.enabled", True
78 )
79 dismiss_backup_disabled = settings_manager.get_setting(
80 "app.warnings.dismiss_backup_disabled", False
81 )
82 dismiss_no_backups = settings_manager.get_setting(
83 "app.warnings.dismiss_no_backups", False
84 )
86 logger.debug(f"Starting warning calculation - provider={provider}")
88 is_local = provider in LOCAL_PROVIDERS
90 # --- Hardware / settings checks (pure functions) ---
91 w = _safe_check(
92 check_high_context,
93 provider,
94 local_context,
95 dismiss_high_context,
96 )
97 if w:
98 warnings.append(w)
100 w = _safe_check(
101 check_model_mismatch,
102 provider,
103 current_model,
104 local_context,
105 dismiss_model_mismatch,
106 )
107 if w:
108 warnings.append(w)
110 w = _safe_check(check_legacy_server_config, dismiss_legacy_config)
111 if w:
112 warnings.append(w)
114 # --- Backup checks ---
115 w = _safe_check(
116 check_backup_disabled, backup_enabled, dismiss_backup_disabled
117 )
118 if w: 118 ↛ 119line 118 didn't jump to line 119 because the condition on line 118 was never true
119 warnings.append(w)
121 # Check backup file status (lightweight filesystem glob)
122 dismiss_backup_info = settings_manager.get_setting(
123 "app.warnings.dismiss_backup_info", False
124 )
125 try:
126 from ...config.paths import get_user_backup_directory
127 from ...utilities.formatting import human_size
129 username = session.get("username")
130 if username: 130 ↛ 163line 130 didn't jump to line 163 because the condition on line 130 was always true
131 backup_dir = get_user_backup_directory(username)
132 total_size = 0
133 backup_count = 0
134 for f in backup_dir.glob("ldr_backup_*.db"): 134 ↛ 135line 134 didn't jump to line 135 because the loop on line 134 never started
135 try:
136 total_size += f.stat().st_size
137 backup_count += 1
138 except FileNotFoundError:
139 continue
141 w = _safe_check(
142 check_no_backups_exist,
143 backup_enabled,
144 backup_count,
145 dismiss_no_backups,
146 )
147 if w:
148 warnings.append(w)
150 w = _safe_check(
151 check_backup_healthy,
152 backup_enabled,
153 backup_count,
154 human_size(total_size),
155 dismiss_backup_info,
156 )
157 if w: 157 ↛ 158line 157 didn't jump to line 158 because the condition on line 157 was never true
158 warnings.append(w)
159 except Exception:
160 logger.debug("Backup status check skipped")
162 # --- History-based checks (need DB queries) ---
163 if is_local and not dismiss_context_warning:
164 w = _safe_check(
165 check_context_below_history, db_session, local_context
166 )
167 if w:
168 warnings.append(w)
170 w = _safe_check(
171 check_context_truncation_history, db_session, local_context
172 )
173 if w:
174 warnings.append(w)
176 except Exception:
177 logger.exception("Error calculating warnings")
179 return warnings