diff --git a/Html/app_back.py b/Html/app_back.py deleted file mode 100644 index 246853c..0000000 --- a/Html/app_back.py +++ /dev/null @@ -1,480 +0,0 @@ -from bootstrap import bootstrap_paths -bootstrap_paths() -from functools import wraps -from flask import Flask, redirect, session, request, jsonify, render_template, send_from_directory, url_for -from flask_cors import CORS -from flask_socketio import SocketIO, join_room, emit, Namespace -import markdown -import os -import uuid -import shutil -import sys -import json -from apps.auth.decorators import require_role -parent_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) -sys.path.insert(0, parent_dir) -student_workspace_root_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '../study')) -current_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '.')) -sys.path.insert(0, current_dir) -from AlgoriAgent.projects.algoriAgent.agent_manager import AgentManager - - -import configparser - -from db.user_list import UserList -from db.user import User, load_user_from_json, create_user_json -from db.course_list import CourseList -from db.course import Course, load_course_from_json -GLOBAL_CONFIG = configparser.ConfigParser() -GLOBAL_CONFIG.read('config.ini') -VSCODE_WEB_URL = GLOBAL_CONFIG['VSCODE_WEB']['url'] -USER_DATA_DIR = GLOBAL_CONFIG['USER_DATA']['dir'] -COURSE_DATA_DIR = GLOBAL_CONFIG['COURSE_DATA']['dir'] - -app = Flask(__name__) -socketio = SocketIO(app, cors_allowed_origins="*",ping_timeout=60, ping_interval=5) -# socketio = SocketIO(app, cors_allowed_origins="http://localhost:9888") # 设置跨域支持 -import logging -app.secret_key = 'cakebaker' -app.logger.setLevel(logging.DEBUG) -# 配置 CORS -CORS(app, resources={r"/*": {"origins": VSCODE_WEB_URL},}, supports_credentials=True) - - -userid_recorder = {} # user_id&path -> session['user_id'] - -''' -Backboard -''' -from backboardManager import BackBoardManager, Backboard - -backboard_manager = BackBoardManager() -uuid2username = {} -username2uuid = {} - - - -# 定义命名空间:用于和 VSCode 插件交流 -class VSCodeNamespace(Namespace): - def on_login(self,data): - print("VSCode client connected") - print(data) - dataconfig = data['config'] - user_id = dataconfig.get('user_id') - path = dataconfig.get('path') - course_id = dataconfig.get('course_id') - lesson_id = dataconfig.get('chapter_id') - print(f"User {user_id} connected with path: {path}") - useruuid = username2uuid[user_id] - join_room(useruuid, namespace='/vscode') - if backboard_manager.get_backboard(useruuid) == None: - backboard_manager.add_backboard(useruuid,user_id, course_id, lesson_id, path) - - - def on_message(self, data): - print(f"Received from VSCode client: {data}") - dataconfig = data['config'] - realtime_response(dataconfig, data) - # emit('response', {'message': 'Config data received and connection established'}) - def on_disconnect(self, data): - print("VSCode client disconnected") - print("Disconnect reason:"+str(data)) - - -def realtime_response(config, realtime_action): - user_id = config['user_id'] - folder_path = config['path'] - useruuid = username2uuid[user_id] - bb = backboard_manager.get_backboard(useruuid) - assert type(bb) == Backboard - - bb.add_history(realtime_action) - - if realtime_action['type'] == 'workspaceFolders': - bb.file_tree = realtime_action['fileTree'] - - if realtime_action['type'] == 'activeFile': - file_path = realtime_action['filePath'] - assert type(file_path) == str - with open(f"{file_path}") as f: - bb.active_file_content = f.read() - - if realtime_action['type'] == 'paste': - file_path = realtime_action['filePath'] - assert type(file_path) == str - bb.pasted_file_path = file_path - bb.pasted_content = realtime_action['content'] - bb.active_file_path = file_path - with open(f"{file_path}") as f: - bb.active_file_content = f.read() - - - if realtime_action['type'] == 'fileEdit': - file_path = realtime_action['filePath'] - assert type(file_path) == str - bb.active_file_path = file_path - with open(f"{file_path}") as f: - bb.active_file_content = f.read() - - - - - print("config"+str(config)) - print("realtime_action"+str(realtime_action)) - pass - - -''' -Agent and Chat -''' -agent_manager = AgentManager(app = app, socketio = socketio) -user_threads = {} -import threading -from concurrent.futures import ThreadPoolExecutor, as_completed - -# 初始化线程池 -executor = ThreadPoolExecutor(max_workers=10) -class AgentNamespace(Namespace): - def on_login(self, data): - data = json.loads(data) - user = data['username'] - course_id = data['course_id'] - chapter_id = data['chapter_id'] - user_uuid = username2uuid[user] - session['user_id'] = user_uuid - print(f'User connected with session user_id: {user_uuid}') - # 从markdown、markdown_prompts、score_prompts中各读取数据folder.md并进行new_agent - with open(f'books/markdown/{course_id}/{chapter_id}.md','r',encoding='UTF-8') as fmd,\ - open(f'books/markdown_prompts/{course_id}/{chapter_id}.md','r',encoding='UTF-8')as fmdp,\ - open(f'books/score_prompts/{course_id}/{chapter_id}.md','r',encoding='UTF-8') as fsp: - markdown = fmd.read() - markdown_prompts = fmdp.read() - score_prompts = fsp.read() - user_uuid, agent = agent_manager.new_agent(course_id, chapter_id, markdown, markdown_prompts, score_prompts, id=user_uuid, - root_path=f'../../study/{user}/{course_id}/{chapter_id}') - print(user_uuid) - join_room(user_uuid, namespace='/agent') # 将该用户加入以user_id为名的room - backboard_manager.add_backboard(user_uuid, user, course_id, chapter_id, root_path=f'../../study/{user}/{course_id}/{chapter_id}') - - def on_language(self, language): - id = session.get('user_id') - agent_manager.change_language(id, language) - - def on_message(self, data): - print(f"Message from client: {data}") - id = session.get('user_id') - if (type(data)==str): - data = json.loads(data) - print(id) - if data['type'] == 'text': - res = agent_manager.invoke(id, data['data'], backboard_manager.get_backboard(id).get_info_prompt()) - print('=*='*20) - print(res.content) - reply = f"{res.content['speak']}" - with app.app_context(): - emit('message',reply, room=id, namespace='/agent') - emit('request_function',res.content['function'], room=id, namespace='/agent') - - if data['type'] == 'function': - agent_manager.function_call(id, data['data']) - - def on_initiative(self,data): - print("User active function call") - user_id = session['user_id'] - if data['name'] == 'sample_judge': - agent_manager.sample_judge(user_id, backboard_manager.get_backboard(user_id)) - if data['name'] == 'judge': - agent_manager.judge(user_id, backboard_manager.get_backboard(user_id)) - - - - def on_disconnect(self,data): - print("VSCode client disconnected") - print("Disconnect reason:"+str(data)) - - - -''' -Markdown to HTML -''' -# 配置文件路径 -MARKDOWN_DIR = 'books/markdown' # 存放 markdown 文件的文件夹 -STATIC_DIR = 'static' # 存放生成的 HTML 和图片资源的文件夹 -IMAGE_DIR = 'image' # 图片资源相对于 markdown 的位置 - - - -@app.route('/--markdown', methods=['GET']) -def convert_md(course_id, filename): - md_file_path = os.path.join(MARKDOWN_DIR,course_id, f'{filename}.md') - - if not os.path.exists(md_file_path): - return jsonify({'error': 'Markdown file not found'}), 404 - - # 读取 markdown 文件内容 - with open(md_file_path, 'r', encoding='utf-8') as file: - md_content = file.read() - - # 将 markdown 转换为 HTML - html_content = markdown.markdown(md_content) - # 插入 CSS 样式,限制图片最大宽度为 100%,高度自动调整 - html_with_styles = f""" - - - - - - - {html_content} - - - """ - # 保存 HTML 文件到 static 文件夹 - html_output_path = os.path.join(STATIC_DIR, f'{filename}.html') - with open(html_output_path, 'w', encoding='utf-8') as html_file: - html_file.write(html_with_styles) - - # 处理图片资源,将 image/xxx 文件夹拷贝到 static/image/xxx - image_source_dir = os.path.join(MARKDOWN_DIR,course_id, IMAGE_DIR, filename) - image_target_dir = os.path.join(STATIC_DIR, IMAGE_DIR, filename) - print(f"Copying image resources from {image_source_dir} to {image_target_dir}") - if os.path.exists(image_source_dir): - # 确保 static/image/xxx 目录存在 - if not os.path.exists(image_target_dir): - os.makedirs(image_target_dir) - - # 拷贝图片资源 - for image_file in os.listdir(image_source_dir): - full_image_file_path = os.path.join(image_source_dir, image_file) - if os.path.isfile(full_image_file_path): - shutil.copy(full_image_file_path, image_target_dir) - - return jsonify({'html_url': f'/static/{filename}.html'}) - -# 静态文件(HTML 和图片资源)的访问 -@app.route('/static/') -def serve_static(filename): - return send_from_directory(STATIC_DIR, filename) - - -''' -Vscode -''' -@app.route('/desktop///') -def desktop(user_id, course_id, chapter_id): - if 'user_id' not in session: - # return redirect(url_for('login')) - session['user_id'] = 'user_' + str(uuid.uuid4()) - print("user "+ user_id + "uuid is"+ session['user_id']) - username2uuid[user_id] = session['user_id'] - uuid2username[session['user_id']] = user_id - userid_recorder[user_id+'&'+course_id] = session['user_id'] - - # 在学习目录下创建一个名为 user_id_path 的文件夹 - path_dir = os.path.join(student_workspace_root_path, user_id, course_id,chapter_id) - os.makedirs(path_dir, exist_ok=True) - # 在此文件夹内部创建一个.config文件,并写入 user_id=user_id\n path=path - config_path = os.path.join(path_dir, '.config') - if GLOBAL_CONFIG['VSCODE_WEB_PATH']['is_wsl']: # 如果是在 WSL 中运行,则将路径转换为 WSL 路径 - path_dir = path_dir.replace('\\', '/') - path_dir = path_dir.replace(GLOBAL_CONFIG['VSCODE_WEB_PATH']['windows_path'] , GLOBAL_CONFIG['VSCODE_WEB_PATH']['wsl_path']) - with open(config_path, 'w', encoding='utf-8') as f: - tmpd = {'user_id': user_id, 'course_id': course_id, 'chapter_id': chapter_id, 'path': path_dir} - json.dump(tmpd, f) - print('---------------------') - print(config_path) - return render_template('desktop.html', vscode_web_url=VSCODE_WEB_URL, user_id=user_id, course_id=course_id, chapter_id=chapter_id, workspace_path=path_dir) - -@app.route('/desktop_nouser//') -def desktop_nouser(course_id, chapter_id): - if 'user_id' not in session: - return redirect(url_for('login')) - user_id = session['user_id'] - username = uuid2username[user_id] - return redirect(url_for('desktop', user_id=username, course_id=course_id, chapter_id=chapter_id)) - -@app.route('/vscode_data', methods=['POST']) -def vscode_data(): - data = request.json - config = data['config'] - realtime_response(config,data) - print(f"Received data from VSCode: {data}") - return jsonify({"status": "success", "received": data}) - - - -''' -Login - -''' -users_list = UserList() -course_list = CourseList() - - -@app.route('/register') -def register(): - return render_template('register.html') - -@app.route('/register_teacher') -def register_teacher(): - return render_template('register_teacher.html') - -@app.route('/register_teacher_post', methods=['POST']) -def register_teacher_post(): - data = request.get_json() - username = data.get('username') - password = data.get('password') - if users_list.has_user(username) is not None: - users_list.add_user(username, password, teacher=True) - create_user_json(username, USER_DATA_DIR) - return jsonify({'success': True, 'message': '注册成功'}) - else: return jsonify({'success': False, 'message': '用户已存在,请更换用户名'}) - -@app.route('/register_post', methods=['POST']) -def register_post(): - data = request.get_json() - username = data.get('username') - password = data.get('password') - if users_list.has_user(username) is not None: - users_list.add_user(username, password) - create_user_json(username, USER_DATA_DIR) - return jsonify({'success': True, 'message': '注册成功'}) - else: return jsonify({'success': False, 'message': '用户已存在,请更换用户名'}) - - -@app.route('/login') -def login(): - return render_template('login.html') - if 'user_id' not in session: - return render_template('login.html') - else: - return redirect(url_for('/')) - -@app.route('/login_post', methods=['POST']) -def login_post(): - # 获取请求的 JSON 数据 - data = request.get_json() - - username = data.get('username') - password = data.get('password') - - pswd = users_list.get_user_pswd(username) - - if pswd is None: - return jsonify({'success': False, 'message': '用户名或密码错误'}) - if pswd != password: - return jsonify({'success': False, 'message': '用户名或密码错误'}) - - session['user_id'] = 'user_' + str(uuid.uuid4()) - print("user "+ username + "uuid is"+ session['user_id']) - username2uuid[username] = session['user_id'] - uuid2username[session['user_id']] = username - return jsonify({'success': True, 'message': '登录成功'}) - -@app.route('/login_teacher_post', methods=['POST']) -def login_teacher_post(): - data = request.get_json() - username = data.get('username') - password = data.get('password') - pswd = users_list.get_user_pswd(username) - is_teacher = users_list.get_user_is_teacher(username) - if is_teacher is None or is_teacher == False: - return jsonify({'success': False, 'message': '用户名不存在或非教师账号'}) - if pswd is None: - return jsonify({'success': False, 'message': '用户名或密码错误'}) - if pswd != password: - return jsonify({'success': False, 'message': '用户名或密码错误'}) - session['user_id'] = 'user_' + str(uuid.uuid4()) - print("user "+ username + "uuid is"+ session['user_id']) - username2uuid[username] = session['user_id'] - uuid2username[session['user_id']] = username - return jsonify({'success': True, 'message': '登录成功'}) - -@app.route('/teacherboard') -@require_role(roles="teacher") -def teacherboard(): - return render_template('teacherboard.html') - - -@app.route('/logout') -def logout(): - session.pop('user_id', None) - return redirect(url_for('login')) - -@app.route('/get_session') -def get_session(): - user_session = session.get('user_id', 'default_session') - return jsonify({"session": user_session}) - - -''' -DashBoard -''' -user_id2UserClass = {} -@app.route('/dashboard') -@require_role -def dashboard(): - user_id = session['user_id'] - username = uuid2username[user_id] - if (user_id not in user_id2UserClass): - user_id2UserClass[user_id] = load_user_from_json(username, user_data_dir = USER_DATA_DIR) - user_course_data = [] - for course_id in user_id2UserClass[user_id].select_course: - course_brief_info = course_list.get_course_brief_info(course_id, load_course_from_json(course_id, course_data_dir = COURSE_DATA_DIR)) - user_course_data.append(course_brief_info) - return render_template('dashboard.html',user_data = user_id2UserClass[user_id].to_json_without_dialog(), user_course_data = json.dumps(user_course_data)) - -''' -Course -''' - -@app.route('/course/') -@require_role -def course(course_id): - c = load_course_from_json(course_id, course_data_dir = COURSE_DATA_DIR) - return render_template('course.html', course_id=course_id, course_data=c) - -@app.route('/select_course', methods=['POST']) -@require_role -def select_course(): - user = user_id2UserClass[session['user_id']] - data = request.get_json() - course_id = data.get('course_id') - if course_id: - user.select_new_course(course_id, load_course_from_json(course_id, COURSE_DATA_DIR)) - return jsonify({'success': True, 'message': '课程选择成功'}) - - -@app.route('/') -@require_role -def home_index(): - selected_courses=[] - if ('user_id' in session): - if (session['user_id'] not in user_id2UserClass): return redirect(url_for('login')) - user = user_id2UserClass[session['user_id']] - for course_id in user.select_course: - selected_courses.append(course_id) - - return render_template('index.html', courses_data = course_list, selected_courses =selected_courses) - -# 一些app辅助函数,主要提供给Agent与数据库的交互能力 - -class MyFunction: - def save_chapter_memory(self, id, course_id, lesson_id, subchapter_title, mem_list, score, is_rebuttal): - print("-=-=-=-=-=-=-=-") - print(id, course_id, lesson_id, subchapter_title, mem_list, score, is_rebuttal) - username = uuid2username[id] - u = load_user_from_json(username, user_data_dir = USER_DATA_DIR) - u.save_chapter_memory(course_id, lesson_id, subchapter_title, mem_list, score, is_rebuttal) - -app.my_function = MyFunction() -if __name__ == '__main__': - socketio.on_namespace(VSCodeNamespace('/vscode')) - socketio.on_namespace(AgentNamespace('/agent')) - socketio.run(app, host='0.0.0.0', port=5551, debug=False,allow_unsafe_werkzeug=True) -