157 lines
5.5 KiB
Python
157 lines
5.5 KiB
Python
import logging
|
|
import os
|
|
|
|
from flask import Flask, jsonify, request, url_for, session as flask_session
|
|
from werkzeug.middleware.proxy_fix import ProxyFix
|
|
import logging.config
|
|
from jinja2 import ChoiceLoader, FileSystemLoader
|
|
|
|
from common.extensions import (db, bootstrap, cors, csrf, session,
|
|
minio_client, simple_encryption, metrics, cache_manager, content_manager)
|
|
from common.models.user import Tenant, SpecialistMagicLinkTenant
|
|
from config.logging_config import configure_logging
|
|
from common.utils.errors import register_error_handlers
|
|
from common.utils.celery_utils import make_celery, init_celery
|
|
from common.utils.template_filters import register_filters
|
|
from config.config import get_config
|
|
from common.utils.chat_utils import get_default_chat_customisation
|
|
|
|
|
|
def create_app(config_file=None):
|
|
app = Flask(__name__, static_url_path='/static')
|
|
|
|
# Ensure all necessary headers are handled
|
|
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_port=1)
|
|
|
|
environment = os.getenv('FLASK_ENV', 'development')
|
|
|
|
match environment:
|
|
case 'development':
|
|
app.config.from_object(get_config('dev'))
|
|
case 'test':
|
|
app.config.from_object(get_config('test'))
|
|
case 'staging':
|
|
app.config.from_object(get_config('staging'))
|
|
case 'production':
|
|
app.config.from_object(get_config('prod'))
|
|
case _:
|
|
app.config.from_object(get_config('dev'))
|
|
|
|
app.config['SESSION_KEY_PREFIX'] = 'eveai_chat_client_'
|
|
|
|
try:
|
|
os.makedirs(app.instance_path)
|
|
except OSError:
|
|
pass
|
|
|
|
configure_logging()
|
|
logger = logging.getLogger(__name__)
|
|
|
|
logger.info("eveai_chat_client starting up")
|
|
|
|
# Register extensions
|
|
register_extensions(app)
|
|
|
|
# Configure CSRF protection
|
|
app.config['WTF_CSRF_CHECK_DEFAULT'] = False # Disable global CSRF protection
|
|
app.config['WTF_CSRF_TIME_LIMIT'] = None # Remove time limit for CSRF tokens
|
|
|
|
app.celery = make_celery(app.name, app.config)
|
|
init_celery(app.celery, app)
|
|
|
|
# Configure template loader with fallback to common/templates
|
|
try:
|
|
import os as _os
|
|
common_templates_path = _os.path.normpath(_os.path.join(app.root_path, '..', 'common', 'templates'))
|
|
app.jinja_loader = ChoiceLoader([
|
|
app.jinja_loader,
|
|
FileSystemLoader(common_templates_path),
|
|
])
|
|
app.logger.debug(f"Added common templates path: {common_templates_path}")
|
|
except Exception as e:
|
|
app.logger.error(f"Failed to configure ChoiceLoader for common templates: {e}")
|
|
|
|
# Register Blueprints
|
|
register_blueprints(app)
|
|
|
|
# Register Error Handlers (shared, profile-aware)
|
|
register_error_handlers(app, profile='chat_client')
|
|
|
|
# Register Cache Handlers
|
|
register_cache_handlers(app)
|
|
|
|
# Custom url_for function for templates
|
|
@app.context_processor
|
|
def override_url_for():
|
|
return dict(url_for=_url_for)
|
|
|
|
def _url_for(endpoint, **values):
|
|
static_url = app.config.get('STATIC_URL')
|
|
if endpoint == 'static' and static_url:
|
|
filename = values.get('filename', '')
|
|
return f"{static_url}/{filename}"
|
|
return url_for(endpoint, **values)
|
|
|
|
# Debugging settings
|
|
if app.config['DEBUG'] is True:
|
|
app.logger.setLevel(logging.DEBUG)
|
|
|
|
# Register template filters
|
|
register_filters(app)
|
|
|
|
# Always inject chat customisation for templates (safe defaults)
|
|
@app.context_processor
|
|
def inject_customisation():
|
|
try:
|
|
tm = flask_session.get('tenant_make')
|
|
options = None
|
|
if tm and isinstance(tm, dict):
|
|
options = tm.get('chat_customisation_options')
|
|
customisation = get_default_chat_customisation(options)
|
|
except Exception:
|
|
customisation = get_default_chat_customisation(None)
|
|
return {'customisation': customisation}
|
|
|
|
app.logger.info(f"EveAI Chat Client Started Successfully (PID: {os.getpid()})")
|
|
app.logger.info("-------------------------------------------------------------------------------------------------")
|
|
|
|
# @app.before_request
|
|
# def app_before_request():
|
|
# if request.path.startswith('/healthz'):
|
|
# pass
|
|
# app.logger.debug(f'App before request: {request.path} ===== Method: {request.method} =====')
|
|
# app.logger.debug(f'Full URL: {request.url}')
|
|
# app.logger.debug(f'Endpoint: {request.endpoint}')
|
|
|
|
return app
|
|
|
|
|
|
def register_extensions(app):
|
|
db.init_app(app)
|
|
bootstrap.init_app(app)
|
|
csrf.init_app(app)
|
|
cors.init_app(app)
|
|
simple_encryption.init_app(app)
|
|
session.init_app(app)
|
|
minio_client.init_app(app)
|
|
cache_manager.init_app(app)
|
|
metrics.init_app(app)
|
|
content_manager.init_app(app)
|
|
|
|
|
|
def register_blueprints(app):
|
|
from .views.chat_views import chat_bp
|
|
app.register_blueprint(chat_bp)
|
|
# Do not register local error blueprint; use shared error handlers from common
|
|
from .views.healthz_views import healthz_bp
|
|
app.register_blueprint(healthz_bp)
|
|
|
|
|
|
def register_cache_handlers(app):
|
|
from common.utils.cache.config_cache import register_config_cache_handlers
|
|
register_config_cache_handlers(cache_manager)
|
|
from common.utils.cache.crewai_processed_config_cache import register_specialist_cache_handlers
|
|
register_specialist_cache_handlers(cache_manager)
|
|
from common.utils.cache.translation_cache import register_translation_cache_handlers
|
|
register_translation_cache_handlers(cache_manager)
|