Trae Assistant
Initial commit
76ee95f
from flask import Flask, render_template, request, jsonify, send_file
from werkzeug.exceptions import RequestEntityTooLarge
import os
import json
import datetime
app = Flask(__name__)
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 # 16MB max upload
# Data storage path
DATA_DIR = os.path.join(os.path.dirname(__file__), 'data')
os.makedirs(DATA_DIR, exist_ok=True)
@app.errorhandler(RequestEntityTooLarge)
def handle_file_too_large(e):
return jsonify({"success": False, "message": "File too large. Maximum size is 16MB."}), 413
@app.errorhandler(404)
def page_not_found(e):
return render_template('index.html'), 404
@app.route('/')
def index():
return render_template('index.html')
@app.route('/health')
def health_check():
return "OK", 200
@app.route('/api/save', methods=['POST'])
def save_project():
try:
data = request.json
if not data:
return jsonify({"success": False, "message": "No data provided"}), 400
project_name = data.get('projectName', 'untitled')
# Sanitize filename
safe_name = "".join([c for c in project_name if c.isalpha() or c.isdigit() or c in (' ', '-', '_')]).strip()
if not safe_name:
safe_name = 'untitled'
filename = f"{safe_name}.json"
filepath = os.path.join(DATA_DIR, filename)
with open(filepath, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
return jsonify({"success": True, "message": "项目已保存", "filename": filename})
except Exception as e:
return jsonify({"success": False, "message": str(e)}), 500
@app.route('/api/load', methods=['GET'])
def load_projects():
try:
if not os.path.exists(DATA_DIR):
os.makedirs(DATA_DIR, exist_ok=True)
files = [f for f in os.listdir(DATA_DIR) if f.endswith('.json')]
projects = []
for f in files:
filepath = os.path.join(DATA_DIR, f)
try:
with open(filepath, 'r', encoding='utf-8') as file:
data = json.load(file)
projects.append({
"filename": f,
"projectName": data.get('projectName', f.replace('.json', '')),
"updatedAt": datetime.datetime.fromtimestamp(os.path.getmtime(filepath)).strftime('%Y-%m-%d %H:%M:%S')
})
except:
continue
# Sort by update time desc
projects.sort(key=lambda x: x['updatedAt'], reverse=True)
return jsonify({"success": True, "projects": projects})
except Exception as e:
return jsonify({"success": False, "message": str(e)}), 500
@app.route('/api/load/<filename>', methods=['GET'])
def load_project_detail(filename):
try:
# Security check
if '..' in filename or not filename.endswith('.json'):
return jsonify({"success": False, "message": "Invalid filename"}), 400
filepath = os.path.join(DATA_DIR, filename)
if not os.path.exists(filepath):
return jsonify({"success": False, "message": "File not found"}), 404
with open(filepath, 'r', encoding='utf-8') as f:
data = json.load(f)
return jsonify({"success": True, "data": data})
except Exception as e:
return jsonify({"success": False, "message": str(e)}), 500
if __name__ == '__main__':
# Use 7860 for Hugging Face Spaces default
port = int(os.environ.get('PORT', 7860))
app.run(debug=True, host='0.0.0.0', port=port)