local-deep-research 0.6.0__py3-none-any.whl → 0.6.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- local_deep_research/__init__.py +6 -0
- local_deep_research/__version__.py +1 -1
- local_deep_research/setup_data_dir.py +3 -2
- local_deep_research/utilities/db_utils.py +11 -9
- local_deep_research/utilities/log_utils.py +1 -1
- local_deep_research/utilities/threading_utils.py +17 -4
- local_deep_research/web/api.py +5 -3
- local_deep_research/web/app.py +0 -74
- local_deep_research/web/app_factory.py +1 -11
- local_deep_research/web/database/migrations.py +699 -28
- local_deep_research/web/database/uuid_migration.py +2 -247
- local_deep_research/web/models/database.py +0 -79
- local_deep_research/web/routes/settings_routes.py +70 -73
- local_deep_research/web/services/settings_manager.py +13 -28
- local_deep_research/web/services/settings_service.py +6 -40
- local_deep_research/web/services/socket_service.py +1 -1
- local_deep_research/web/templates/pages/benchmark_results.html +146 -8
- local_deep_research/web_search_engines/rate_limiting/tracker.py +1 -3
- {local_deep_research-0.6.0.dist-info → local_deep_research-0.6.4.dist-info}/METADATA +20 -5
- {local_deep_research-0.6.0.dist-info → local_deep_research-0.6.4.dist-info}/RECORD +23 -26
- local_deep_research/migrate_db.py +0 -149
- local_deep_research/web/database/migrate_to_ldr_db.py +0 -297
- local_deep_research/web/database/schema_upgrade.py +0 -519
- {local_deep_research-0.6.0.dist-info → local_deep_research-0.6.4.dist-info}/WHEEL +0 -0
- {local_deep_research-0.6.0.dist-info → local_deep_research-0.6.4.dist-info}/entry_points.txt +0 -0
- {local_deep_research-0.6.0.dist-info → local_deep_research-0.6.4.dist-info}/licenses/LICENSE +0 -0
@@ -5,10 +5,9 @@ Migrates all research_id fields from Integer to String (UUID) format.
|
|
5
5
|
This creates a more consistent and scalable ID system across the application.
|
6
6
|
"""
|
7
7
|
|
8
|
-
import sqlite3
|
9
|
-
import uuid
|
10
8
|
from pathlib import Path
|
11
|
-
|
9
|
+
|
10
|
+
from local_deep_research.web.database.migrations import migrate_to_uuid
|
12
11
|
|
13
12
|
|
14
13
|
def get_database_path():
|
@@ -17,249 +16,5 @@ def get_database_path():
|
|
17
16
|
return data_dir / "ldr.db"
|
18
17
|
|
19
18
|
|
20
|
-
def migrate_to_uuid():
|
21
|
-
"""
|
22
|
-
Migrate all research_id fields from integers to UUIDs.
|
23
|
-
|
24
|
-
Strategy:
|
25
|
-
1. Add new UUID columns alongside existing integer columns
|
26
|
-
2. Generate UUIDs for existing data (or keep as string versions of integers)
|
27
|
-
3. Update foreign key relationships
|
28
|
-
4. Drop old integer columns and rename UUID columns
|
29
|
-
"""
|
30
|
-
db_path = get_database_path()
|
31
|
-
|
32
|
-
if not db_path.exists():
|
33
|
-
logger.info("Database doesn't exist yet, migration not needed")
|
34
|
-
return
|
35
|
-
|
36
|
-
logger.info(f"Starting UUID migration on {db_path}")
|
37
|
-
|
38
|
-
conn = sqlite3.connect(db_path)
|
39
|
-
conn.execute(
|
40
|
-
"PRAGMA foreign_keys = OFF"
|
41
|
-
) # Disable FK constraints during migration
|
42
|
-
|
43
|
-
try:
|
44
|
-
cursor = conn.cursor()
|
45
|
-
|
46
|
-
# 1. Migrate research_history table (main research IDs)
|
47
|
-
logger.info("Migrating research_history table...")
|
48
|
-
|
49
|
-
# Check if the table exists and has the old structure
|
50
|
-
cursor.execute("PRAGMA table_info(research_history)")
|
51
|
-
columns = cursor.fetchall()
|
52
|
-
has_uuid_id = any(col[1] == "uuid_id" for col in columns)
|
53
|
-
|
54
|
-
if not has_uuid_id:
|
55
|
-
# Add UUID column
|
56
|
-
cursor.execute(
|
57
|
-
"ALTER TABLE research_history ADD COLUMN uuid_id TEXT"
|
58
|
-
)
|
59
|
-
|
60
|
-
# Generate UUIDs for existing records (convert integer ID to UUID format)
|
61
|
-
cursor.execute("SELECT id FROM research_history")
|
62
|
-
existing_ids = cursor.fetchall()
|
63
|
-
|
64
|
-
for (old_id,) in existing_ids:
|
65
|
-
# Generate a deterministic UUID based on the old ID
|
66
|
-
new_uuid = str(
|
67
|
-
uuid.uuid5(uuid.NAMESPACE_OID, f"research_{old_id}")
|
68
|
-
)
|
69
|
-
cursor.execute(
|
70
|
-
"UPDATE research_history SET uuid_id = ? WHERE id = ?",
|
71
|
-
(new_uuid, old_id),
|
72
|
-
)
|
73
|
-
|
74
|
-
logger.info(
|
75
|
-
f"Generated UUIDs for {len(existing_ids)} research records"
|
76
|
-
)
|
77
|
-
|
78
|
-
# 2. Migrate metrics tables
|
79
|
-
logger.info("Migrating metrics tables...")
|
80
|
-
|
81
|
-
# Token usage table
|
82
|
-
cursor.execute("PRAGMA table_info(token_usage)")
|
83
|
-
columns = cursor.fetchall()
|
84
|
-
has_uuid_research_id = any(
|
85
|
-
col[1] == "uuid_research_id" for col in columns
|
86
|
-
)
|
87
|
-
|
88
|
-
if not has_uuid_research_id:
|
89
|
-
cursor.execute(
|
90
|
-
"ALTER TABLE token_usage ADD COLUMN uuid_research_id TEXT"
|
91
|
-
)
|
92
|
-
|
93
|
-
# Convert existing research_ids to UUIDs (deterministic conversion)
|
94
|
-
cursor.execute(
|
95
|
-
"SELECT DISTINCT research_id FROM token_usage WHERE research_id IS NOT NULL"
|
96
|
-
)
|
97
|
-
research_ids = cursor.fetchall()
|
98
|
-
|
99
|
-
for (research_id,) in research_ids:
|
100
|
-
if research_id:
|
101
|
-
new_uuid = str(
|
102
|
-
uuid.uuid5(
|
103
|
-
uuid.NAMESPACE_OID, f"research_{research_id}"
|
104
|
-
)
|
105
|
-
)
|
106
|
-
cursor.execute(
|
107
|
-
"UPDATE token_usage SET uuid_research_id = ? WHERE research_id = ?",
|
108
|
-
(new_uuid, research_id),
|
109
|
-
)
|
110
|
-
|
111
|
-
logger.info(
|
112
|
-
f"Migrated {len(research_ids)} research IDs in token_usage"
|
113
|
-
)
|
114
|
-
|
115
|
-
# Model usage table
|
116
|
-
cursor.execute("PRAGMA table_info(model_usage)")
|
117
|
-
columns = cursor.fetchall()
|
118
|
-
has_uuid_research_id = any(
|
119
|
-
col[1] == "uuid_research_id" for col in columns
|
120
|
-
)
|
121
|
-
|
122
|
-
if not has_uuid_research_id:
|
123
|
-
cursor.execute(
|
124
|
-
"ALTER TABLE model_usage ADD COLUMN uuid_research_id TEXT"
|
125
|
-
)
|
126
|
-
|
127
|
-
cursor.execute(
|
128
|
-
"SELECT DISTINCT research_id FROM model_usage WHERE research_id IS NOT NULL"
|
129
|
-
)
|
130
|
-
research_ids = cursor.fetchall()
|
131
|
-
|
132
|
-
for (research_id,) in research_ids:
|
133
|
-
if research_id:
|
134
|
-
new_uuid = str(
|
135
|
-
uuid.uuid5(
|
136
|
-
uuid.NAMESPACE_OID, f"research_{research_id}"
|
137
|
-
)
|
138
|
-
)
|
139
|
-
cursor.execute(
|
140
|
-
"UPDATE model_usage SET uuid_research_id = ? WHERE research_id = ?",
|
141
|
-
(new_uuid, research_id),
|
142
|
-
)
|
143
|
-
|
144
|
-
logger.info(
|
145
|
-
f"Migrated {len(research_ids)} research IDs in model_usage"
|
146
|
-
)
|
147
|
-
|
148
|
-
# Search calls table
|
149
|
-
cursor.execute("PRAGMA table_info(search_calls)")
|
150
|
-
columns = cursor.fetchall()
|
151
|
-
has_uuid_research_id = any(
|
152
|
-
col[1] == "uuid_research_id" for col in columns
|
153
|
-
)
|
154
|
-
|
155
|
-
if not has_uuid_research_id:
|
156
|
-
cursor.execute(
|
157
|
-
"ALTER TABLE search_calls ADD COLUMN uuid_research_id TEXT"
|
158
|
-
)
|
159
|
-
|
160
|
-
cursor.execute(
|
161
|
-
"SELECT DISTINCT research_id FROM search_calls WHERE research_id IS NOT NULL"
|
162
|
-
)
|
163
|
-
research_ids = cursor.fetchall()
|
164
|
-
|
165
|
-
for (research_id,) in research_ids:
|
166
|
-
if research_id:
|
167
|
-
new_uuid = str(
|
168
|
-
uuid.uuid5(
|
169
|
-
uuid.NAMESPACE_OID, f"research_{research_id}"
|
170
|
-
)
|
171
|
-
)
|
172
|
-
cursor.execute(
|
173
|
-
"UPDATE search_calls SET uuid_research_id = ? WHERE research_id = ?",
|
174
|
-
(new_uuid, research_id),
|
175
|
-
)
|
176
|
-
|
177
|
-
logger.info(
|
178
|
-
f"Migrated {len(research_ids)} research IDs in search_calls"
|
179
|
-
)
|
180
|
-
|
181
|
-
# 3. Migrate benchmark tables
|
182
|
-
logger.info("Migrating benchmark tables...")
|
183
|
-
|
184
|
-
# Check if benchmark_results table exists
|
185
|
-
cursor.execute(
|
186
|
-
"SELECT name FROM sqlite_master WHERE type='table' AND name='benchmark_results'"
|
187
|
-
)
|
188
|
-
if cursor.fetchone():
|
189
|
-
cursor.execute("PRAGMA table_info(benchmark_results)")
|
190
|
-
columns = cursor.fetchall()
|
191
|
-
has_uuid_research_id = any(
|
192
|
-
col[1] == "uuid_research_id" for col in columns
|
193
|
-
)
|
194
|
-
|
195
|
-
if not has_uuid_research_id:
|
196
|
-
cursor.execute(
|
197
|
-
"ALTER TABLE benchmark_results ADD COLUMN uuid_research_id TEXT"
|
198
|
-
)
|
199
|
-
|
200
|
-
cursor.execute(
|
201
|
-
"SELECT DISTINCT research_id FROM benchmark_results WHERE research_id IS NOT NULL"
|
202
|
-
)
|
203
|
-
research_ids = cursor.fetchall()
|
204
|
-
|
205
|
-
for (research_id,) in research_ids:
|
206
|
-
if research_id:
|
207
|
-
new_uuid = str(
|
208
|
-
uuid.uuid5(
|
209
|
-
uuid.NAMESPACE_OID, f"research_{research_id}"
|
210
|
-
)
|
211
|
-
)
|
212
|
-
cursor.execute(
|
213
|
-
"UPDATE benchmark_results SET uuid_research_id = ? WHERE research_id = ?",
|
214
|
-
(new_uuid, research_id),
|
215
|
-
)
|
216
|
-
|
217
|
-
logger.info(
|
218
|
-
f"Migrated {len(research_ids)} research IDs in benchmark_results"
|
219
|
-
)
|
220
|
-
|
221
|
-
# Commit all changes
|
222
|
-
conn.commit()
|
223
|
-
logger.info("UUID migration completed successfully!")
|
224
|
-
|
225
|
-
# Note: We're keeping both old and new columns for now
|
226
|
-
# The application will use the new UUID columns
|
227
|
-
# Old columns can be dropped in a future migration once everything is stable
|
228
|
-
|
229
|
-
except Exception as e:
|
230
|
-
logger.error(f"Error during UUID migration: {e}")
|
231
|
-
conn.rollback()
|
232
|
-
raise
|
233
|
-
finally:
|
234
|
-
conn.execute("PRAGMA foreign_keys = ON") # Re-enable FK constraints
|
235
|
-
conn.close()
|
236
|
-
|
237
|
-
|
238
|
-
def cleanup_old_columns():
|
239
|
-
"""
|
240
|
-
Cleanup migration - drops old integer columns after UUID migration is stable.
|
241
|
-
Run this only after confirming the UUID migration is working correctly.
|
242
|
-
"""
|
243
|
-
logger.warning(
|
244
|
-
"This will permanently remove old integer research_id columns!"
|
245
|
-
)
|
246
|
-
logger.warning("Make sure to backup your database before running this!")
|
247
|
-
|
248
|
-
db_path = get_database_path()
|
249
|
-
conn = sqlite3.connect(db_path)
|
250
|
-
conn.execute("PRAGMA foreign_keys = OFF")
|
251
|
-
|
252
|
-
try:
|
253
|
-
# For SQLite, we need to recreate tables to drop columns
|
254
|
-
# This is complex, so we'll leave old columns for now
|
255
|
-
# They can be cleaned up manually if needed
|
256
|
-
|
257
|
-
logger.info("Cleanup deferred - old columns remain for safety")
|
258
|
-
|
259
|
-
finally:
|
260
|
-
conn.execute("PRAGMA foreign_keys = ON")
|
261
|
-
conn.close()
|
262
|
-
|
263
|
-
|
264
19
|
if __name__ == "__main__":
|
265
20
|
migrate_to_uuid()
|
@@ -38,85 +38,6 @@ def get_db_connection():
|
|
38
38
|
return conn
|
39
39
|
|
40
40
|
|
41
|
-
def init_db():
|
42
|
-
"""Initialize the database with necessary tables."""
|
43
|
-
conn = get_db_connection()
|
44
|
-
cursor = conn.cursor()
|
45
|
-
|
46
|
-
# Create a dedicated table for research logs
|
47
|
-
cursor.execute(
|
48
|
-
"""
|
49
|
-
CREATE TABLE IF NOT EXISTS research_logs (
|
50
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
51
|
-
research_id INTEGER NOT NULL,
|
52
|
-
timestamp TEXT NOT NULL,
|
53
|
-
message TEXT NOT NULL,
|
54
|
-
log_type TEXT NOT NULL,
|
55
|
-
progress INTEGER,
|
56
|
-
metadata TEXT,
|
57
|
-
FOREIGN KEY (research_id) REFERENCES research_history (id) ON DELETE CASCADE
|
58
|
-
)
|
59
|
-
"""
|
60
|
-
)
|
61
|
-
|
62
|
-
# Create a dedicated table for research resources
|
63
|
-
cursor.execute(
|
64
|
-
"""
|
65
|
-
CREATE TABLE IF NOT EXISTS research_resources (
|
66
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
67
|
-
research_id INTEGER NOT NULL,
|
68
|
-
title TEXT,
|
69
|
-
url TEXT,
|
70
|
-
content_preview TEXT,
|
71
|
-
source_type TEXT,
|
72
|
-
metadata TEXT,
|
73
|
-
created_at TEXT NOT NULL,
|
74
|
-
FOREIGN KEY (research_id) REFERENCES research_history (id) ON DELETE CASCADE
|
75
|
-
)
|
76
|
-
"""
|
77
|
-
)
|
78
|
-
|
79
|
-
# Check if the duration_seconds column exists, add it if missing
|
80
|
-
cursor.execute("PRAGMA table_info(research_history)")
|
81
|
-
columns = [column[1] for column in cursor.fetchall()]
|
82
|
-
|
83
|
-
if "duration_seconds" not in columns:
|
84
|
-
logger.info(
|
85
|
-
"Adding missing 'duration_seconds' column to research_history table"
|
86
|
-
)
|
87
|
-
cursor.execute(
|
88
|
-
"ALTER TABLE research_history ADD COLUMN duration_seconds INTEGER"
|
89
|
-
)
|
90
|
-
|
91
|
-
# Check if the progress column exists, add it if missing
|
92
|
-
if "progress" not in columns:
|
93
|
-
logger.info(
|
94
|
-
"Adding missing 'progress' column to research_history table"
|
95
|
-
)
|
96
|
-
cursor.execute(
|
97
|
-
"ALTER TABLE research_history ADD COLUMN progress INTEGER"
|
98
|
-
)
|
99
|
-
|
100
|
-
# Check if the title column exists, add it if missing
|
101
|
-
if "title" not in columns:
|
102
|
-
logger.info("Adding missing 'title' column to research_history table")
|
103
|
-
cursor.execute("ALTER TABLE research_history ADD COLUMN title TEXT")
|
104
|
-
|
105
|
-
# Check if the metadata column exists, and rename it to "research_meta"
|
106
|
-
# if it does.
|
107
|
-
if "metadata" in columns:
|
108
|
-
logger.info("Renaming 'metadata' column to 'research_meta'")
|
109
|
-
cursor.execute(
|
110
|
-
"ALTER TABLE research_history RENAME COLUMN metadata TO research_meta"
|
111
|
-
)
|
112
|
-
|
113
|
-
# Enable foreign key support
|
114
|
-
cursor.execute("PRAGMA foreign_keys = ON")
|
115
|
-
|
116
|
-
conn.commit()
|
117
|
-
conn.close()
|
118
|
-
|
119
|
-
|
120
41
|
def calculate_duration(created_at_str, completed_at_str=None):
|
121
42
|
"""
|
122
43
|
Calculate duration in seconds between created_at timestamp and completed_at or now.
|
@@ -16,16 +16,17 @@ from flask import (
|
|
16
16
|
from flask_wtf.csrf import generate_csrf
|
17
17
|
from loguru import logger
|
18
18
|
|
19
|
-
from ...utilities.db_utils import
|
19
|
+
from ...utilities.db_utils import (
|
20
|
+
get_db_setting,
|
21
|
+
get_db_session,
|
22
|
+
get_settings_manager,
|
23
|
+
)
|
20
24
|
from ...utilities.url_utils import normalize_url
|
21
25
|
from ..database.models import Setting, SettingType
|
22
26
|
from ..services.settings_service import (
|
23
27
|
create_or_update_setting,
|
24
|
-
get_setting,
|
25
|
-
get_settings_manager,
|
26
28
|
set_setting,
|
27
29
|
)
|
28
|
-
from ..services.settings_manager import SettingsManager
|
29
30
|
from ..utils.templates import render_template_with_defaults
|
30
31
|
|
31
32
|
# Create a Blueprint for settings
|
@@ -37,20 +38,15 @@ def calculate_warnings():
|
|
37
38
|
warnings = []
|
38
39
|
|
39
40
|
try:
|
40
|
-
# Get a fresh database session for safety
|
41
|
-
db_session = get_db_session()
|
42
|
-
|
43
41
|
# Get current settings
|
44
|
-
provider =
|
45
|
-
local_context =
|
46
|
-
"llm.local_context_window_size", 4096, db_session
|
47
|
-
)
|
42
|
+
provider = get_db_setting("llm.provider", "ollama").lower()
|
43
|
+
local_context = get_db_setting("llm.local_context_window_size", 4096)
|
48
44
|
|
49
45
|
logger.debug(f"Starting warning calculation - provider={provider}")
|
50
46
|
|
51
47
|
# Get dismissal settings
|
52
|
-
dismiss_high_context =
|
53
|
-
"app.warnings.dismiss_high_context", False
|
48
|
+
dismiss_high_context = get_db_setting(
|
49
|
+
"app.warnings.dismiss_high_context", False
|
54
50
|
)
|
55
51
|
|
56
52
|
# Check warning conditions
|
@@ -78,15 +74,15 @@ def calculate_warnings():
|
|
78
74
|
)
|
79
75
|
|
80
76
|
# Get additional warning settings
|
81
|
-
dismiss_model_mismatch =
|
82
|
-
"app.warnings.dismiss_model_mismatch", False
|
77
|
+
dismiss_model_mismatch = get_db_setting(
|
78
|
+
"app.warnings.dismiss_model_mismatch", False
|
83
79
|
)
|
84
80
|
|
85
81
|
# Get current strategy and model (these need to be passed from the frontend or retrieved differently)
|
86
82
|
# For now, we'll implement basic warnings that don't require form state
|
87
83
|
|
88
84
|
# Model mismatch warning (simplified - checking setting instead of form value)
|
89
|
-
current_model =
|
85
|
+
current_model = get_db_setting("llm.model", "")
|
90
86
|
if (
|
91
87
|
current_model
|
92
88
|
and "70b" in current_model.lower()
|
@@ -165,7 +161,7 @@ def save_all_settings():
|
|
165
161
|
"""Handle saving all settings at once from the unified settings page"""
|
166
162
|
db_session = get_db_session()
|
167
163
|
# Get the settings manager but we don't need to assign it to a variable right now
|
168
|
-
#
|
164
|
+
# get_db_settings_manager(db_session)
|
169
165
|
|
170
166
|
try:
|
171
167
|
# Process JSON data
|
@@ -462,7 +458,7 @@ def reset_to_defaults():
|
|
462
458
|
# Import default settings from files
|
463
459
|
try:
|
464
460
|
# Create settings manager for the temporary config
|
465
|
-
settings_mgr = get_settings_manager(
|
461
|
+
settings_mgr = get_settings_manager()
|
466
462
|
# Import settings from default files
|
467
463
|
settings_mgr.load_from_defaults_file()
|
468
464
|
|
@@ -499,7 +495,7 @@ def api_get_all_settings():
|
|
499
495
|
|
500
496
|
# Create settings manager
|
501
497
|
db_session = get_db_session()
|
502
|
-
settings_manager = get_settings_manager(
|
498
|
+
settings_manager = get_settings_manager()
|
503
499
|
|
504
500
|
# Get settings
|
505
501
|
settings = settings_manager.get_all_settings()
|
@@ -527,15 +523,15 @@ def api_get_all_settings():
|
|
527
523
|
|
528
524
|
|
529
525
|
@settings_bp.route("/api/<path:key>", methods=["GET"])
|
530
|
-
def
|
526
|
+
def api_get_db_setting(key):
|
531
527
|
"""Get a specific setting by key"""
|
532
528
|
try:
|
533
529
|
db_session = get_db_session()
|
534
530
|
# No need to assign if not used
|
535
|
-
#
|
531
|
+
# get_db_settings_manager(db_session)
|
536
532
|
|
537
533
|
# Get setting
|
538
|
-
value =
|
534
|
+
value = get_db_setting(key)
|
539
535
|
if value is None:
|
540
536
|
return jsonify({"error": f"Setting not found: {key}"}), 404
|
541
537
|
|
@@ -587,7 +583,7 @@ def api_update_setting(key):
|
|
587
583
|
# Get DB session and settings manager
|
588
584
|
db_session = get_db_session()
|
589
585
|
# Only use settings_manager if needed - we don't need to assign if not used
|
590
|
-
#
|
586
|
+
# get_db_settings_manager(db_session)
|
591
587
|
|
592
588
|
# Check if setting exists
|
593
589
|
db_setting = (
|
@@ -687,7 +683,7 @@ def api_delete_setting(key):
|
|
687
683
|
"""Delete a setting"""
|
688
684
|
try:
|
689
685
|
db_session = get_db_session()
|
690
|
-
settings_manager = get_settings_manager(
|
686
|
+
settings_manager = get_settings_manager()
|
691
687
|
|
692
688
|
# Check if setting exists
|
693
689
|
db_setting = (
|
@@ -711,7 +707,7 @@ def api_delete_setting(key):
|
|
711
707
|
def api_import_settings():
|
712
708
|
"""Import settings from defaults file"""
|
713
709
|
try:
|
714
|
-
settings_manager = get_settings_manager(
|
710
|
+
settings_manager = get_settings_manager()
|
715
711
|
|
716
712
|
success = settings_manager.load_from_defaults_file()
|
717
713
|
|
@@ -782,7 +778,7 @@ def api_get_available_models():
|
|
782
778
|
try:
|
783
779
|
from datetime import datetime, timedelta
|
784
780
|
from ..database.models import ProviderModel
|
785
|
-
from flask import request
|
781
|
+
from flask import request
|
786
782
|
|
787
783
|
# Check if force_refresh is requested
|
788
784
|
force_refresh = (
|
@@ -806,17 +802,16 @@ def api_get_available_models():
|
|
806
802
|
# Check database cache first (unless force_refresh is True)
|
807
803
|
if not force_refresh:
|
808
804
|
try:
|
809
|
-
db_session = current_app.db_session
|
810
|
-
|
811
805
|
# Define cache expiration (24 hours)
|
812
806
|
cache_expiry = datetime.utcnow() - timedelta(hours=24)
|
813
807
|
|
814
808
|
# Get cached models from database
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
809
|
+
with get_db_session("settings_routes") as db_session:
|
810
|
+
cached_models = (
|
811
|
+
db_session.query(ProviderModel)
|
812
|
+
.filter(ProviderModel.last_updated > cache_expiry)
|
813
|
+
.all()
|
814
|
+
)
|
820
815
|
|
821
816
|
if cached_models:
|
822
817
|
logger.info(
|
@@ -1269,41 +1264,44 @@ def api_get_available_models():
|
|
1269
1264
|
# Save fetched models to database cache
|
1270
1265
|
if force_refresh or providers:
|
1271
1266
|
# We fetched fresh data, save it to database
|
1272
|
-
|
1273
|
-
|
1274
|
-
|
1275
|
-
|
1276
|
-
|
1277
|
-
|
1278
|
-
|
1279
|
-
|
1280
|
-
|
1281
|
-
ProviderModel.
|
1282
|
-
|
1283
|
-
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1288
|
-
|
1289
|
-
|
1290
|
-
|
1291
|
-
|
1292
|
-
|
1293
|
-
|
1294
|
-
|
1295
|
-
|
1296
|
-
|
1297
|
-
|
1298
|
-
|
1299
|
-
|
1300
|
-
|
1301
|
-
|
1302
|
-
|
1303
|
-
|
1304
|
-
|
1305
|
-
|
1306
|
-
|
1267
|
+
with get_db_session("settings_routes") as db_session:
|
1268
|
+
try:
|
1269
|
+
from datetime import datetime
|
1270
|
+
|
1271
|
+
# Clear old cache entries for providers we're updating
|
1272
|
+
for provider_key in providers.keys():
|
1273
|
+
provider_name = provider_key.replace(
|
1274
|
+
"_models", ""
|
1275
|
+
).upper()
|
1276
|
+
db_session.query(ProviderModel).filter(
|
1277
|
+
ProviderModel.provider == provider_name
|
1278
|
+
).delete()
|
1279
|
+
|
1280
|
+
# Insert new models
|
1281
|
+
for provider_key, models in providers.items():
|
1282
|
+
provider_name = provider_key.replace(
|
1283
|
+
"_models", ""
|
1284
|
+
).upper()
|
1285
|
+
for model in models:
|
1286
|
+
if (
|
1287
|
+
isinstance(model, dict)
|
1288
|
+
and "value" in model
|
1289
|
+
and "label" in model
|
1290
|
+
):
|
1291
|
+
new_model = ProviderModel(
|
1292
|
+
provider=provider_name,
|
1293
|
+
model_key=model["value"],
|
1294
|
+
model_label=model["label"],
|
1295
|
+
last_updated=datetime.utcnow(),
|
1296
|
+
)
|
1297
|
+
db_session.add(new_model)
|
1298
|
+
|
1299
|
+
db_session.commit()
|
1300
|
+
logger.info("Successfully cached models to database")
|
1301
|
+
|
1302
|
+
except Exception:
|
1303
|
+
logger.exception("Error saving models to database cache")
|
1304
|
+
db_session.rollback()
|
1307
1305
|
|
1308
1306
|
# Return all options
|
1309
1307
|
return jsonify(
|
@@ -1858,9 +1856,9 @@ def api_get_rate_limiting_status():
|
|
1858
1856
|
"max_wait_seconds": round(max_wait, 2),
|
1859
1857
|
"last_updated": last_updated,
|
1860
1858
|
"total_attempts": total_attempts,
|
1861
|
-
"success_rate":
|
1862
|
-
|
1863
|
-
|
1859
|
+
"success_rate": (
|
1860
|
+
round(success_rate * 100, 1) if success_rate else 0.0
|
1861
|
+
),
|
1864
1862
|
}
|
1865
1863
|
)
|
1866
1864
|
|
@@ -1934,12 +1932,11 @@ def get_bulk_settings():
|
|
1934
1932
|
|
1935
1933
|
# Fetch all settings at once
|
1936
1934
|
session = get_db_session()
|
1937
|
-
settings_manager = SettingsManager(db_session=session)
|
1938
1935
|
|
1939
1936
|
result = {}
|
1940
1937
|
for key in requested:
|
1941
1938
|
try:
|
1942
|
-
value =
|
1939
|
+
value = get_db_setting(key)
|
1943
1940
|
result[key] = {"value": value, "exists": value is not None}
|
1944
1941
|
except Exception as e:
|
1945
1942
|
logger.warning(f"Error getting setting {key}: {e}")
|