diff --git a/src/khoj/configure.py b/src/khoj/configure.py index 18c5ac8a..087245f8 100644 --- a/src/khoj/configure.py +++ b/src/khoj/configure.py @@ -37,23 +37,40 @@ from khoj.search_filter.file_filter import FileFilter logger = logging.getLogger(__name__) -def configure_server(args, required=False): - if args.config is None: - if required: - logger.error( - f"Exiting as Khoj is not configured.\nConfigure it via http://localhost:42110/config or by editing {state.config_file}." - ) - sys.exit(1) - else: - logger.warning( - f"Khoj is not configured.\nConfigure it via http://localhost:42110/config, plugins or by editing {state.config_file}." - ) - return - else: - state.config = args.config +def initialize_server( + config: Optional[FullConfig], regenerate: bool, type: Optional[SearchType] = None, required=False +): + if config is None and required: + logger.error( + f"🚨 Exiting as Khoj is not configured.\nConfigure it via http://localhost:42110/config or by editing {state.config_file}." + ) + sys.exit(1) + elif config is None: + logger.warning( + f"🚨 Khoj is not configured.\nConfigure it via http://localhost:42110/config, plugins or by editing {state.config_file}." + ) + return None + + try: + configure_server(config, regenerate, type) + except Exception as e: + logger.error(f"🚨 Failed to configure server on app load: {e}") + raise e + + +def configure_server(config: FullConfig, regenerate: bool, search_type: Optional[SearchType] = None): + # Update Config + state.config = config # Initialize Processor from Config - state.processor_config = configure_processor(args.config.processor) + try: + state.search_index_lock.acquire() + state.processor_config = configure_processor(state.config.processor) + except Exception as e: + logger.error(f"🚨 Failed to configure processor") + raise e + finally: + state.search_index_lock.release() # Initialize Search Models from Config try: @@ -61,7 +78,8 @@ def configure_server(args, required=False): state.SearchType = configure_search_types(state.config) state.search_models = configure_search(state.search_models, state.config.search_type) except Exception as e: - logger.error(f"🚨 Error configuring search models on app load: {e}") + logger.error(f"🚨 Failed to configure search models") + raise e finally: state.search_index_lock.release() @@ -70,10 +88,11 @@ def configure_server(args, required=False): try: state.search_index_lock.acquire() state.content_index = configure_content( - state.content_index, state.config.content_type, state.search_models, args.regenerate + state.content_index, state.config.content_type, state.search_models, regenerate, search_type ) except Exception as e: - logger.error(f"🚨 Error configuring content index on app load: {e}") + logger.error(f"🚨 Failed to index content") + raise e finally: state.search_index_lock.release() @@ -118,10 +137,10 @@ def configure_search_types(config: FullConfig): return Enum("SearchType", merge_dicts(core_search_types, plugin_search_types)) -def configure_search(search_models: SearchModels, search_config: SearchConfig) -> Optional[SearchModels]: +def configure_search(search_models: SearchModels, search_config: Optional[SearchConfig]) -> Optional[SearchModels]: # Run Validation Checks if search_config is None: - logger.warning("🚨 No Search type is configured.") + logger.warning("🚨 No Search configuration available.") return None if search_models is None: search_models = SearchModels() @@ -147,7 +166,7 @@ def configure_content( ) -> Optional[ContentIndex]: # Run Validation Checks if content_config is None: - logger.warning("🚨 No Content type is configured.") + logger.warning("🚨 No Content configuration available.") return None if content_index is None: content_index = ContentIndex() @@ -242,9 +261,10 @@ def configure_content( return content_index -def configure_processor(processor_config: ProcessorConfig): +def configure_processor(processor_config: Optional[ProcessorConfig]): if not processor_config: - return + logger.warning("🚨 No Processor configuration available.") + return None processor = ProcessorConfigModel() diff --git a/src/khoj/main.py b/src/khoj/main.py index 1e4d407d..5b24bc05 100644 --- a/src/khoj/main.py +++ b/src/khoj/main.py @@ -27,7 +27,7 @@ from rich.logging import RichHandler import schedule # Internal Packages -from khoj.configure import configure_routes, configure_server +from khoj.configure import configure_routes, initialize_server from khoj.utils import state from khoj.utils.cli import cli from khoj.interface.desktop.main_window import MainWindow @@ -75,7 +75,7 @@ def run(): poll_task_scheduler() # Start Server - configure_server(args, required=False) + initialize_server(args.config, args.regenerate, required=False) configure_routes(app) start_server(app, host=args.host, port=args.port, socket=args.socket) else: @@ -93,7 +93,7 @@ def run(): tray.show() # Setup Server - configure_server(args, required=False) + initialize_server(args.config, args.regenerate, required=False) configure_routes(app) server = ServerThread(app, args.host, args.port, args.socket) diff --git a/src/khoj/routers/api.py b/src/khoj/routers/api.py index 50e8e1f2..0269987d 100644 --- a/src/khoj/routers/api.py +++ b/src/khoj/routers/api.py @@ -5,20 +5,20 @@ import time import yaml import logging import json -from typing import List, Optional, Union +from typing import Iterable, List, Optional, Union # External Packages from fastapi import APIRouter, HTTPException, Header, Request from sentence_transformers import util # Internal Packages -from khoj.configure import configure_content, configure_processor, configure_search +from khoj.configure import configure_processor, configure_server from khoj.search_type import image_search, text_search from khoj.search_filter.date_filter import DateFilter from khoj.search_filter.file_filter import FileFilter from khoj.search_filter.word_filter import WordFilter from khoj.utils.config import TextSearchModel -from khoj.utils.helpers import log_telemetry, timer +from khoj.utils.helpers import timer from khoj.utils.rawconfig import ( ContentConfig, FullConfig, @@ -524,34 +524,26 @@ def update( referer: Optional[str] = Header(None), host: Optional[str] = Header(None), ): + if not state.config: + error_msg = f"🚨 Khoj is not configured.\nConfigure it via http://localhost:42110/config, plugins or by editing {state.config_file}." + logger.warning(error_msg) + raise HTTPException(status_code=500, detail=error_msg) try: - state.search_index_lock.acquire() - try: - if state.config and state.config.search_type: - state.search_models = configure_search(state.search_models, state.config.search_type) - if state.search_models: - state.content_index = configure_content( - state.content_index, state.config.content_type, state.search_models, regenerate=force or False, t=t - ) - except Exception as e: - logger.error(e) - raise HTTPException(status_code=500, detail=str(e)) - finally: - state.search_index_lock.release() - except ValueError as e: - logger.error(e) - raise HTTPException(status_code=500, detail=str(e)) + configure_server(state.config, regenerate=force or False, search_type=t) + except Exception as e: + error_msg = f"🚨 Failed to update server via API: {e}" + logger.error(error_msg) + raise HTTPException(status_code=500, detail=error_msg) else: - logger.info("📬 Search index updated via API") - - try: - if state.config and state.config.processor: - state.processor_config = configure_processor(state.config.processor) - except ValueError as e: - logger.error(e) - raise HTTPException(status_code=500, detail=str(e)) - else: - logger.info("📬 Processor reconfigured via API") + components = [] + if state.search_models: + components.append("Search models") + if state.content_index: + components.append("Content index") + if state.processor_config: + components.append("Conversation processor") + components_msg = ", ".join(components) + logger.info(f"📬 {components_msg} updated via API") update_telemetry_state( request=request,