# Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Unified Flask application for Sushruta Patient 360.""" import logging import os from flask import Flask, send_from_directory, jsonify from flask_cors import CORS import config from intake.routes import intake_bp from radiology.routes import radiology_bp # Configure logging logging.basicConfig( level=logging.INFO, format="%(asctime)s [%(levelname)s] %(name)s: %(message)s", handlers=[logging.StreamHandler()], ) logger = logging.getLogger(__name__) # Initialize Flask app # Point static_folder to the React build output directory app = Flask( __name__, static_folder=str(config.FRONTEND_BUILD), static_url_path="", ) # Enable CORS for all API endpoints CORS(app, resources={r"/api/*": {"origins": "*"}}) # Register blueprints app.register_blueprint(intake_bp, url_prefix="/api/intake") app.register_blueprint(radiology_bp, url_prefix="/api/radiology") # ── Serve Radiology static assets ─────────────────────────────────────────── @app.route("/static/images/") def serve_radiology_images(filename): """Serve radiology images from base static directory.""" static_images_dir = config.BASE_DIR / "static" / "images" return send_from_directory(str(static_images_dir), filename) @app.route("/static/reports/") def serve_radiology_reports(filename): """Serve raw radiology reports from base static directory.""" static_reports_dir = config.BASE_DIR / "static" / "reports" return send_from_directory(str(static_reports_dir), filename) # ── Health Check ──────────────────────────────────────────────────────────── @app.route("/api/health", methods=["GET"]) def health_check(): """Health check endpoint.""" return jsonify({ "status": "healthy", "app": "Sushruta Patient 360", "medgemma_27b_initialized": bool(config.MEDGEMMA_27B_ENDPOINT or config.HF_TOKEN), "medgemma_4b_initialized": bool(config.MEDGEMMA_4B_ENDPOINT or config.HF_TOKEN), }) # ── Serve React Frontend ──────────────────────────────────────────────────── @app.route("/", defaults={"path": ""}) @app.route("/") def serve_react(path): """Serve the index.html or assets from the React build folder.""" static_folder = str(config.FRONTEND_BUILD) # If file exists in React build folder, serve it if path and os.path.exists(os.path.join(static_folder, path)): return send_from_directory(static_folder, path) # Fallback to serving index.html for React SPA routing return send_from_directory(static_folder, "index.html") if __name__ == "__main__": port = int(os.environ.get("PORT", 7860)) logger.info("Starting Sushruta Patient 360 server on port %d...", port) app.run(host="0.0.0.0", port=port, debug=False)