local-deep-research 0.6.1__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.
Files changed (25) hide show
  1. local_deep_research/__init__.py +6 -0
  2. local_deep_research/__version__.py +1 -1
  3. local_deep_research/setup_data_dir.py +3 -2
  4. local_deep_research/utilities/db_utils.py +11 -9
  5. local_deep_research/utilities/log_utils.py +1 -1
  6. local_deep_research/utilities/threading_utils.py +17 -4
  7. local_deep_research/web/api.py +5 -3
  8. local_deep_research/web/app.py +0 -74
  9. local_deep_research/web/app_factory.py +1 -11
  10. local_deep_research/web/database/migrations.py +699 -28
  11. local_deep_research/web/database/uuid_migration.py +2 -247
  12. local_deep_research/web/models/database.py +0 -79
  13. local_deep_research/web/routes/settings_routes.py +70 -73
  14. local_deep_research/web/services/settings_manager.py +13 -28
  15. local_deep_research/web/services/settings_service.py +6 -40
  16. local_deep_research/web/services/socket_service.py +1 -1
  17. local_deep_research/web_search_engines/rate_limiting/tracker.py +1 -3
  18. {local_deep_research-0.6.1.dist-info → local_deep_research-0.6.4.dist-info}/METADATA +19 -4
  19. {local_deep_research-0.6.1.dist-info → local_deep_research-0.6.4.dist-info}/RECORD +22 -25
  20. local_deep_research/migrate_db.py +0 -149
  21. local_deep_research/web/database/migrate_to_ldr_db.py +0 -297
  22. local_deep_research/web/database/schema_upgrade.py +0 -519
  23. {local_deep_research-0.6.1.dist-info → local_deep_research-0.6.4.dist-info}/WHEEL +0 -0
  24. {local_deep_research-0.6.1.dist-info → local_deep_research-0.6.4.dist-info}/entry_points.txt +0 -0
  25. {local_deep_research-0.6.1.dist-info → local_deep_research-0.6.4.dist-info}/licenses/LICENSE +0 -0
@@ -66,11 +66,17 @@ class SettingsManager:
66
66
  self.db_session = db_session
67
67
  self.db_first = True # Always prioritize DB settings
68
68
 
69
- # Load default settings.
69
+ @property
70
+ def default_settings(self) -> Dict[str, Any]:
71
+ """
72
+ Returns:
73
+ The default settings, loaded from JSON.
74
+
75
+ """
70
76
  default_settings = pkg_resources.read_text(
71
77
  defaults, "default_settings.json"
72
78
  )
73
- self.default_settings = json.loads(default_settings)
79
+ return json.loads(default_settings)
74
80
 
75
81
  def __get_typed_setting_value(
76
82
  self,
@@ -462,27 +468,6 @@ class SettingsManager:
462
468
  self.db_session.add(version)
463
469
  self.db_session.commit()
464
470
 
465
- @classmethod
466
- def get_instance(
467
- cls, db_session: Optional[Session] = None
468
- ) -> "SettingsManager":
469
- """
470
- Get a singleton instance of the settings manager
471
-
472
- Args:
473
- db_session: Optional database session
474
-
475
- Returns:
476
- SettingsManager instance
477
- """
478
- if not hasattr(cls, "_instance"):
479
- cls._instance = cls(db_session)
480
- elif db_session and not cls._instance.db_session:
481
- # Update existing instance with a session
482
- cls._instance.db_session = db_session
483
-
484
- return cls._instance
485
-
486
471
  def import_settings(
487
472
  self,
488
473
  settings_data: Dict[str, Any],
@@ -517,6 +502,11 @@ class SettingsManager:
517
502
  setting = Setting(key=key, **setting_values)
518
503
  self.db_session.add(setting)
519
504
 
505
+ if commit or delete_extra:
506
+ self.db_session.commit()
507
+ # Emit WebSocket event for all imported settings
508
+ self._emit_settings_changed(list(settings_data.keys()))
509
+
520
510
  if delete_extra:
521
511
  all_settings = self.get_all_settings()
522
512
  for key in all_settings:
@@ -524,11 +514,6 @@ class SettingsManager:
524
514
  logger.debug(f"Deleting extraneous setting: {key}")
525
515
  self.delete_setting(key, commit=False)
526
516
 
527
- if commit:
528
- self.db_session.commit()
529
- # Emit WebSocket event for all imported settings
530
- self._emit_settings_changed(list(settings_data.keys()))
531
-
532
517
  def _create_setting(self, key, value, setting_type):
533
518
  """Create a setting with appropriate metadata"""
534
519
 
@@ -3,41 +3,10 @@ from typing import Any, Dict, Optional, Union
3
3
  from loguru import logger
4
4
 
5
5
  from ..database.models import Setting
6
- from .settings_manager import SettingsManager
6
+ from ...utilities.db_utils import get_settings_manager
7
7
 
8
8
 
9
- def get_settings_manager(db_session=None):
10
- """
11
- Get or create the settings manager instance.
12
-
13
- Args:
14
- db_session: Optional database session to use
15
-
16
- Returns:
17
- SettingsManager: The settings manager instance
18
- """
19
- return SettingsManager.get_instance(db_session)
20
-
21
-
22
- def get_setting(key: str, default: Any = None, db_session=None) -> Any:
23
- """
24
- Get a setting value by key
25
-
26
- Args:
27
- key: Setting key
28
- default: Default value if setting not found
29
- db_session: Optional database session to use
30
-
31
- Returns:
32
- Any: The setting value
33
- """
34
- manager = get_settings_manager(db_session)
35
- return manager.get_setting(key, default)
36
-
37
-
38
- def set_setting(
39
- key: str, value: Any, commit: bool = True, db_session=None
40
- ) -> bool:
9
+ def set_setting(key: str, value: Any, commit: bool = True) -> bool:
41
10
  """
42
11
  Set a setting value
43
12
 
@@ -45,26 +14,23 @@ def set_setting(
45
14
  key: Setting key
46
15
  value: Setting value
47
16
  commit: Whether to commit the change
48
- db_session: Optional database session
49
17
 
50
18
  Returns:
51
19
  bool: True if successful
52
20
  """
53
- manager = get_settings_manager(db_session)
21
+ manager = get_settings_manager()
54
22
  return manager.set_setting(key, value, commit)
55
23
 
56
24
 
57
- def get_all_settings(db_session=None) -> Dict[str, Any]:
25
+ def get_all_settings() -> Dict[str, Any]:
58
26
  """
59
27
  Get all settings, optionally filtered by type
60
28
 
61
- Args:
62
- db_session: Optional database session
63
-
64
29
  Returns:
65
30
  Dict[str, Any]: Dictionary of settings
31
+
66
32
  """
67
- manager = get_settings_manager(db_session)
33
+ manager = get_settings_manager()
68
34
  return manager.get_all_settings()
69
35
 
70
36
 
@@ -49,7 +49,7 @@ class SocketIOService:
49
49
  app,
50
50
  cors_allowed_origins="*",
51
51
  async_mode="threading",
52
- path="/research/socket.io",
52
+ path="/socket.io",
53
53
  logger=False,
54
54
  engineio_logger=False,
55
55
  ping_timeout=20,
@@ -9,7 +9,7 @@ from collections import deque
9
9
  from typing import Dict, Optional, Tuple, List
10
10
 
11
11
 
12
- from ...utilities.db_utils import get_db_session
12
+ from ...utilities.db_utils import get_db_session, get_db_setting
13
13
  from ...web.database.models import RateLimitAttempt, RateLimitEstimate
14
14
 
15
15
  logger = logging.getLogger(__name__)
@@ -23,8 +23,6 @@ class AdaptiveRateLimitTracker:
23
23
 
24
24
  def __init__(self):
25
25
  # Load configuration from database settings
26
- from ...utilities.db_utils import get_db_setting
27
-
28
26
  self.memory_window = int(
29
27
  get_db_setting("rate_limiting.memory_window", 100)
30
28
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: local-deep-research
3
- Version: 0.6.1
3
+ Version: 0.6.4
4
4
  Summary: AI-powered research assistant with deep, iterative analysis using LLMs and web searches
5
5
  Author-Email: LearningCircuit <185559241+LearningCircuit@users.noreply.github.com>, HashedViking <6432677+HashedViking@users.noreply.github.com>, djpetti <djpetti@gmail.com>
6
6
  License: MIT License
@@ -99,6 +99,7 @@ Description-Content-Type: text/markdown
99
99
 
100
100
  *Performs deep, iterative research using multiple LLMs and search engines with proper citations*
101
101
  </div>
102
+
102
103
  ## 🚀 What is Local Deep Research?
103
104
 
104
105
  LDR is an AI research assistant that performs systematic research by:
@@ -118,6 +119,14 @@ It aims to help researchers, students, and professionals find accurate informati
118
119
  - **Transparent**: Track costs and performance with built-in analytics
119
120
  - **Open Source**: MIT licensed with an active community
120
121
 
122
+ ## 📊 Performance
123
+
124
+ **~95% accuracy on SimpleQA benchmark** (preliminary results)
125
+ - Tested with GPT-4.1-mini + SearXNG + focused-iteration strategy
126
+ - Comparable to state-of-the-art AI research systems
127
+ - Local models can achieve similar performance with proper configuration
128
+ - [Join our community benchmarking effort →](https://github.com/LearningCircuit/local-deep-research/tree/main/community_benchmark_results)
129
+
121
130
  ## ✨ Key Features
122
131
 
123
132
  ### 🔍 Research Modes
@@ -160,7 +169,7 @@ It aims to help researchers, students, and professionals find accurate informati
160
169
 
161
170
  ## ⚡ Quick Start
162
171
 
163
- ### Option 1: Docker (Quickstart no MAC/ARM)
172
+ ### Option 1: Docker (Quickstart on MAC/ARM)
164
173
 
165
174
  ```bash
166
175
  # Step 1: Pull and run SearXNG for optimal search results
@@ -175,7 +184,13 @@ docker run -d -p 5000:5000 --name local-deep-research --volume 'deep-research:/i
175
184
  LDR uses Docker compose to bundle the web app and all it's dependencies so
176
185
  you can get up and running quickly.
177
186
 
178
- #### Option 2a: DIY docker-compose
187
+ #### Option 2a: Quick Start (One Command)
188
+ ```bash
189
+ curl -O https://raw.githubusercontent.com/LearningCircuit/local-deep-research/main/docker-compose.yml && docker compose up -d
190
+ ```
191
+ Open http://localhost:5000 after ~30 seconds. This starts LDR with SearXNG and all dependencies.
192
+
193
+ #### Option 2b: DIY docker-compose
179
194
  See [docker-compose.yml](./docker-compose.yml) for a docker-compose file with reasonable defaults to get up and running with ollama, searxng, and local deep research all running locally.
180
195
 
181
196
  Things you may want/need to configure:
@@ -184,7 +199,7 @@ Things you may want/need to configure:
184
199
  * Ollama keep alive (duration model will stay loaded into VRAM and idle before getting unloaded automatically)
185
200
  * Deep Research model (depends on available VRAM and preference)
186
201
 
187
- #### Option 2b: Use Cookie Cutter to tailor a docker-compose to your needs:
202
+ #### Option 2c: Use Cookie Cutter to tailor a docker-compose to your needs:
188
203
 
189
204
  ##### Prerequisites
190
205
 
@@ -1,9 +1,9 @@
1
- local_deep_research-0.6.1.dist-info/METADATA,sha256=YMrqywP2xGWYA40UZUB51NA5A3k9iYUitu5kHiJlpO4,14522
2
- local_deep_research-0.6.1.dist-info/WHEEL,sha256=tSfRZzRHthuv7vxpI4aehrdN9scLjk-dCJkPLzkHxGg,90
3
- local_deep_research-0.6.1.dist-info/entry_points.txt,sha256=GcXS501Rjh-P80S8db7hnrQ23mS_Jg27PwpVQVO77as,113
4
- local_deep_research-0.6.1.dist-info/licenses/LICENSE,sha256=Qg2CaTdu6SWnSqk1_JtgBPp_Da-LdqJDhT1Vt1MUc5s,1072
5
- local_deep_research/__init__.py,sha256=j1ktf_e9HeXPe86NHibY5aINtZfTSGRTvLNtz9BJZa4,1071
6
- local_deep_research/__version__.py,sha256=baAcEjLSYFIeNZF51tOMmA_zAMhN8HvKael-UU-Ruec,22
1
+ local_deep_research-0.6.4.dist-info/METADATA,sha256=TtghNU7ziPFS-HZL26QwIS_4EcR7JNL85H0e8BRBOCs,15218
2
+ local_deep_research-0.6.4.dist-info/WHEEL,sha256=tSfRZzRHthuv7vxpI4aehrdN9scLjk-dCJkPLzkHxGg,90
3
+ local_deep_research-0.6.4.dist-info/entry_points.txt,sha256=GcXS501Rjh-P80S8db7hnrQ23mS_Jg27PwpVQVO77as,113
4
+ local_deep_research-0.6.4.dist-info/licenses/LICENSE,sha256=Qg2CaTdu6SWnSqk1_JtgBPp_Da-LdqJDhT1Vt1MUc5s,1072
5
+ local_deep_research/__init__.py,sha256=_I_QZVYHUi9KSq78IVVNm_MKasj2RByOxBEo6w72PT8,1250
6
+ local_deep_research/__version__.py,sha256=WMmvm2Keb76yMz8OL_h4fKT34Xpi-1BVfCiTn2QGzz4,22
7
7
  local_deep_research/advanced_search_system/__init__.py,sha256=sGusMj4eFIrhXR6QbOM16UDKB6aI-iS4IFivKWpMlh0,234
8
8
  local_deep_research/advanced_search_system/answer_decoding/__init__.py,sha256=BmmbIPQnouYyboFD61CDq71fW5On555w7dbt42s9gV4,148
9
9
  local_deep_research/advanced_search_system/answer_decoding/browsecomp_answer_decoder.py,sha256=4FDMP4n_z5DOzVIisH3_kexRqNm1AO3MDe-Md3WtgE0,12856
@@ -166,35 +166,32 @@ local_deep_research/metrics/pricing/pricing_fetcher.py,sha256=YQThSQIZmy9VJp0TSo
166
166
  local_deep_research/metrics/query_utils.py,sha256=BDQk3F-nmI09mIGbelteCCWxq4oSKKKdHv4OO5Q_fGo,1522
167
167
  local_deep_research/metrics/search_tracker.py,sha256=sPC9hKq2X78Wlx4YUVxvneq0Ce1m0HebJAWO-226gd8,15862
168
168
  local_deep_research/metrics/token_counter.py,sha256=QmNvJhAKgpzxmBErCZ0pEAjCwgk8IBMt-gXaQRksXCs,43043
169
- local_deep_research/migrate_db.py,sha256=-Ql7bC2VmXlWtDOXj7CGVBvBlSk--wHyZCniWJnhC6c,4648
170
169
  local_deep_research/report_generator.py,sha256=8nBYTT5cO35B0b6NFsjdroBoBvzSJJa9OsUCtdQPAAg,9320
171
170
  local_deep_research/search_system.py,sha256=_JaOavJNo4q8t0Ir8KlvG6fFX3k7P6GkCOwYkCGYJ3E,27348
172
- local_deep_research/setup_data_dir.py,sha256=7MJa2MMdDUnktJVHwMpyNL2079-qylpIyyLpVbF5AUY,1134
171
+ local_deep_research/setup_data_dir.py,sha256=IMp9ndGUqY5XYIbCk0V_F4cEL3n7FWLbut5XeatqUuc,1172
173
172
  local_deep_research/utilities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
174
- local_deep_research/utilities/db_utils.py,sha256=BE3oP7WRbtlaqOxMrVFoAo11NpTk3RlC9w8tZUC_INU,1681
173
+ local_deep_research/utilities/db_utils.py,sha256=7FbN5LWiDqv7tLdcSr8cuGREBpOvIU8-f_S1Bnd3v_E,1872
175
174
  local_deep_research/utilities/enums.py,sha256=yFwmodt93uETdQd7qyW4vOUhiAzZF-BHBbVYHKN7scU,223
176
175
  local_deep_research/utilities/es_utils.py,sha256=5jT17BDR0bapHNIwMgezHmrbV4WQ7ZA1rY9CDF8ouAc,14747
177
176
  local_deep_research/utilities/llm_utils.py,sha256=svjDDto95myjtSIJyd6t6uaezBEdEtj_tH-wVGjAHV0,5046
178
- local_deep_research/utilities/log_utils.py,sha256=664m7Rc90Fna_UE8n50bPxvC7alLEYDi2EY3ZiHFQqk,5393
177
+ local_deep_research/utilities/log_utils.py,sha256=xFHsS7SJEdQhEdKoxVgcWMbY-wMEbvPD6Bey63pxh7s,5418
179
178
  local_deep_research/utilities/search_cache.py,sha256=BGHU3_1PhRc1gikiFtl-28ziqMMQLm8GBR46Hir1Y_U,13239
180
179
  local_deep_research/utilities/search_utilities.py,sha256=yyQYSBSS1IGGFwaRs0s27gEvSYgYqYRsVTK0v2jZ4GQ,9713
181
180
  local_deep_research/utilities/setup_utils.py,sha256=0Us6doQ6xQtKzgtnN1C4L7sSgxzFKJ35FpmZdj1tCDM,213
182
181
  local_deep_research/utilities/thread_context.py,sha256=M3NszCJD1xHa_9-GJpDrAi5qYmKVe55lj1Vq_Z_P8vw,3104
183
- local_deep_research/utilities/threading_utils.py,sha256=3dwErIOazT6V4HkUFo4BvjRNLe_I_PGi8Xtfl8LfmVY,2495
182
+ local_deep_research/utilities/threading_utils.py,sha256=j1YdqD0PvUuLrcaaI_itLUfWK7ki_B0F18xy0s9gtpo,2888
184
183
  local_deep_research/utilities/url_utils.py,sha256=-GjOVrJCglNCDRs9rePyP1T8d6TeIGwI_nzCA5USPd4,1909
185
184
  local_deep_research/web/__init__.py,sha256=CynnuRxCf9mB0AHeylhF5yVZwdj0H6bxVrZtniw3xmE,44
186
- local_deep_research/web/api.py,sha256=jtn6ndV-ghRYqBkxDTz2hR9woQ4yIAtwa13YXa2_d7g,11260
187
- local_deep_research/web/app.py,sha256=3bBUHXB35AE3-7oxSieF0ceYrQaq5LBTdJUSr8PpcCU,3376
188
- local_deep_research/web/app_factory.py,sha256=AjWReFfpUgpQHw70cik0MZeRmDxMwlx7VooIxWPiNnQ,10220
185
+ local_deep_research/web/api.py,sha256=JSc3mRrVVB4BHgeYLnUjtq0dxURbKKQNrS2HdRAct2o,11285
186
+ local_deep_research/web/app.py,sha256=cWiNJL-DExvg3bH6TBmL4C4fO-B-0wakdrn5qdCi-IY,798
187
+ local_deep_research/web/app_factory.py,sha256=41BwIgnHRz3KMFEp7KmAm6IydrfzIkrjO5OqV0D6CBo,9949
189
188
  local_deep_research/web/database/README.md,sha256=eEDLqLIfOBRvc0TFh3J1HrtFbZceYmVgpjS3-oyZ5nI,2861
190
189
  local_deep_research/web/database/benchmark_schema.py,sha256=nlqqG5o9XVRGtDlLzFS9XNinNntUhvl_JFUYyjMst-w,7629
191
190
  local_deep_research/web/database/convert_research_id_to_string.py,sha256=3xrVy0crCoM94N4TZfLZAEJTt7oYGX60zrDo0PZZrCQ,5619
192
- local_deep_research/web/database/migrate_to_ldr_db.py,sha256=RRzITerhjUjlHPTf6GoNgrwa4BpKuj_RAohzcS9ttG0,9919
193
- local_deep_research/web/database/migrations.py,sha256=BKUDckR98Yz8cMtd473lMxLcVqWTtFyHVFWFPs9PgfY,2468
191
+ local_deep_research/web/database/migrations.py,sha256=YLa78izXCdwY6YZokYUIPQl2Ryd-5v_jwQ79PJAI8R4,25101
194
192
  local_deep_research/web/database/models.py,sha256=eQN1Rqo_aCHjpefedoGi7zQ_HSbKKFhKTqF-6lOUvqc,7991
195
- local_deep_research/web/database/schema_upgrade.py,sha256=RamOIDMu9bTRzdG5jKK5a4h6mK3aTEPvehNwoSbQPyA,16904
196
- local_deep_research/web/database/uuid_migration.py,sha256=U9nJQyl1BszcP-4kBREKsivAk9fjQZ6BowIvjUstnT0,9041
197
- local_deep_research/web/models/database.py,sha256=uBecKQpZd9cXdt2ZPUr0FOpHFbDZd40kQNKYSZOxnEI,8422
193
+ local_deep_research/web/database/uuid_migration.py,sha256=12se2wvSLtHUNKctu_e0bfgDjfV-ykZwWCdiYcbXvv0,484
194
+ local_deep_research/web/models/database.py,sha256=w8A4ORA4jXBVdr0UK0THfLmWfbjNsA-reYv3jO6Vkaw,5915
198
195
  local_deep_research/web/models/settings.py,sha256=rXBI9vY5k3ndR8dPd3fZJy-6HwYltQihhSBRq-sZutw,2314
199
196
  local_deep_research/web/routes/api_routes.py,sha256=RlpM0cl9UKxYdezNtNvzbUQiZsTOyTnlvoRMeylUYK0,21167
200
197
  local_deep_research/web/routes/benchmark_routes.py,sha256=bXiURrmWoaGtbOQ3jhgXgxjs3Qa440Jqk1CPZ1QMyO0,15725
@@ -203,12 +200,12 @@ local_deep_research/web/routes/history_routes.py,sha256=h2AeFhpQ8H7uKulKTtddQAH8
203
200
  local_deep_research/web/routes/metrics_routes.py,sha256=HiiO_2N4_YZG0xmBaC9iny3yNwIK7lzqqRoC36SuWiE,51054
204
201
  local_deep_research/web/routes/research_routes.py,sha256=H4M_iWStNQUqmhGmMfsFBb-e9wetX6FJVH46J4d0ITE,29054
205
202
  local_deep_research/web/routes/route_registry.py,sha256=4-8hDPSoZme20kXGb3sXCfZR17mEarluhhHEF23MZ0E,10822
206
- local_deep_research/web/routes/settings_routes.py,sha256=0HncIt3upismRvZnxzbSzAF4RoxAnDJKbxYo6sdVzr8,73711
203
+ local_deep_research/web/routes/settings_routes.py,sha256=2oUCDlbLW-OKe49h59OAskNDgkZYRFdJhxVlBSijTQ0,73656
207
204
  local_deep_research/web/services/research_service.py,sha256=H-l37P61VkHENtk2iVdanf96_ocMVIFD6t9PV1XELL4,48166
208
205
  local_deep_research/web/services/resource_service.py,sha256=aU7SDADxcIAAuIymL_TOxUV_HvEMAfL8gZSB5gVSzFM,4674
209
- local_deep_research/web/services/settings_manager.py,sha256=goVcKMogPxYf7ey2dq3Cp6ULvfrQLiUJ-mOXAUsdrVY,21708
210
- local_deep_research/web/services/settings_service.py,sha256=s_JFXJTdMmZ1d-_FGWibfSKkYp6kCs5TqMVqNgBJrvQ,3666
211
- local_deep_research/web/services/socket_service.py,sha256=kKV9LbMvgMtuvX32nuZnrMWwS6IzSOM90FxL9nWsfCQ,11904
206
+ local_deep_research/web/services/settings_manager.py,sha256=EOdE8rtm4mFV3_4gLfupOtHGlQf6bBAn0m3Xz_t58sY,21235
207
+ local_deep_research/web/services/settings_service.py,sha256=OemPUMQtb8cfRjG7ZIWVDZ5ZZQTaxdQx4RNrwKgAyDQ,2821
208
+ local_deep_research/web/services/socket_service.py,sha256=oyO1_S-lFJRIHw06hepheBiz_xYanZ0Fd2gmyGV2hiI,11895
212
209
  local_deep_research/web/static/css/custom_dropdown.css,sha256=MFRm4HaMGM7X2Z-Yvb-_y20BE1NInSmN1cUJc_v5k4k,11542
213
210
  local_deep_research/web/static/css/settings.css,sha256=QZbjLz8zNQZvM_ROzQOH67ZHZHEQ8WohkIPJlsekqfk,24719
214
211
  local_deep_research/web/static/css/styles.css,sha256=u7ZjeXIk_aMwLKLyDAc5lpY6nz9J_I_SaUTZzk6Hk84,37088
@@ -284,9 +281,9 @@ local_deep_research/web_search_engines/rate_limiting/__init__.py,sha256=gWBaVMRY
284
281
  local_deep_research/web_search_engines/rate_limiting/__main__.py,sha256=9sWZ7ev3dZYPmgKK3K7fEaku2IAnjlrHPbaKV9VlllY,191
285
282
  local_deep_research/web_search_engines/rate_limiting/cli.py,sha256=xX5YD-fNXjdqCaDzx4_aEIoiZFX1AyuQV6Vfya-Wios,5683
286
283
  local_deep_research/web_search_engines/rate_limiting/exceptions.py,sha256=KIzjgVPMxx4sw1J4tjkxz0N9TgrFZGWXQxCemHnVXHI,396
287
- local_deep_research/web_search_engines/rate_limiting/tracker.py,sha256=Q36R2coA0kBE2XeRxb0Ebnq4P9DWbRsrc3DbAjS8GQU,17562
284
+ local_deep_research/web_search_engines/rate_limiting/tracker.py,sha256=vvZ0jvi9FbvqrNE0rvoncsXuEXjRwboRpPAcp03bGqk,17520
288
285
  local_deep_research/web_search_engines/retriever_registry.py,sha256=ZErfErn6s1LIQt1q9KjMu61-l7w_D_2jQceQT8kS3xo,3026
289
286
  local_deep_research/web_search_engines/search_engine_base.py,sha256=0ys6nqm4WLTvYqHLZk4x5ZKFTc4BcqhUBjT1m1Jibp0,17114
290
287
  local_deep_research/web_search_engines/search_engine_factory.py,sha256=jKvLkv6rHWSKTnqfLvyvA2WF4qu5qaelgd4IoGOcyVs,12588
291
288
  local_deep_research/web_search_engines/search_engines_config.py,sha256=aZ1Y5YMPWgZqRC-wCJ4JUQgliBNSbU0dOUlCvR_elws,6086
292
- local_deep_research-0.6.1.dist-info/RECORD,,
289
+ local_deep_research-0.6.4.dist-info/RECORD,,
@@ -1,149 +0,0 @@
1
- #!/usr/bin/env python
2
- """
3
- Database migration script for Local Deep Research.
4
- Migrates data from legacy databases (deep_research.db and research_history.db) to the new unified database (ldr.db).
5
- """
6
-
7
- import argparse
8
- import logging
9
- import os
10
- import sys
11
-
12
- try:
13
- from local_deep_research.web.database.migrate_to_ldr_db import (
14
- migrate_to_ldr_db,
15
- )
16
- from local_deep_research.web.models.database import (
17
- DB_PATH,
18
- LEGACY_DEEP_RESEARCH_DB,
19
- LEGACY_RESEARCH_HISTORY_DB,
20
- )
21
- except ImportError:
22
- # If that fails, try with the relative path.
23
- from .web.database.migrate_to_ldr_db import migrate_to_ldr_db
24
- from .web.models.database import (
25
- DB_PATH,
26
- LEGACY_DEEP_RESEARCH_DB,
27
- LEGACY_RESEARCH_HISTORY_DB,
28
- )
29
-
30
- # Configure logging
31
- logging.basicConfig(
32
- level=logging.INFO,
33
- format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
34
- handlers=[logging.StreamHandler()],
35
- )
36
- logger = logging.getLogger("migrate_db")
37
-
38
- # Add proper paths for import
39
- current_dir = os.path.dirname(os.path.abspath(__file__))
40
- sys.path.insert(0, os.path.dirname(os.path.dirname(current_dir)))
41
-
42
-
43
- def main():
44
- """Main migration function that parses arguments and runs the migration"""
45
- parser = argparse.ArgumentParser(
46
- description="Local Deep Research Database Migration"
47
- )
48
- parser.add_argument(
49
- "--backup",
50
- action="store_true",
51
- help="Create backup of existing databases before migration",
52
- )
53
- parser.add_argument(
54
- "--force",
55
- action="store_true",
56
- help="Force migration even if target database exists",
57
- )
58
- parser.add_argument(
59
- "--dry-run",
60
- action="store_true",
61
- help="Only check what would be migrated, don't perform actual migration",
62
- )
63
- parser.add_argument(
64
- "--verbose", action="store_true", help="Enable verbose logging"
65
- )
66
-
67
- args = parser.parse_args()
68
-
69
- if args.verbose:
70
- logging.getLogger().setLevel(logging.DEBUG)
71
-
72
- print("=" * 80)
73
- print("LOCAL DEEP RESEARCH DATABASE MIGRATION")
74
- print("=" * 80)
75
-
76
- try:
77
- # First try the normal import
78
- print(f"Target database will be created at: {DB_PATH}")
79
-
80
- # Check if migration is needed
81
- if os.path.exists(DB_PATH) and not args.force:
82
- print(f"Target database already exists at: {DB_PATH}")
83
- if (
84
- input(
85
- "Do you want to continue anyway? This may overwrite data. (y/n): "
86
- ).lower()
87
- != "y"
88
- ):
89
- print("Migration aborted.")
90
- return 1
91
-
92
- # Check if source databases exist
93
- deep_research_exists = os.path.exists(LEGACY_DEEP_RESEARCH_DB)
94
- research_history_exists = os.path.exists(LEGACY_RESEARCH_HISTORY_DB)
95
-
96
- if not deep_research_exists and not research_history_exists:
97
- print("No legacy databases found. Nothing to migrate.")
98
- return 0
99
-
100
- print("Found legacy databases:")
101
- if deep_research_exists:
102
- print(f" - {LEGACY_DEEP_RESEARCH_DB}")
103
- if research_history_exists:
104
- print(f" - {LEGACY_RESEARCH_HISTORY_DB}")
105
-
106
- # Create backups if requested
107
- if args.backup:
108
- if deep_research_exists:
109
- backup_path = f"{LEGACY_DEEP_RESEARCH_DB}.bak"
110
- import shutil
111
-
112
- shutil.copy2(LEGACY_DEEP_RESEARCH_DB, backup_path)
113
- print(f"Created backup: {backup_path}")
114
-
115
- if research_history_exists:
116
- backup_path = f"{LEGACY_RESEARCH_HISTORY_DB}.bak"
117
- import shutil
118
-
119
- shutil.copy2(LEGACY_RESEARCH_HISTORY_DB, backup_path)
120
- print(f"Created backup: {backup_path}")
121
-
122
- # Run migration or dry run
123
- if args.dry_run:
124
- print("\nDRY RUN - No changes will be made.")
125
- print(f"Would migrate data to: {DB_PATH}")
126
- return 0
127
- else:
128
- print(f"\nStarting migration to: {DB_PATH}")
129
-
130
- success = migrate_to_ldr_db()
131
-
132
- if success:
133
- print("\nMigration completed successfully.")
134
- print(
135
- "You can now start the application with the new unified database."
136
- )
137
- return 0
138
- else:
139
- print("\nMigration failed. Check the logs for details.")
140
- return 1
141
-
142
- except Exception as e:
143
- logger.error(f"Migration error: {e}", exc_info=True)
144
- print(f"Error during migration: {e}")
145
- return 1
146
-
147
-
148
- if __name__ == "__main__":
149
- sys.exit(main())