from flask import Blueprint, render_template, request, Response, stream_with_context, jsonify from flask_login import login_required from app.models.ai_insight import AiInsight from app.services.ai_service import stream_chat, get_latest_daily_insight, generate_daily_insight ai_bp = Blueprint('ai', __name__, url_prefix='/ai') @ai_bp.route('/') @login_required def index(): latest_insight = get_latest_daily_insight() recent_chats = AiInsight.query\ .filter_by(insight_type='chat_response')\ .order_by(AiInsight.created_at.desc())\ .limit(20).all() return render_template('ai/index.html', latest_insight=latest_insight, recent_chats=recent_chats) @ai_bp.route('/stream') @login_required def stream(): """SSE endpoint — streams Groq response chunk by chunk.""" message = request.args.get('message', '').strip() if not message: def empty(): yield 'data: Please enter a message.\n\n' yield 'data: [DONE]\n\n' return Response(stream_with_context(empty()), mimetype='text/event-stream', headers={ 'Cache-Control': 'no-cache', 'X-Accel-Buffering': 'no', }) return Response( stream_with_context(stream_chat(message)), mimetype='text/event-stream', headers={ 'Cache-Control': 'no-cache', 'X-Accel-Buffering': 'no', } ) @ai_bp.route('/generate-insight', methods=['POST']) @login_required def trigger_insight(): """Manually trigger a daily insight generation.""" content = generate_daily_insight() if content: return jsonify({'status': 'ok', 'content': content}) return jsonify({'status': 'error', 'message': 'Failed to generate insight'}), 500 @ai_bp.route('/history') @login_required def history(): page = request.args.get('page', 1, type=int) insights = AiInsight.query\ .order_by(AiInsight.created_at.desc())\ .paginate(page=page, per_page=20, error_out=False) return render_template('ai/history.html', insights=insights)