local-deep-research 0.2.3__py3-none-any.whl → 0.3.1__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 (42) hide show
  1. local_deep_research/__init__.py +1 -1
  2. local_deep_research/__version__.py +1 -0
  3. local_deep_research/advanced_search_system/filters/cross_engine_filter.py +5 -1
  4. local_deep_research/advanced_search_system/strategies/base_strategy.py +5 -2
  5. local_deep_research/advanced_search_system/strategies/iterdrag_strategy.py +23 -16
  6. local_deep_research/advanced_search_system/strategies/parallel_search_strategy.py +13 -6
  7. local_deep_research/advanced_search_system/strategies/rapid_search_strategy.py +4 -3
  8. local_deep_research/advanced_search_system/strategies/source_based_strategy.py +57 -62
  9. local_deep_research/advanced_search_system/strategies/standard_strategy.py +8 -4
  10. local_deep_research/api/research_functions.py +0 -46
  11. local_deep_research/citation_handler.py +2 -5
  12. local_deep_research/config/llm_config.py +25 -68
  13. local_deep_research/config/search_config.py +8 -21
  14. local_deep_research/defaults/default_settings.json +3996 -0
  15. local_deep_research/search_system.py +34 -31
  16. local_deep_research/utilities/db_utils.py +22 -3
  17. local_deep_research/utilities/search_utilities.py +10 -7
  18. local_deep_research/web/app.py +3 -23
  19. local_deep_research/web/app_factory.py +1 -25
  20. local_deep_research/web/database/migrations.py +20 -418
  21. local_deep_research/web/routes/settings_routes.py +75 -364
  22. local_deep_research/web/services/research_service.py +43 -43
  23. local_deep_research/web/services/settings_manager.py +108 -315
  24. local_deep_research/web/services/settings_service.py +3 -56
  25. local_deep_research/web/static/js/components/research.js +1 -1
  26. local_deep_research/web/static/js/components/settings.js +16 -4
  27. local_deep_research/web/static/js/research_form.js +106 -0
  28. local_deep_research/web/templates/pages/research.html +3 -2
  29. local_deep_research/web_search_engines/engines/meta_search_engine.py +56 -21
  30. local_deep_research/web_search_engines/engines/search_engine_local.py +11 -2
  31. local_deep_research/web_search_engines/engines/search_engine_local_all.py +7 -11
  32. local_deep_research/web_search_engines/search_engine_factory.py +12 -64
  33. local_deep_research/web_search_engines/search_engines_config.py +123 -64
  34. {local_deep_research-0.2.3.dist-info → local_deep_research-0.3.1.dist-info}/METADATA +16 -1
  35. {local_deep_research-0.2.3.dist-info → local_deep_research-0.3.1.dist-info}/RECORD +38 -39
  36. local_deep_research/config/config_files.py +0 -245
  37. local_deep_research/defaults/local_collections.toml +0 -53
  38. local_deep_research/defaults/main.toml +0 -80
  39. local_deep_research/defaults/search_engines.toml +0 -291
  40. {local_deep_research-0.2.3.dist-info → local_deep_research-0.3.1.dist-info}/WHEEL +0 -0
  41. {local_deep_research-0.2.3.dist-info → local_deep_research-0.3.1.dist-info}/entry_points.txt +0 -0
  42. {local_deep_research-0.2.3.dist-info → local_deep_research-0.3.1.dist-info}/licenses/LICENSE +0 -0
@@ -3,76 +3,135 @@ Configuration file for search engines.
3
3
  Loads search engine definitions from the user's configuration.
4
4
  """
5
5
 
6
+ import json
6
7
  import logging
7
- import os
8
+ from functools import cache
9
+ from typing import Any, Dict, List
8
10
 
9
- import toml
10
-
11
- from ..config.config_files import CONFIG_DIR, LOCAL_COLLECTIONS_FILE
11
+ from ..utilities.db_utils import get_db_setting
12
12
 
13
13
  logger = logging.getLogger(__name__)
14
14
 
15
- # Get search engines configuration directly from TOML file
16
- SEARCH_ENGINES = {}
17
- DEFAULT_SEARCH_ENGINE = "wikipedia" # Default fallback if not specified in config
18
15
 
19
- # Path to the search engines configuration file
20
- SEARCH_ENGINES_FILE = CONFIG_DIR / "search_engines.toml"
16
+ def _extract_per_engine_config(raw_config: Dict[str, Any]) -> Dict[str, Dict[str, Any]]:
17
+ """
18
+ Converts the "flat" configuration loaded from the settings database into
19
+ individual settings dictionaries for each engine.
20
+
21
+ Args:
22
+ raw_config: The raw "flat" configuration.
23
+
24
+ Returns:
25
+ Configuration dictionaries indexed by engine name.
26
+
27
+ """
28
+ engine_config = {}
29
+ for key, value in raw_config.items():
30
+ engine_name = key.split(".")[0]
31
+ setting_name = ".".join(key.split(".")[1:])
32
+ engine_config.setdefault(engine_name, {})[setting_name] = value
33
+
34
+ return engine_config
35
+
36
+
37
+ @cache
38
+ def search_config() -> Dict[str, Any]:
39
+ """
40
+ Returns:
41
+ The search engine configuration loaded from the database.
42
+
43
+ """
44
+ # Extract search engine definitions
45
+ config_data = get_db_setting("search.engine.web", {})
46
+ search_engines = _extract_per_engine_config(config_data)
47
+ search_engines["auto"] = get_db_setting("search.engine.auto", {})
48
+
49
+ logger.info(f"Loaded {len(search_engines)} search engines from configuration file")
50
+ logger.info(f"\n {', '.join(sorted(search_engines.keys()))} \n")
51
+
52
+ # Add alias for 'auto' if it exists
53
+ if "auto" in search_engines and "meta" not in search_engines:
54
+ search_engines["meta"] = search_engines["auto"]
55
+
56
+ # Register local document collections
57
+ local_collections_data = get_db_setting("search.engine.local", {})
58
+ local_collections_data = _extract_per_engine_config(local_collections_data)
59
+
60
+ for collection, config in local_collections_data.items():
61
+ if not config.get("enabled", True):
62
+ # Search engine is not enabled. Ignore.
63
+ logger.info(f"Ignoring disabled local collection '{collection}'.")
64
+ continue
65
+
66
+ if "paths" in config and isinstance(config["paths"], str):
67
+ # This will be saved as a json array.
68
+ try:
69
+ config["paths"] = json.loads(config["paths"])
70
+ except json.decoder.JSONDecodeError:
71
+ logger.error(
72
+ f"Invalid paths specified for local collection: "
73
+ f"{config['paths']}"
74
+ )
75
+ config["paths"] = []
76
+
77
+ # Create a new dictionary with required search engine fields
78
+ engine_config = {
79
+ "default_params": config,
80
+ "requires_llm": True,
81
+ }
82
+ engine_config_prefix = f"search.engine.local.{collection}"
83
+ engine_config["module_path"] = get_db_setting(
84
+ f"{engine_config_prefix}.module_path",
85
+ "local_deep_research.web_search_engines.engines.search_engine_local",
86
+ )
87
+ engine_config["class_name"] = get_db_setting(
88
+ f"{engine_config_prefix}.class_name",
89
+ "LocalSearchEngine",
90
+ )
21
91
 
22
- # Load directly from TOML file
23
- if os.path.exists(SEARCH_ENGINES_FILE):
24
- try:
25
- # Load the TOML file directly
26
- config_data = toml.load(SEARCH_ENGINES_FILE)
92
+ # Copy these specific fields to the top level if they exist
93
+ for field in ["strengths", "weaknesses", "reliability", "description"]:
94
+ if field in config:
95
+ engine_config[field] = config[field]
27
96
 
28
- # Extract search engine definitions
29
- for key, value in config_data.items():
30
- if key == "DEFAULT_SEARCH_ENGINE":
31
- DEFAULT_SEARCH_ENGINE = value
32
- elif isinstance(value, dict):
33
- SEARCH_ENGINES[key] = value
97
+ search_engines[collection] = engine_config
34
98
 
35
- logger.info(
36
- f"Loaded {len(SEARCH_ENGINES)} search engines from configuration file"
37
- )
38
- logger.info(f"\n {', '.join(sorted(SEARCH_ENGINES.keys()))} \n")
39
- except Exception as e:
40
- logger.error(f"Error loading search engines from TOML file: {e}")
41
- else:
42
- logger.warning(
43
- f"Search engines configuration file not found: {SEARCH_ENGINES_FILE}"
44
- )
45
-
46
- # Add alias for 'auto' if it exists
47
- if "auto" in SEARCH_ENGINES and "meta" not in SEARCH_ENGINES:
48
- SEARCH_ENGINES["meta"] = SEARCH_ENGINES["auto"]
49
-
50
- # Register local document collections
51
-
52
- if os.path.exists(LOCAL_COLLECTIONS_FILE):
53
- try:
54
- local_collections_data = toml.load(LOCAL_COLLECTIONS_FILE)
55
-
56
- for collection, config in local_collections_data.items():
57
- # Create a new dictionary with required search engine fields
58
- engine_config = {
59
- "module_path": "local_deep_research.web_search_engines.engines.search_engine_local",
60
- "class_name": "LocalSearchEngine",
61
- "default_params": config,
62
- "requires_llm": True,
63
- }
64
-
65
- # Copy these specific fields to the top level if they exist
66
- for field in ["strengths", "weaknesses", "reliability", "description"]:
67
- if field in config:
68
- engine_config[field] = config[field]
69
-
70
- SEARCH_ENGINES[collection] = engine_config
71
-
72
- logger.info("Registered local document collections as search engines")
73
- except Exception as e:
74
- logger.error(f"Error loading local collections from TOML file: {e}")
75
- # Ensure the meta search engine is still available at the end if it exists
76
- if "auto" in SEARCH_ENGINES:
77
- meta_config = SEARCH_ENGINES["auto"]
78
- SEARCH_ENGINES["auto"] = meta_config
99
+ logger.info("Registered local document collections as search engines")
100
+ # Ensure the meta search engine is still available at the end if it exists
101
+ if "auto" in search_engines:
102
+ meta_config = search_engines["auto"]
103
+ search_engines["auto"] = meta_config
104
+
105
+ return search_engines
106
+
107
+
108
+ @cache
109
+ def default_search_engine() -> str:
110
+ """
111
+ Returns:
112
+ The configured default search engine.
113
+
114
+ """
115
+ return get_db_setting("search.engine.DEFAULT_SEARCH_ENGINE", "wikipedia")
116
+
117
+
118
+ @cache
119
+ def local_search_engines() -> List[str]:
120
+ """
121
+ Returns:
122
+ A list of the enabled local search engines.
123
+
124
+ """
125
+ local_collections_data = get_db_setting("search.engine.local", {})
126
+ local_collections_data = _extract_per_engine_config(local_collections_data)
127
+
128
+ # Don't include the `local_all` collection.
129
+ local_collections_data.pop("local_all", None)
130
+ # Remove disabled collections.
131
+ local_collections_data = {
132
+ k: v for k, v in local_collections_data.items() if v.get("enabled", True)
133
+ }
134
+
135
+ enabled_collections = list(local_collections_data.keys())
136
+ logger.debug(f"Using local collections: {enabled_collections}")
137
+ return enabled_collections
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: local-deep-research
3
- Version: 0.2.3
3
+ Version: 0.3.1
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>
6
6
  License: MIT License
@@ -122,6 +122,21 @@ A powerful AI-powered research assistant that performs deep, iterative analysis
122
122
 
123
123
  **Important for non-academic searches:** For normal web searches you will need SearXNG or an API key to a search provider like brave search or SerpAPI. The free searches are mostly academic search engines and will not help you for most normal searches.
124
124
 
125
+ ## Quick SearXNG Setup (Recommended)
126
+
127
+ ```bash
128
+ # Pull the SearXNG Docker image
129
+ docker pull searxng/searxng
130
+
131
+ # Run SearXNG (will be available at http://localhost:8080)
132
+ docker run -d -p 8080:8080 --name searxng searxng/searxng
133
+
134
+ # Start SearXNG (Required after system restart)
135
+ docker start searxng
136
+ ```
137
+
138
+ Once these commands are executed, SearXNG will be automatically activated and ready to use. The tool will automatically detect and use your local SearXNG instance for searches.
139
+
125
140
  ## Windows Installation
126
141
 
127
142
  Download the [Windows Installer](https://github.com/LearningCircuit/local-deep-research/releases/download/v0.1.0/LocalDeepResearch_Setup.exe) for easy one-click installation.
@@ -1,13 +1,14 @@
1
- local_deep_research-0.2.3.dist-info/METADATA,sha256=46N1CYIqxccMSv3Iaq-Tm8gEFtnuc1ATUJqfM720HkE,19797
2
- local_deep_research-0.2.3.dist-info/WHEEL,sha256=tSfRZzRHthuv7vxpI4aehrdN9scLjk-dCJkPLzkHxGg,90
3
- local_deep_research-0.2.3.dist-info/entry_points.txt,sha256=GcXS501Rjh-P80S8db7hnrQ23mS_Jg27PwpVQVO77as,113
4
- local_deep_research-0.2.3.dist-info/licenses/LICENSE,sha256=Qg2CaTdu6SWnSqk1_JtgBPp_Da-LdqJDhT1Vt1MUc5s,1072
5
- local_deep_research/__init__.py,sha256=tczbsYNZQqfPAuVtz6OFyo-uUqjNQLelEIT2G7mPTwA,870
1
+ local_deep_research-0.3.1.dist-info/METADATA,sha256=hm0xOekqqqLIN0jglNZfEIsEZXrlg29PaAPgav3jFd4,20274
2
+ local_deep_research-0.3.1.dist-info/WHEEL,sha256=tSfRZzRHthuv7vxpI4aehrdN9scLjk-dCJkPLzkHxGg,90
3
+ local_deep_research-0.3.1.dist-info/entry_points.txt,sha256=GcXS501Rjh-P80S8db7hnrQ23mS_Jg27PwpVQVO77as,113
4
+ local_deep_research-0.3.1.dist-info/licenses/LICENSE,sha256=Qg2CaTdu6SWnSqk1_JtgBPp_Da-LdqJDhT1Vt1MUc5s,1072
5
+ local_deep_research/__init__.py,sha256=9wV3oonZMEHsE_JhyZU9P0hW2Uwv47zotGlbAB_gQiA,885
6
6
  local_deep_research/__main__.py,sha256=LIxK5iS6aLAKMFBDpUS3V-jDcxchqi3eSUsI2jAZUXk,371
7
+ local_deep_research/__version__.py,sha256=r4xAFihOf72W9TD-lpMi6ntWSTKTP2SlzKP1ytkjRbI,22
7
8
  local_deep_research/advanced_search_system/__init__.py,sha256=sGusMj4eFIrhXR6QbOM16UDKB6aI-iS4IFivKWpMlh0,234
8
9
  local_deep_research/advanced_search_system/filters/__init__.py,sha256=2dXrV4skcVHI2Lb3BSL2Ajq0rnLeSw7kc1MbIynMxa4,190
9
10
  local_deep_research/advanced_search_system/filters/base_filter.py,sha256=dFNQ7U2dj4bf3voT73YhcG-w9eW-BTlc4F9kstFcETY,969
10
- local_deep_research/advanced_search_system/filters/cross_engine_filter.py,sha256=j-0bBFHEaLbfOJxIWH8MzNpQ2JIKn9zGwzzLbyn8tm0,7775
11
+ local_deep_research/advanced_search_system/filters/cross_engine_filter.py,sha256=R2pM5p06gXLwOvXexGcUe5h4OQpxmlft-DXC217CiOo,8004
11
12
  local_deep_research/advanced_search_system/findings/base_findings.py,sha256=tTVEQZeGuTdJ1tDF8QAkiS5pWest8_lmbq3Oq5EPGeY,2052
12
13
  local_deep_research/advanced_search_system/findings/repository.py,sha256=nIdF114IaSNLjnjetbXE8s8C69djik3lywOiFvFI4Lk,19804
13
14
  local_deep_research/advanced_search_system/knowledge/__init__.py,sha256=9zjQkdmomZCgZZP45fqw0E8UVpBjkzkyW7RpY0f8gY8,34
@@ -19,48 +20,45 @@ local_deep_research/advanced_search_system/questions/decomposition_question.py,s
19
20
  local_deep_research/advanced_search_system/questions/standard_question.py,sha256=SRT5f8pFlcI-AT88CgmQZEnU6-XKpN2cppvMxO6mWXc,4561
20
21
  local_deep_research/advanced_search_system/repositories/__init__.py,sha256=cCjAR9Z3BFZaN6_OYN9zJPvwcxCxgfp9oOeMqUmLX2c,145
21
22
  local_deep_research/advanced_search_system/strategies/__init__.py,sha256=upbslnB6Ns8RJ0-b1bH74-f5gZbo7evpx1dRrKEkzHA,35
22
- local_deep_research/advanced_search_system/strategies/base_strategy.py,sha256=cK5DqvsjGlFyqKRtpl0-dI6cip32UIbGS8eqsuL9SjI,3781
23
- local_deep_research/advanced_search_system/strategies/iterdrag_strategy.py,sha256=eKCyxNVRnN7pOr-8LEzREbRkHX6ffa9hmjGwBYHHDDc,18129
24
- local_deep_research/advanced_search_system/strategies/parallel_search_strategy.py,sha256=dA5KgS5G_1O82MLhWx1UOZi5P4c7hqWdQPRdtt1B49U,19006
25
- local_deep_research/advanced_search_system/strategies/rapid_search_strategy.py,sha256=fiLTqCfpyoNlP_rRZB96gdi3KoOkCWk-Nw5fb7E9an4,10389
26
- local_deep_research/advanced_search_system/strategies/source_based_strategy.py,sha256=PW5gHhpayon3d716Ooo02UITkoxfBGvgzrm7kFITWWo,17312
27
- local_deep_research/advanced_search_system/strategies/standard_strategy.py,sha256=FbZAHiRAhfFCtA46Im0KxF5QNzursiz0SqhimvNiaXs,12747
23
+ local_deep_research/advanced_search_system/strategies/base_strategy.py,sha256=NVowhf36DLeES302v0U6cWDCmQvNuV0cVj4glSculfQ,3975
24
+ local_deep_research/advanced_search_system/strategies/iterdrag_strategy.py,sha256=dKTgwXaXFxBqzUw_S434LdEvV4HL2CrR9K9KBaMYxOg,18473
25
+ local_deep_research/advanced_search_system/strategies/parallel_search_strategy.py,sha256=iOWxbfKQZAt-Ua8NDqKaMZugete0YMCk9wfQfKkQHVE,19385
26
+ local_deep_research/advanced_search_system/strategies/rapid_search_strategy.py,sha256=giuBMkkxUkdI4J9711bjM3ReMLTFfyt6irT4v-3ef_Q,10426
27
+ local_deep_research/advanced_search_system/strategies/source_based_strategy.py,sha256=QmdwUV56ZGCHMLti91hEFQ6As9Yp0C_rvC6aJsnfI0U,17288
28
+ local_deep_research/advanced_search_system/strategies/standard_strategy.py,sha256=Yqe5N3bUCDXjeSlP8__AORPYyHVY5sEb82zvpTU34r8,12774
28
29
  local_deep_research/advanced_search_system/tools/__init__.py,sha256=73jLuCKigwc9lJQ0uD3_F16dgCg4pL-F2cwC6tk9-oc,30
29
30
  local_deep_research/advanced_search_system/tools/base_tool.py,sha256=jEs4eroCvo0dHP_uF-5kLiQP7OfkD1YzNAD650a8Ktk,2865
30
31
  local_deep_research/advanced_search_system/tools/knowledge_tools/__init__.py,sha256=73jLuCKigwc9lJQ0uD3_F16dgCg4pL-F2cwC6tk9-oc,30
31
32
  local_deep_research/advanced_search_system/tools/question_tools/__init__.py,sha256=73jLuCKigwc9lJQ0uD3_F16dgCg4pL-F2cwC6tk9-oc,30
32
33
  local_deep_research/advanced_search_system/tools/search_tools/__init__.py,sha256=73jLuCKigwc9lJQ0uD3_F16dgCg4pL-F2cwC6tk9-oc,30
33
34
  local_deep_research/api/__init__.py,sha256=-tJQp7Qm1aPg6fgfuw-w9dfNo8GzrJLOy2i3dG8Drl8,441
34
- local_deep_research/api/research_functions.py,sha256=8Q_Rzfc0Qj2oLxzvFJIA4ms10uQC0a5SBHkIkSoPcw4,10908
35
+ local_deep_research/api/research_functions.py,sha256=SItLEuib94AXrhMsgmYDtykGrVmBPDKYHzzeDPhH688,9563
35
36
  local_deep_research/app.py,sha256=U_92UX0dpVAQoaXciVNy_By_AyDEWGlXSeTwFpohALQ,155
36
- local_deep_research/citation_handler.py,sha256=NoEvnpf7jqCAJX6H-H8i2Hz69CVPW6UBg12cBRYtVdA,4396
37
+ local_deep_research/citation_handler.py,sha256=MZVd6xl7g3xrWauFBPuVIC36z8onc-zQb8xI4dQXxsU,4307
37
38
  local_deep_research/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
- local_deep_research/config/config_files.py,sha256=k6ptAKIvqGrhnRsfRjT9uD2xBLAiD0vqXoYxggF5mik,10041
39
- local_deep_research/config/llm_config.py,sha256=KhuDbxjndU939rMCKmeYDctsx7fRoXMoQRv1AgtZKI4,16536
40
- local_deep_research/config/search_config.py,sha256=-qacGuPOuOgPzSS0j2Nt7dBBah2cx4syIlm5KMrGzRo,2503
39
+ local_deep_research/config/llm_config.py,sha256=Ot61pHJVAjgX9l3SmaoyxcaQg1pd2dmK24XYL8JyTs8,14743
40
+ local_deep_research/config/search_config.py,sha256=ruryPSS4Wy9-xi_02c-98KLKaELeLnZ10pnCpc0-ogg,2171
41
41
  local_deep_research/defaults/.env.template,sha256=_eVCy4d_XwpGXy8n50CG3wH9xx2oqJCFKS7IbqgInDk,491
42
42
  local_deep_research/defaults/__init__.py,sha256=C_0t0uZmtrVB4rM9NM9Wx8PJU5kFcT-qOHvws5W2iOg,1352
43
- local_deep_research/defaults/local_collections.toml,sha256=zNa03PVnFrZ757JdZOuW6QDxkOc6ep5tG8baGBrMmXM,1778
44
- local_deep_research/defaults/main.toml,sha256=4PfSKHXzPjesdh7IzLprJ_oaCxqum9PvuKEaxr_-iJI,1940
45
- local_deep_research/defaults/search_engines.toml,sha256=XBnqCxzFvXa1HoKLcb_Jg4EGXMlgYOw1sm_CicSdYDM,8285
43
+ local_deep_research/defaults/default_settings.json,sha256=J9vhJHu2lMYMJnw68kO4e0So3SrMrHUwbjPW7i4LAPc,119769
46
44
  local_deep_research/main.py,sha256=umGmaQmW7bpx27wUAgSNjNr4oSHV6mDX5hoyfb22HEY,7033
47
45
  local_deep_research/migrate_db.py,sha256=S1h6Bv0OJdRW4BaH7MIMrUXBRV_yqgH2T6LVOZKTQjI,4634
48
46
  local_deep_research/report_generator.py,sha256=-G3KDEbsuU3PdxDfuo5v28DIX7RE1yJCCBU2KgRbNzI,9084
49
- local_deep_research/search_system.py,sha256=YmXu9ui-aB5kGb9rqQWUb7qSvd-iHfp3PvRenPwCdDA,7604
47
+ local_deep_research/search_system.py,sha256=hzJRsT5iX_D65Su4Q8v6Dd9ElH-oG0E7RhqulgEqXSY,7567
50
48
  local_deep_research/setup_data_dir.py,sha256=7MJa2MMdDUnktJVHwMpyNL2079-qylpIyyLpVbF5AUY,1134
51
49
  local_deep_research/test_migration.py,sha256=cXY9WbpxLslNEa1vFwLMvcvKBbUe7Wosm--AqmPIPYM,6459
52
50
  local_deep_research/utilities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
53
- local_deep_research/utilities/db_utils.py,sha256=pSxtGT6rGFf2-yrci0FW0UBUj51B7WOhzS0GfMeY7oQ,1226
51
+ local_deep_research/utilities/db_utils.py,sha256=27RTIWrzyNC0oDmJAOc6raTmmgrc8jqJLxH7jQbCt0g,1830
54
52
  local_deep_research/utilities/enums.py,sha256=yFwmodt93uETdQd7qyW4vOUhiAzZF-BHBbVYHKN7scU,223
55
53
  local_deep_research/utilities/llm_utils.py,sha256=1O8faskPSnyave15cxOVXQcdcFrDybQA445m0OjnD9g,4877
56
- local_deep_research/utilities/search_utilities.py,sha256=JiSRMiXZEgtpEbpmPbfoBtR5tARB6Su0wEeATFVz_9Y,9453
54
+ local_deep_research/utilities/search_utilities.py,sha256=k4Eag-XJOZl4cRd4GO1z2WpvVPLLhZ-HuBD7RswhaQM,9604
57
55
  local_deep_research/utilities/setup_utils.py,sha256=0Us6doQ6xQtKzgtnN1C4L7sSgxzFKJ35FpmZdj1tCDM,213
58
56
  local_deep_research/web/__init__.py,sha256=CynnuRxCf9mB0AHeylhF5yVZwdj0H6bxVrZtniw3xmE,44
59
- local_deep_research/web/app.py,sha256=yOCi7ZT8bPjmX9N_2YkhYwFiIvf33VMDYeHRtLgBBE4,4213
60
- local_deep_research/web/app_factory.py,sha256=vGQ7UL6zDIX8MSt2Z_CIOwkD5Phj-kXkPhN9KoJHW2E,9037
57
+ local_deep_research/web/app.py,sha256=tl3PAf41NBYYGq0oeIKAZw_hVSB8JmjyF8jzvYPeAU0,3414
58
+ local_deep_research/web/app_factory.py,sha256=rk5QCwpxrub6ptKsvjSDTNtq8d2RWbKo2LZLvL__fPo,8107
61
59
  local_deep_research/web/database/README.md,sha256=eEDLqLIfOBRvc0TFh3J1HrtFbZceYmVgpjS3-oyZ5nI,2861
62
60
  local_deep_research/web/database/migrate_to_ldr_db.py,sha256=-ltKuhgosPhybDsJ13BuvvHEDJTN4Jx6SiO6XvW0SKA,9823
63
- local_deep_research/web/database/migrations.py,sha256=9u33vKB-Q9ixtd52hWitOZI2U5ULaEnoylccGoyQInU,16718
61
+ local_deep_research/web/database/migrations.py,sha256=ylfHrPGs0xWwUAAratsXGJ2aoS_C0ysHd92EwniLz44,1618
64
62
  local_deep_research/web/database/models.py,sha256=MIxYWIQIovkrR65rFMxlDXn2iZXf5SIePIE_-vSmLXg,3489
65
63
  local_deep_research/web/database/schema_upgrade.py,sha256=u3tx_tlsuzJw-NhvhKvQG6dqzwUckQkic0D3taZAt-k,2924
66
64
  local_deep_research/web/models/database.py,sha256=NV4h0RU0ta408SkI_ZmquCplMTNH1Q4zxYJ4SHwmiGY,9489
@@ -68,11 +66,11 @@ local_deep_research/web/models/settings.py,sha256=rXBI9vY5k3ndR8dPd3fZJy-6HwYltQ
68
66
  local_deep_research/web/routes/api_routes.py,sha256=S0UdCmfm0v1GEM4UiSbI0PE3xUOxiGaYFR2ZOE0256U,19075
69
67
  local_deep_research/web/routes/history_routes.py,sha256=6a_8nX349viuvi1zP5S7BaPPpAh133eTi1NVWO545A8,12622
70
68
  local_deep_research/web/routes/research_routes.py,sha256=JlzaP1z-7XAP3E0nkEjLIfYj_NKf5qDcrjxBmUouAhM,23492
71
- local_deep_research/web/routes/settings_routes.py,sha256=rEvvFCVWJ80zchnzXBv9SAnDXMvDPLGDjSUfLRlCCi0,60012
72
- local_deep_research/web/services/research_service.py,sha256=0tFx3wactXhZjFuZDHC3aAFgpDTtjfm_c-1HsZLxaos,39656
69
+ local_deep_research/web/routes/settings_routes.py,sha256=r9RbCCD37rqPsQPFyzlku6OElzQP-nuLbL4AH6e6Fgo,49233
70
+ local_deep_research/web/services/research_service.py,sha256=vs_pWuv56rG2atgSamlDK4MdxpWTxbBVf3rHztr6y2A,39488
73
71
  local_deep_research/web/services/resource_service.py,sha256=yKgOC6GEOmHqRoGzwf52e19UaGCCS1DbDbOIXgWGvGc,4378
74
- local_deep_research/web/services/settings_manager.py,sha256=ybnhSlByuKA2oJPElN2WI8bh-ZzC6lP08x0Gsz8Ycbk,24310
75
- local_deep_research/web/services/settings_service.py,sha256=1XHvNBNs9gzor2AxOEDrqL-JsKyXKk5izCnoXAV78u8,5064
72
+ local_deep_research/web/services/settings_manager.py,sha256=lHc0Arh9RR4D_Dubj6OxtlZw7MvHtdY8Db9p5LnX_ac,16376
73
+ local_deep_research/web/services/settings_service.py,sha256=SgmjhMvGZjJE63hKKaqY7kPGphnUyXcQG8NFN5rTizs,3550
76
74
  local_deep_research/web/services/socket_service.py,sha256=jZGXk6kesBOf4bAdLiT3V4Ofod12pGKTsvxr3ml8ydY,7272
77
75
  local_deep_research/web/static/css/custom_dropdown.css,sha256=-pCx6oazWVgwqFAGq_eZ8OrTKMVQlgkKYCM6w-bACLs,7949
78
76
  local_deep_research/web/static/css/settings.css,sha256=QZbjLz8zNQZvM_ROzQOH67ZHZHEQ8WohkIPJlsekqfk,24719
@@ -84,11 +82,12 @@ local_deep_research/web/static/js/components/fallback/ui.js,sha256=b2mbTrUGMdH6p
84
82
  local_deep_research/web/static/js/components/history.js,sha256=Tqn6tdFcj5QMZd_eW8YTIHPVQMEMFUQJlRaFv0waQFA,16100
85
83
  local_deep_research/web/static/js/components/logpanel.js,sha256=bRYkOf-BRTAHrHx9cnF8wYMWVoCbyA7XevcJzTujQjg,42115
86
84
  local_deep_research/web/static/js/components/progress.js,sha256=aTvtyZDQMkjyhqy62icuZuJ7Khyujgust6fpQFcRABk,41570
87
- local_deep_research/web/static/js/components/research.js,sha256=eGcYMgprmwTG0ApZuzazqXsdUed7GbWEzBwnCNHJL3U,81074
85
+ local_deep_research/web/static/js/components/research.js,sha256=LQmZNqRrxkqa61pGaXHLiHGh7SNiq5XNMqfGMKCRDzM,81074
88
86
  local_deep_research/web/static/js/components/results.js,sha256=7fL18Yn0DwAjuelXvz-UlbDiLCFk-_UEEeqEjaDEVBA,32314
89
- local_deep_research/web/static/js/components/settings.js,sha256=CgQQ8Bz1JW9n8zZIkTcZs5LgbtwB3MAGGwohQSgHlyc,167969
87
+ local_deep_research/web/static/js/components/settings.js,sha256=0i8bwvgVrgyAeRus29txodBY5MeAVSpZ0byL5h_VRgY,168278
90
88
  local_deep_research/web/static/js/components/settings_sync.js,sha256=LWDZ2EE8ChCxI5TPmPm9F4rOiYIEzEJxSCE1GLXk-2w,3925
91
89
  local_deep_research/web/static/js/main.js,sha256=NHOcEVytPCvF5tz3yPWg8Qu5ghVs5-GWKmpaKB87oi4,8440
90
+ local_deep_research/web/static/js/research_form.js,sha256=qOZK0z_BE_xx2a1sx5vTjsCTW-ggHES_uj5eunO9Bo8,3632
92
91
  local_deep_research/web/static/js/services/api.js,sha256=AP24hrw6VBrEjQxIMnxrZuGFmrdm9MReSjjZ-AIKqr0,6776
93
92
  local_deep_research/web/static/js/services/audio.js,sha256=-Sdjuq8U-isBEK4aLc-QMDedfGtEvsQc7FBJTEoAueM,857
94
93
  local_deep_research/web/static/js/services/formatting.js,sha256=wBAVHls_TTzGLreqi7lHcm0dXPm7F0Itttpn8NEtzfg,3345
@@ -107,7 +106,7 @@ local_deep_research/web/templates/components/sidebar.html,sha256=FLjlpwlXPoNd-Nc
107
106
  local_deep_research/web/templates/pages/details.html,sha256=OYvSNfi8uFD1wNeHxWza1-xWMrT9c4V7U0ZEZnISlCU,2768
108
107
  local_deep_research/web/templates/pages/history.html,sha256=ZS3QufL2beUVB9P_LvqIixvYfCT-EjtokQa9LRp5sUs,1982
109
108
  local_deep_research/web/templates/pages/progress.html,sha256=tq9XRRZBm2KnnBxPlAa7cWWDAP-pqJeHGgtlul7UVSs,2550
110
- local_deep_research/web/templates/pages/research.html,sha256=abrFM19P86U5uaNUZmJMl75pkJuAM4isZ2WBd6s5vGs,6965
109
+ local_deep_research/web/templates/pages/research.html,sha256=b1NnqsrGvSJdt3FMHlEr3C7zbgCwVdBgoV8qOE0LNU0,7052
111
110
  local_deep_research/web/templates/pages/results.html,sha256=XKZVWo1CfbyjxMOntFO7IiF0_xX5r-JaJf7HDUSZTEY,2721
112
111
  local_deep_research/web/templates/settings_dashboard.html,sha256=A1fBe1D29v8G3ys94_rIiBP6Ky-rtYL6TRbDluoBMPI,4342
113
112
  local_deep_research/web/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -115,15 +114,15 @@ local_deep_research/web/utils/formatters.py,sha256=Gj_a0oFveNXHtvkiFe1rwlEtzYerM
115
114
  local_deep_research/web_search_engines/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
116
115
  local_deep_research/web_search_engines/engines/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
117
116
  local_deep_research/web_search_engines/engines/full_search.py,sha256=6Pi_wj9oAtDHAyLsIbWGBeS8QBv6yCJEJ87LN68Cp-k,4703
118
- local_deep_research/web_search_engines/engines/meta_search_engine.py,sha256=92L7PKHh6DKV2ESxoycR_pXBYt_jC4XlTJAJKn9ptzk,12970
117
+ local_deep_research/web_search_engines/engines/meta_search_engine.py,sha256=qUFl8yw5l7sfH-BRpXXrNQ2KrQ9LsaslhG1glb2AOIM,14715
119
118
  local_deep_research/web_search_engines/engines/search_engine_arxiv.py,sha256=3k8R4pyqIZf0RDMqXDw08xIGsfkp4ZR9kePDbmeuaH0,16603
120
119
  local_deep_research/web_search_engines/engines/search_engine_brave.py,sha256=y1j4CSLM0Ujw1LSBiWg1ZBnc2BvrkhDCorrQLnUBVtM,9149
121
120
  local_deep_research/web_search_engines/engines/search_engine_ddg.py,sha256=w9vRDpt_L0h5J-PWiNO_3J5uuRsfk5smlcIQjRofwB4,4649
122
121
  local_deep_research/web_search_engines/engines/search_engine_github.py,sha256=bojmx-R36eT_s20DGspAopkwqt6vKy4q_jH4foBt3Kk,31934
123
122
  local_deep_research/web_search_engines/engines/search_engine_google_pse.py,sha256=DuFtSUZgBR7nFBLZrbFMEuG-Rnv0cb-upHeGSDo7xRY,11177
124
123
  local_deep_research/web_search_engines/engines/search_engine_guardian.py,sha256=bNCppKJNNvkmw-LR5vfpRABhdhsUwOJqpcRHVjcziNU,23390
125
- local_deep_research/web_search_engines/engines/search_engine_local.py,sha256=7s2qcyslMNiwXQynYjm_9t8nL_MDfue8wuDrBhfpcEg,40506
126
- local_deep_research/web_search_engines/engines/search_engine_local_all.py,sha256=zg963qnwg8XwUqc9DeBrFaDSEHVr-j7Bv76WhaEuyi8,5785
124
+ local_deep_research/web_search_engines/engines/search_engine_local.py,sha256=ephjkDrQbvil6GnceW31qSt70k11REOJ9o7y-bl69-A,40857
125
+ local_deep_research/web_search_engines/engines/search_engine_local_all.py,sha256=vznpusmCBY9bLjD8EPrVhCb_8RZ8e9Wa8x386zv0pcM,5681
127
126
  local_deep_research/web_search_engines/engines/search_engine_pubmed.py,sha256=O99qfbSz7RHqinAP_C0iod-ZaEGE5tyBbh1DJi2-VhQ,38495
128
127
  local_deep_research/web_search_engines/engines/search_engine_searxng.py,sha256=wPYIl22SgXjIDYzcq62glGH2JZywCnZR31he1i7U1cE,18053
129
128
  local_deep_research/web_search_engines/engines/search_engine_semantic_scholar.py,sha256=jYs_TRM0izMfldsZ8NkCQsP-o6vCPXUjyxt0nIsxOVI,22799
@@ -131,6 +130,6 @@ local_deep_research/web_search_engines/engines/search_engine_serpapi.py,sha256=O
131
130
  local_deep_research/web_search_engines/engines/search_engine_wayback.py,sha256=rfRs7WJxa-H1DXSyduFHBMfpFwWEVRXLd8s_78iU8gU,17894
132
131
  local_deep_research/web_search_engines/engines/search_engine_wikipedia.py,sha256=UxYBSGD-XZGQantq_AdgtBA8FCKV0C6mEr6GS_vleQQ,10092
133
132
  local_deep_research/web_search_engines/search_engine_base.py,sha256=PLU_sAWhWKTOQWcv32GINuhLdIwB0sEQy-pp9oG9Ggo,9835
134
- local_deep_research/web_search_engines/search_engine_factory.py,sha256=mkIf6F-8-aooS47iqb8SanJ9shnl0UOVia8hr2xX0b0,12751
135
- local_deep_research/web_search_engines/search_engines_config.py,sha256=GmwpCT6vfeq1wrdr1R-zu6WRQ5XxyE7921HPsgGm3gI,2771
136
- local_deep_research-0.2.3.dist-info/RECORD,,
133
+ local_deep_research/web_search_engines/search_engine_factory.py,sha256=DghAkQvLKRJYl5xb9AUjUv7ydAQ4rPi-TvzrmqdyGxE,10890
134
+ local_deep_research/web_search_engines/search_engines_config.py,sha256=rgKo3UQhXov_4QxPcdzMqnAfJc5a6tGXtfnjIzKeHdQ,4584
135
+ local_deep_research-0.3.1.dist-info/RECORD,,
@@ -1,245 +0,0 @@
1
- import logging
2
- import os
3
- import platform
4
- from pathlib import Path
5
-
6
- from dotenv import load_dotenv
7
- from dynaconf import Dynaconf
8
- from platformdirs import user_documents_dir
9
-
10
- # Setup logging
11
- logger = logging.getLogger(__name__)
12
-
13
-
14
- def get_config_dir():
15
-
16
- if platform.system() == "Windows":
17
- # Windows: Use Documents directory
18
- from platformdirs import user_documents_dir
19
-
20
- config_dir = (
21
- Path(user_documents_dir()) / "LearningCircuit" / "local-deep-research"
22
- )
23
- else:
24
- # Linux/Mac: Use standard config directory
25
- from platformdirs import user_config_dir
26
-
27
- config_dir = Path(user_config_dir("local_deep_research", "LearningCircuit"))
28
-
29
- logger.info(f"Looking for config in: {config_dir}")
30
- return config_dir
31
-
32
-
33
- # Define config paths
34
- CONFIG_DIR = get_config_dir() / "config"
35
- CONFIG_DIR.mkdir(parents=True, exist_ok=True)
36
- SETTINGS_FILE = CONFIG_DIR / "settings.toml"
37
- SECRETS_FILE = CONFIG_DIR / ".secrets.toml"
38
- SEARCH_ENGINES_FILE = CONFIG_DIR / "search_engines.toml"
39
-
40
- LOCAL_COLLECTIONS_FILE = CONFIG_DIR / "local_collections.toml"
41
-
42
- # Define data directory for database
43
- DATA_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "data"))
44
- os.makedirs(DATA_DIR, exist_ok=True)
45
- DB_PATH = os.path.join(DATA_DIR, "ldr.db")
46
-
47
- env_file = CONFIG_DIR / ".env"
48
-
49
- if env_file.exists():
50
- logger.info(f"Loading environment variables from: {env_file}")
51
- load_dotenv(dotenv_path=env_file)
52
- else:
53
- logger.warning(
54
- f"Warning: .env file not found at {env_file}. Trying secondary location."
55
- )
56
- env_file_secondary = get_config_dir() / ".env"
57
- if env_file_secondary.exists():
58
- get_config_dir() / "config"
59
- logger.info(f"Loading environment variables from: {env_file_secondary}")
60
- load_dotenv(dotenv_path=env_file_secondary)
61
- else:
62
- logger.warning(f"Warning: .env file also not found at {env_file_secondary}.")
63
-
64
-
65
- # Set environment variable for Dynaconf to use
66
- docs_base = Path(user_documents_dir()) / "local_deep_research"
67
- os.environ["DOCS_DIR"] = str(docs_base)
68
-
69
-
70
- def init_config_files():
71
- """Initialize config files if they don't exist"""
72
- import os
73
- import platform
74
- import shutil
75
-
76
- # Ensure CONFIG_DIR exists with explicit creation
77
- os.makedirs(CONFIG_DIR, exist_ok=True)
78
-
79
- # Get default files path with more reliable approach for Windows
80
- if platform.system() == "Windows":
81
- # Use a more reliable method on Windows
82
- from pkg_resources import resource_filename
83
-
84
- try:
85
- defaults_dir = Path(resource_filename("local_deep_research", "defaults"))
86
- logger.info(f"Using pkg_resources for Windows: {defaults_dir}")
87
-
88
- # Create settings.toml if it doesn't exist (with explicit Windows paths)
89
- settings_file = os.path.join(CONFIG_DIR, "settings.toml")
90
- default_settings = os.path.join(defaults_dir, "main.toml")
91
- if not os.path.exists(settings_file) and os.path.exists(default_settings):
92
- shutil.copyfile(default_settings, settings_file)
93
- logger.info(f"Created settings.toml at {settings_file}")
94
- # Add note about database-first settings
95
- with open(settings_file, "a") as f:
96
- f.write(
97
- "\n\n# NOTE: Settings in this file are used as fallback only.\n"
98
- )
99
- f.write(
100
- "# Settings stored in the database (ldr.db) take precedence.\n"
101
- )
102
- f.write(
103
- "# To modify settings permanently, use the web interface settings page.\n"
104
- )
105
-
106
- # Create local_collections.toml if it doesn't exist
107
- collections_file = os.path.join(CONFIG_DIR, "local_collections.toml")
108
- default_collections = os.path.join(defaults_dir, "local_collections.toml")
109
- if not os.path.exists(collections_file) and os.path.exists(
110
- default_collections
111
- ):
112
- shutil.copyfile(default_collections, collections_file)
113
- logger.info(f"Created local_collections.toml at {collections_file}")
114
-
115
- # Create search_engines.toml if it doesn't exist
116
- search_engines_file = os.path.join(CONFIG_DIR, "search_engines.toml")
117
- default_engines = os.path.join(defaults_dir, "search_engines.toml")
118
- if not os.path.exists(search_engines_file) and os.path.exists(
119
- default_engines
120
- ):
121
- shutil.copyfile(default_engines, search_engines_file)
122
- logger.info(f"Created search_engines.toml at {search_engines_file}")
123
- # Add note about database-first settings
124
- with open(search_engines_file, "a") as f:
125
- f.write(
126
- "\n\n# NOTE: Settings in this file are used as fallback only.\n"
127
- )
128
- f.write(
129
- "# Settings stored in the database (ldr.db) take precedence.\n"
130
- )
131
- f.write(
132
- "# To modify search settings permanently, use the web interface settings page.\n"
133
- )
134
-
135
- # Create .env.template if it doesn't exist
136
- env_template_file = CONFIG_DIR / ".env.template"
137
- if not env_template_file.exists():
138
- shutil.copy(defaults_dir / ".env.template", env_template_file)
139
- logger.info(f"Created .env.template at {env_template_file}")
140
-
141
- # Optionally create an empty .env file if it doesn't exist
142
- env_file = CONFIG_DIR / ".env"
143
- if not env_file.exists():
144
- with open(env_file, "w") as f:
145
- f.write("# Add your environment variables here\n")
146
- logger.info(f"Created empty .env file at {env_file}")
147
- except Exception as e:
148
- logger.error(f"Error initializing Windows config files: {e}")
149
- else:
150
- """Initialize config files if they don't exist"""
151
- import shutil
152
- from importlib.resources import files
153
-
154
- # Get default files path
155
- try:
156
- defaults_dir = files("local_deep_research.defaults")
157
- except ImportError:
158
- # Fallback for older Python versions
159
- from pkg_resources import resource_filename
160
-
161
- defaults_dir = Path(resource_filename("local_deep_research", "defaults"))
162
-
163
- # Create settings.toml if it doesn't exist
164
- settings_file = CONFIG_DIR / "settings.toml"
165
- if not settings_file.exists():
166
- shutil.copy(defaults_dir / "main.toml", settings_file)
167
- logger.info(f"Created settings.toml at {settings_file}")
168
- # Add note about database-first settings
169
- with open(settings_file, "a") as f:
170
- f.write(
171
- "\n\n# NOTE: Settings in this file are used as fallback only.\n"
172
- )
173
- f.write("# Settings stored in the database (ldr.db) take precedence.\n")
174
- f.write(
175
- "# To modify settings permanently, use the web interface settings page.\n"
176
- )
177
-
178
- # Create local_collections.toml if it doesn't exist
179
- collections_file = CONFIG_DIR / "local_collections.toml"
180
- if not collections_file.exists():
181
- shutil.copy(defaults_dir / "local_collections.toml", collections_file)
182
- logger.info(f"Created local_collections.toml at {collections_file}")
183
-
184
- # Create search_engines.toml if it doesn't exist
185
- search_engines_file = CONFIG_DIR / "search_engines.toml"
186
- if not search_engines_file.exists():
187
- shutil.copy(defaults_dir / "search_engines.toml", search_engines_file)
188
- logger.info(f"Created search_engines.toml at {search_engines_file}")
189
- # Add note about database-first settings
190
- with open(search_engines_file, "a") as f:
191
- f.write(
192
- "\n\n# NOTE: Settings in this file are used as fallback only.\n"
193
- )
194
- f.write("# Settings stored in the database (ldr.db) take precedence.\n")
195
- f.write(
196
- "# To modify search settings permanently, use the web interface settings page.\n"
197
- )
198
-
199
- env_template_file = CONFIG_DIR / ".env.template"
200
- if not env_template_file.exists():
201
- shutil.copy(defaults_dir / ".env.template", env_template_file)
202
- logger.info(f"Created .env.template at {env_template_file}")
203
-
204
- # Optionally create an empty .env file if it doesn't exist
205
- env_file = CONFIG_DIR / ".env"
206
- if not env_file.exists():
207
- with open(env_file, "w") as f:
208
- f.write("# Add your environment variables here\n")
209
- logger.info(f"Created empty .env file at {env_file}")
210
- secrets_file = CONFIG_DIR / ".secrets.toml"
211
- if not secrets_file.exists():
212
- with open(secrets_file, "w") as f:
213
- f.write(
214
- """
215
- # ANTHROPIC_API_KEY = "your-api-key-here"
216
- # OPENAI_API_KEY = "your-openai-key-here"
217
- # GOOGLE_API_KEY = "your-google-key-here"
218
- # SERP_API_KEY = "your-api-key-here"
219
- # GUARDIAN_API_KEY = "your-api-key-here"
220
- # GOOGLE_PSE_API_KEY = "your-google-api-key-here"
221
- # GOOGLE_PSE_ENGINE_ID = "your-programmable-search-engine-id-here"
222
- """
223
- )
224
-
225
-
226
- # Add a comment to explain the DB-first settings approach
227
- logger.info(
228
- "Using database-first settings approach. TOML files are used as fallback only."
229
- )
230
-
231
- settings = Dynaconf(
232
- settings_files=[
233
- str(SETTINGS_FILE),
234
- str(LOCAL_COLLECTIONS_FILE),
235
- str(SEARCH_ENGINES_FILE),
236
- ],
237
- secrets=str(SECRETS_FILE),
238
- env_prefix="LDR",
239
- load_dotenv=True,
240
- envvar_prefix="LDR",
241
- env_file=str(CONFIG_DIR / ".env"),
242
- )
243
-
244
- # Initialize config files on import
245
- init_config_files()