import sys import json import asyncio from database import create_sql_engine, User, Agent from sqlalchemy.orm import Session from sqlalchemy.sql.expression import select from quart import Quart, Response, request, send_from_directory, jsonify, websocket class App: def __init__(self, data_directory): self.data_directory = data_directory self.sql_engine = create_sql_engine(self.data_directory) def sql_session(self): return Session(self.sql_engine) app = App("./") def start_server(app): server = Quart(__name__, static_folder='../frontend/build/web') @server.route('/') async def index(): return await send_from_directory(server.static_folder, 'index.html') @server.route('/') async def serve_static(path): return await send_from_directory(server.static_folder, path) @server.route('/user/signup', methods=['POST']) async def signup(): data = await request.get_json() user_id = None username = data['username'] email = data['email'] password = data['password'] with app.sql_session() as session: result = session.execute( select(User.id).where(User.email == email or User.username == username) ).first() if result is None: user = User() user.email = email user.username = username user.password = password session.add(user) session.commit() user_id = user.id print(f"Created user #{user_id}: {username} ({email})") else: user_id = None print(f"Signup error: '{email}' or '{username}' are already used") if user_id is None: return {"error": "existing credentials"} else: # token = auth_manager.dump_token(user_id) return {"userId": user_id} @server.websocket('/ws') async def ws(): print("incoming ws") # Authenticate before dedicating any resources auth_req = json.loads(await websocket.receive()) if "username" not in auth_req: print("Invalid auth request:", auth_req) await websocket.send(json.dumps({'error': 'invalid auth'})) return # TODO: Actually authenticate credentials against stored users # TODO: Get the user id from the credentials, use them in create-agent print(f"User {auth_req['username']} connected") send_queue = asyncio.Queue() async def sender_task(): nonlocal send_queue while True: msg = await send_queue.get() await websocket.send(json.dumps(msg)) async def send(msg): await send_queue.put(msg) asyncio.create_task(sender_task()) while True: req = json.loads(await websocket.receive()) action = req['action'] body = req.get('body', {}) nonce = req.get('nonce', None) if action == "ping": print("ping") await send({'content': "pong"}) elif action == "create-agent": with app.sql_session() as session: agent = Agent() agent.user_id = None agent.name = body['name'] agent.description = body['description'] agent.picture = body.get('picture') agent.kind = body['kind'] agent.data = body['data'] session.add(agent) session.commit() print(f"Created user #{agent.id}: {agent.name}") await send({'content': "agent created", 'agentId': agent.id, 'nonce': nonce}) else: print("Unknown message: " + action) server.run(debug=True) if __name__ == "__main__": if len(sys.argv) > 1: data_directory = sys.argv[1] else: print("No directory specified. Using current directory as default.") data_directory = "." app = App(data_directory) start_server(app)