""" Configuration management Loads config uniformly from the .env file at the project root """ import os from dotenv import load_dotenv # Load the .env file from the project root # Path: MiroFish/.env (relative to backend/app/config.py) project_root_env = os.path.join(os.path.dirname(__file__), '../../.env') if os.path.exists(project_root_env): load_dotenv(project_root_env, override=True) else: # If no root-level .env file found, load from environment variables (production) load_dotenv(override=True) class Config: """Flask configuration class""" # Flask settings SECRET_KEY = os.environ.get('SECRET_KEY', 'mirofish-secret-key') DEMO_PASSWORD = os.environ.get('DEMO_PASSWORD', '') DEBUG = os.environ.get('FLASK_DEBUG', 'True').lower() == 'true' # JSON settings - disable ASCII escaping so non-ASCII chars are output directly (not as \uXXXX) JSON_AS_ASCII = False # LLM settings (unified OpenAI-compatible format) LLM_API_KEY = os.environ.get('LLM_API_KEY') LLM_BASE_URL = os.environ.get('LLM_BASE_URL', 'https://api.openai.com/v1') LLM_MODEL_NAME = os.environ.get('LLM_MODEL_NAME', 'gpt-4o-mini') # Graph backend: "zep" (default, cloud) o "graphiti" (Neo4j local) GRAPH_BACKEND = os.environ.get('GRAPH_BACKEND', 'zep') # Zep Cloud ZEP_API_KEY = os.environ.get('ZEP_API_KEY') # Graphiti + Neo4j NEO4J_URI = os.environ.get('NEO4J_URI', 'bolt://localhost:7687') NEO4J_USER = os.environ.get('NEO4J_USER', 'neo4j') NEO4J_PASSWORD = os.environ.get('NEO4J_PASSWORD') # LLM provider ("" = OpenAI-compatible per defecte, "gemini" = Google AI Studio) LLM_PROVIDER = os.environ.get('LLM_PROVIDER', '') # File upload settings MAX_CONTENT_LENGTH = 50 * 1024 * 1024 # 50MB UPLOAD_FOLDER = os.path.join(os.path.dirname(__file__), '../uploads') ALLOWED_EXTENSIONS = {'pdf', 'md', 'txt', 'markdown'} # Text processing settings DEFAULT_CHUNK_SIZE = 500 # default chunk size DEFAULT_CHUNK_OVERLAP = 50 # default overlap size # OASIS simulation settings OASIS_DEFAULT_MAX_ROUNDS = int(os.environ.get('OASIS_DEFAULT_MAX_ROUNDS', '10')) OASIS_SIMULATION_DATA_DIR = os.path.join(os.path.dirname(__file__), '../uploads/simulations') # OASIS platform available actions OASIS_TWITTER_ACTIONS = [ 'CREATE_POST', 'LIKE_POST', 'REPOST', 'FOLLOW', 'DO_NOTHING', 'QUOTE_POST' ] OASIS_REDDIT_ACTIONS = [ 'LIKE_POST', 'DISLIKE_POST', 'CREATE_POST', 'CREATE_COMMENT', 'LIKE_COMMENT', 'DISLIKE_COMMENT', 'SEARCH_POSTS', 'SEARCH_USER', 'TREND', 'REFRESH', 'DO_NOTHING', 'FOLLOW', 'MUTE' ] # Report Agent settings REPORT_AGENT_MAX_TOOL_CALLS = int(os.environ.get('REPORT_AGENT_MAX_TOOL_CALLS', '5')) REPORT_AGENT_MAX_REFLECTION_ROUNDS = int(os.environ.get('REPORT_AGENT_MAX_REFLECTION_ROUNDS', '2')) REPORT_AGENT_TEMPERATURE = float(os.environ.get('REPORT_AGENT_TEMPERATURE', '0.5')) @classmethod def get_graph_config_errors(cls) -> list: errors = [] if cls.GRAPH_BACKEND == 'zep': if not cls.ZEP_API_KEY: errors.append("ZEP_API_KEY is not configured (required when GRAPH_BACKEND=zep)") elif cls.GRAPH_BACKEND == 'graphiti': if not cls.NEO4J_PASSWORD: errors.append("NEO4J_PASSWORD is not configured (required when GRAPH_BACKEND=graphiti)") else: errors.append(f"Unknown GRAPH_BACKEND value: '{cls.GRAPH_BACKEND}'. Use 'zep' or 'graphiti'.") return errors @classmethod def validate(cls): """Validate required configuration""" errors = [] if not cls.LLM_API_KEY: errors.append("LLM_API_KEY is not configured") errors.extend(cls.get_graph_config_errors()) return errors