#!/usr/bin/env python3 """ AnnabanOS Enhanced - Web App Backend This script provides a Flask API for the AnnabanOS Enhanced web app. """ import os import sys import logging import json import datetime from typing import Dict, List, Any, Optional from flask import Flask, request, jsonify, send_from_directory from flask_cors import CORS # Add parent directory to path to import modules sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) # Import AnnabanOS modules from config import config from agents.base_agent import BaseAgent, Memory, Goal from agents.task_agent import TaskAgent from agents.social_agent import SocialAgent from agents.collective import AgentCollective, AgentRole, CollectiveTask from environment.environment import Environment from environment.virtual_world import VirtualWorld, VirtualLocation, VirtualObject from token_economy.token_manager import TokenManager from token_economy.marketplace import TokenMarketplace from annabanai.echo_loop import reflect, update_portfolio, get_journal_entries, get_portfolio_items from annabanai.agent_cua import ConversationalUserAgent # Configure logging logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', handlers=[ logging.StreamHandler(sys.stdout), logging.FileHandler('annabanOS_api.log') ] ) logger = logging.getLogger("annabanOS_api") # Initialize Flask app app = Flask(__name__, static_folder='../frontend/build') CORS(app) # Enable CORS for all routes # Initialize AnnabanOS components token_manager = TokenManager() marketplace = TokenMarketplace(token_manager) environment = Environment() virtual_world = VirtualWorld("AnnabanOS World", (100.0, 100.0)) # Create demo environment (similar to main.py) def initialize_demo_environment(): """Initialize the demo environment with agents and collectives.""" global environment, virtual_world, token_manager, marketplace logger.info("Initializing demo environment") # Create task agents task_agent1 = TaskAgent("TaskMaster") task_agent1.earn_tokens(100, "Initial allocation") task_agent1.learn_skill("problem_solving", 0.8) task_agent1.learn_skill("data_analysis", 0.7) task_agent1.learn_skill("planning", 0.9) task_agent2 = TaskAgent("Analyzer") task_agent2.earn_tokens(80, "Initial allocation") task_agent2.learn_skill("research", 0.9) task_agent2.learn_skill("critical_thinking", 0.8) task_agent2.learn_skill("data_visualization", 0.7) # Create social agents social_agent1 = SocialAgent("Networker") social_agent1.earn_tokens(120, "Initial allocation") social_agent1.learn_skill("communication", 0.9) social_agent1.learn_skill("empathy", 0.8) social_agent1.learn_skill("negotiation", 0.7) social_agent2 = SocialAgent("Diplomat") social_agent2.earn_tokens(90, "Initial allocation") social_agent2.learn_skill("conflict_resolution", 0.9) social_agent2.learn_skill("persuasion", 0.8) social_agent2.learn_skill("leadership", 0.7) # Create conversational agent cua = ConversationalUserAgent("Assistant") cua.earn_tokens(50, "Initial allocation") # Register agents with environment environment.register_agent(task_agent1) environment.register_agent(task_agent2) environment.register_agent(social_agent1) environment.register_agent(social_agent2) environment.register_agent(cua) # Create a collective collective = AgentCollective("Dream Team") collective.add_agent(task_agent1, "coordinator") collective.add_agent(task_agent2, "analyst") collective.add_agent(social_agent1, "creator") collective.add_agent(social_agent2, "evaluator") # Register collective with environment environment.register_collective(collective) # Add agents to virtual world virtual_world.add_agent(task_agent1.id, (20.0, 30.0), {"icon": "🧠"}) virtual_world.add_agent(task_agent2.id, (40.0, 20.0), {"icon": "📊"}) virtual_world.add_agent(social_agent1.id, (60.0, 40.0), {"icon": "🗣️"}) virtual_world.add_agent(social_agent2.id, (80.0, 70.0), {"icon": "🤝"}) virtual_world.add_agent(cua.id, (50.0, 50.0), {"icon": "💬"}) # Add locations to virtual world virtual_world.add_location(VirtualLocation("Task Hub", (30.0, 30.0), 15.0, {"type": "work"})) virtual_world.add_location(VirtualLocation("Social Center", (70.0, 50.0), 20.0, {"type": "social"})) virtual_world.add_location(VirtualLocation("Learning Zone", (50.0, 80.0), 10.0, {"type": "education"})) virtual_world.add_location(VirtualLocation("Marketplace", (20.0, 70.0), 12.0, {"type": "economic"})) virtual_world.add_location(VirtualLocation("Reflection Garden", (80.0, 20.0), 8.0, {"type": "reflection"})) # Add objects to virtual world virtual_world.add_object(VirtualObject("Knowledge Base", (25.0, 25.0), {"type": "resource", "value": 10})) virtual_world.add_object(VirtualObject("Communication Hub", (75.0, 45.0), {"type": "tool", "value": 15})) virtual_world.add_object(VirtualObject("Token Vault", (50.0, 50.0), {"type": "economic", "value": 20})) virtual_world.add_object(VirtualObject("Skill Tree", (55.0, 85.0), {"type": "education", "value": 25})) virtual_world.add_object(VirtualObject("Meditation Pool", (85.0, 15.0), {"type": "reflection", "value": 15})) # Create marketplace listings marketplace.create_listing( task_agent1.id, "Problem-Solving Service", "Expert problem-solving assistance for complex challenges", 25.0, "task_service", {"skill_level": 0.8, "duration": "1 day"} ) marketplace.create_listing( task_agent2.id, "Data Analysis Report", "Comprehensive data analysis with visualizations and insights", 40.0, "information", {"skill_level": 0.7, "format": "PDF"} ) marketplace.create_listing( social_agent1.id, "Network Introduction", "Introduction to key agents in my network", 15.0, "social_service", {"connections": 5, "quality": "high"} ) marketplace.create_listing( social_agent2.id, "Conflict Resolution", "Professional mediation and conflict resolution services", 35.0, "social_service", {"skill_level": 0.9, "success_rate": 0.95} ) # Add some reflections reflect("Starting a new day with clear objectives. My primary focus is on task coordination and ensuring efficient resource allocation.", "goal_setting", {"agent_id": task_agent1.id}) reflect("I've been analyzing patterns in recent data and noticed some interesting correlations that could inform our strategy.", "learning", {"agent_id": task_agent2.id}) reflect("Building relationships requires active listening and genuine interest in others. Today I practiced these skills with good results.", "social_interaction", {"agent_id": social_agent1.id}) reflect("Successfully mediated a disagreement by focusing on shared goals rather than points of contention.", "problem_solving", {"agent_id": social_agent2.id}) # Add some portfolio items update_portfolio("Developed a new task prioritization algorithm that improved team efficiency by 15%", "achievement", {"agent_id": task_agent1.id}) update_portfolio("Created comprehensive market analysis report with actionable insights", "project", {"agent_id": task_agent2.id}) update_portfolio("Facilitated introduction between key stakeholders that led to new partnership", "achievement", {"agent_id": social_agent1.id}) update_portfolio("Resolved critical team conflict that was blocking progress on key initiative", "achievement", {"agent_id": social_agent2.id}) logger.info("Demo environment initialized") # Initialize the demo environment initialize_demo_environment() # API Routes @app.route('/api/system/info', methods=['GET']) def get_system_info(): """Get system information.""" return jsonify({ "name": "AnnabanOS Enhanced", "version": "1.0.0", "environment": environment.to_dict(), "virtual_world": virtual_world.to_dict(), "token_economy": token_manager.to_dict(), "marketplace": marketplace.to_dict(), "config": config.get_all() }) @app.route('/api/agents', methods=['GET']) def get_agents(): """Get all agents.""" agents_data = {} for agent_id, agent in environment.agents.items(): agents_data[agent_id] = agent.to_dict() return jsonify(agents_data) @app.route('/api/agents/', methods=['GET']) def get_agent(agent_id): """Get a specific agent.""" agent = environment.get_agent_by_id(agent_id) if agent: return jsonify(agent.to_dict()) return jsonify({"error": "Agent not found"}), 404 @app.route('/api/collectives', methods=['GET']) def get_collectives(): """Get all collectives.""" collectives_data = {} for collective_id, collective in environment.collectives.items(): collectives_data[collective_id] = collective.to_dict() return jsonify(collectives_data) @app.route('/api/collectives/', methods=['GET']) def get_collective(collective_id): """Get a specific collective.""" collective = environment.collectives.get(collective_id) if collective: return jsonify(collective.to_dict()) return jsonify({"error": "Collective not found"}), 404 @app.route('/api/journal', methods=['GET']) def get_journal(): """Get journal entries.""" category = request.args.get('category') agent_id = request.args.get('agent_id') limit = request.args.get('limit') if limit: limit = int(limit) entries = get_journal_entries(category=category, agent_id=agent_id, limit=limit) return jsonify(entries) @app.route('/api/journal', methods=['POST']) def add_journal_entry(): """Add a journal entry.""" data = request.json if not data or 'content' not in data: return jsonify({"error": "Missing required fields"}), 400 content = data['content'] category = data.get('category', 'general') metadata = data.get('metadata', {}) agent_id = data.get('agent_id') entry_id = reflect(content, category, metadata, agent_id) return jsonify({"id": entry_id, "status": "success"}) @app.route('/api/portfolio', methods=['GET']) def get_portfolio(): """Get portfolio items.""" item_type = request.args.get('item_type') agent_id = request.args.get('agent_id') limit = request.args.get('limit') if limit: limit = int(limit) items = get_portfolio_items(item_type=item_type, agent_id=agent_id, limit=limit) return jsonify(items) @app.route('/api/portfolio', methods=['POST']) def add_portfolio_item(): """Add a portfolio item.""" data = request.json if not data or 'content' not in data: return jsonify({"error": "Missing required fields"}), 400 content = data['content'] item_type = data.get('item_type', 'achievement') metadata = data.get('metadata', {}) agent_id = data.get('agent_id') item_id = update_portfolio(content, item_type, metadata, agent_id) return jsonify({"id": item_id, "status": "success"}) @app.route('/api/token-economy/balances', methods=['GET']) def get_token_balances(): """Get token balances for all agents.""" balances = {} for agent_id in token_manager.balances: agent = environment.get_agent_by_id(agent_id) if agent: balances[agent_id] = { "agent_id": agent_id, "agent_name": agent.name, "balance": token_manager.get_balance(agent_id), "staked": token_manager.get_staked_amount(agent_id) } return jsonify(balances) @app.route('/api/token-economy/transactions', methods=['GET']) def get_token_transactions(): """Get token transactions.""" agent_id = request.args.get('agent_id') limit = request.args.get('limit') if limit: limit = int(limit) transactions = token_manager.get_transaction_history(agent_id=agent_id, limit=limit) return jsonify(transactions) @app.route('/api/token-economy/transfer', methods=['POST']) def transfer_tokens(): """Transfer tokens between agents.""" data = request.json if not data or 'sender_id' not in data or 'recipient_id' not in data or 'amount' not in data: return jsonify({"error": "Missing required fields"}), 400 sender_id = data['sender_id'] recipient_id = data['recipient_id'] amount = float(data['amount']) description = data.get('description', '') success = token_manager.transfer_tokens(sender_id, recipient_id, amount, description) if success: return jsonify({"status": "success"}) return jsonify({"error": "Transfer failed"}), 400 @app.route('/api/marketplace/listings', methods=['GET']) def get_marketplace_listings(): """Get marketplace listings.""" category = request.args.get('category') seller_id = request.args.get('seller_id') listings = marketplace.get_active_listings(category=category, seller_id=seller_id) return jsonify(listings) @app.route('/api/marketplace/listings', methods=['POST']) def create_marketplace_listing(): """Create a marketplace listing.""" data = request.json if not data or 'seller_id' not in data or 'title' not in data or 'description' not in data or 'price' not in data or 'category' not in data: return jsonify({"error": "Missing required fields"}), 400 seller_id = data['seller_id'] title = data['title'] description = data['description'] price = float(data['price']) category = data['category'] properties = data.get('properties', {}) listing_id = marketplace.create_listing(seller_id, title, description, price, category, properties) if listing_id: return jsonify({"id": listing_id, "status": "success"}) return jsonify({"error": "Failed to create listing"}), 400 @app.route('/api/marketplace/purchase', methods=['POST']) def purchase_listing(): """Purchase a marketplace listing.""" data = request.json if not data or 'listing_id' not in data or 'buyer_id' not in data: return jsonify({"error": "Missing required fields"}), 400 listing_id = data['listing_id'] buyer_id = data['buyer_id'] success = marketplace.purchase(listing_id, buyer_id) if success: return jsonify({"status": "success"}) return jsonify({"error": "Purchase failed"}), 400 @app.route('/api/virtual-world/map', methods=['GET']) def get_virtual_world_map(): """Get virtual world map data.""" # Agents agents_data = [] for agent_id, virtual_agent in virtual_world.virtual_agents.items(): agent = environment.get_agent_by_id(agent_id) name = agent.name if agent else "Unknown" icon = virtual_agent.get_property("icon", "🤖") agents_data.append({ "id": agent_id, "name": name, "position": virtual_agent.position, "icon": icon, "properties": virtual_agent.properties }) # Locations locations_data = [] for location_id, location in virtual_world.locations.items(): locations_data.append({ "id": location_id, "name": location.name, "position": location.position, "radius": location.radius, "properties": location.properties }) # Objects objects_data = [] for object_id, obj in virtual_world.objects.items(): objects_data.append({ "id": object_id, "name": obj.name, "position": obj.position, "properties": obj.properties }) return jsonify({ "size": virtual_world.size, "agents": agents_data, "locations": locations_data, "objects": objects_data }) @app.route('/api/virtual-world/move-agent', methods=['POST']) def move_agent(): """Move an agent in the virtual world.""" data = request.json if not data or 'agent_id' not in data or 'position' not in data: return jsonify({"error": "Missing required fields"}), 400 agent_id = data['agent_id'] position = data['position'] success = virtual_world.move_agent(agent_id, position) if success: return jsonify({"status": "success"}) return jsonify({"error": "Failed to move agent"}), 400 @app.route('/api/chat', methods=['POST']) def chat_with_agent(): """Chat with a conversational agent.""" data = request.json if not data or 'agent_id' not in data or 'message' not in data: return jsonify({"error": "Missing required fields"}), 400 agent_id = data['agent_id'] message = data['message'] metadata = data.get('metadata', {}) agent = environment.get_agent_by_id(agent_id) if agent and isinstance(agent, ConversationalUserAgent): response = agent.respond(message, metadata) return jsonify({ "agent_id": agent_id, "agent_name": agent.name, "response": response }) return jsonify({"error": "Agent not found or not a conversational agent"}), 404 @app.route('/api/simulate', methods=['POST']) def run_simulation(): """Run a simulation cycle.""" data = request.json cycles = data.get('cycles', 1) if data else 1 # Similar to run_simulation in main.py but simplified for _ in range(cycles): # Move agents randomly for agent_id in list(virtual_world.virtual_agents.keys()): if agent_id in environment.agents: new_pos = virtual_world.get_random_position() virtual_world.move_agent(agent_id, new_pos) # Generate some reflections if environment.agents: agent_id = random.choice(list(environment.agents.keys())) agent = environment.agents[agent_id] reflection = f"Reflecting on my current state and environment. I'm at position {virtual_world.virtual_agents[agent_id].position if agent_id in virtual_world.virtual_agents else 'unknown'} and have {agent.tokens:.1f} tokens." reflect(reflection, "general", {"agent_id": agent_id, "simulation": True}) return jsonify({"status": "success", "cycles": cycles}) # Serve React app @app.route('/', defaults={'path': ''}) @app.route('/') def serve(path): if path != "" and os.path.exists(app.static_folder + '/' + path): return send_from_directory(app.static_folder, path) else: return send_from_directory(app.static_folder, 'index.html') if __name__ == '__main__': app.run(debug=True, host='0.0.0.0', port=5000)