Files
hsa/Html/app.py
2024-12-08 21:58:09 +08:00

242 lines
8.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from flask import Flask, session, request, jsonify, render_template, send_from_directory
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
parent_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
sys.path.insert(0, parent_dir)
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
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": "http://localhost:9888"}}, supports_credentials=True)
userid_recorder = {} # user_id&path -> session['user_id']
'''
Backboard
'''
from backboardManager import BackBoardManager, Backboard
backboard_manager = BackBoardManager()
uuid2user_id = {}
user_id2uuid = {}
# 定义命名空间:用于和 VSCode 插件交流
class VSCodeNamespace(Namespace):
def on_connect(self):
print("VSCode client connected")
def on_message(self, data):
print(f"Received from VSCode client: {data}")
data = json.loads(data)
datatype = data['type']
dataconfig = data['config']
user_id = dataconfig.get('user_id')
path = dataconfig.get('path')
print(f"User {user_id} connected with path: {path}")
emit('response', {'message': 'Config data received and connection established'})
def on_disconnect(self):
print("VSCode client disconnected")
@app.route('/backboard')
def backboard():
return jsonify({'status': 'success'})
def realtime_response(config, realtime_action):
user_id = config['user_id']
folder_path = config['path']
useruuid = user_id2uuid[user_id]
if backboard_manager.get_backboard(useruuid) == None:
backboard_manager.add_backboard(useruuid, folder_path)
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
file_path = "".join(file_path.split(f'/{user_id}/{folder_path}/')[1:])
bb.active_file_path = file_path
with open(f"../{user_id}/{folder_path}/{file_path}") as f:
bb.active_file_content = f.read()
if realtime_action['type'] == 'paste':
file_path = realtime_action['filePath']
file_path = "".join(file_path.split(f'/{user_id}/{folder_path}/')[1:])
bb.pasted_file_path = file_path
bb.pasted_content = realtime_action['content']
print("config"+str(config))
print("realtime_action"+str(realtime_action))
pass
'''
Agent and Chat
'''
agent_manager = AgentManager()
class AgentNamespace(Namespace):
def on_connect(self):
user = request.args.get('username')
folder_name = request.args.get('folder')
user_uuid = user_id2uuid[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/{folder_name}.md','r') as fmd,\
open(f'books/markdown_prompts/{folder_name}.md','r')as fmdp,\
open(f'books/score_prompts/{folder_name}.md','r') as fsp:
markdown = fmd.read()
markdown_prompts = fmdp.read()
score_prompts = fsp.read()
user_uuid, agent = agent_manager.new_agent(markdown, markdown_prompts, score_prompts, id=user_uuid)
join_room(user_uuid) # 将该用户加入以user_id为名的room
def on_message(self, data):
print(f"Message from client: {data}")
id = session.get('user_id')
print(id)
# 构造回复消息
res = agent_manager.invoke(id, data, backboard_manager.get_backboard(id).get_info_prompt())
reply = f"AI: {res.content['speak']}"
# 将回复发送回前端
emit('receive_message', reply)
def on_disconnect(self):
print("VSCode client disconnected")
'''
Markdown to HTML
'''
# 配置文件路径
MARKDOWN_DIR = 'books/markdown' # 存放 markdown 文件的文件夹
STATIC_DIR = 'static' # 存放生成的 HTML 和图片资源的文件夹
IMAGE_DIR = 'image' # 图片资源相对于 markdown 的位置
@app.route('/<filename>-markdown', methods=['GET'])
def convert_md(filename):
md_file_path = os.path.join(MARKDOWN_DIR, 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>
<head>
<style>
img {{
max-width: 100%;
height: auto;
}}
</style>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.2.0/github-markdown.min.css">
</head>
<body>
{html_content}
</body>
</html>
"""
# 保存 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, 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/<path:filename>')
def serve_static(filename):
return send_from_directory(STATIC_DIR, filename)
'''
Vscode
'''
@app.route('/desktop/<user_id>/<path>')
def hello_world(user_id, path):
if 'user_id' not in session:
session['user_id'] = 'user_' + str(uuid.uuid4())
print("user "+ user_id + "uuid is"+ session['user_id'])
user_id2uuid[user_id] = session['user_id']
uuid2user_id[session['user_id']] = user_id
userid_recorder[user_id+'&'+path] = session['user_id']
# 在上层 目录下创建一个名为 user_id_path 的文件夹
path_dir = os.path.join(parent_dir, user_id, path)
os.makedirs(path_dir, exist_ok=True)
# 在此文件夹内部创建一个.config文件并写入 user_id=user_id\n path=path
config_path = os.path.join(path_dir, '.config')
with open(config_path, 'w') as f:
f.write(f"user_id={user_id}\npath={path}")
return render_template('index.html', user_id=user_id, path=path)
@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})
@app.route('/get_session')
def get_session():
user_session = session.get('user_id', 'default_session')
return jsonify({"session": user_session})
if __name__ == '__main__':
socketio.on_namespace(VSCodeNamespace('/vscode'))
socketio.on_namespace(AgentNamespace('/agent'))
socketio.run(app, host='localhost', port=5500, debug=True)