|
|
|
|
|
""" |
|
|
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 |
|
|
|
|
|
|
|
|
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) |
|
|
|
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
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") |
|
|
|
|
|
|
|
|
app = Flask(__name__, static_folder='../frontend/build') |
|
|
CORS(app) |
|
|
|
|
|
|
|
|
token_manager = TokenManager() |
|
|
marketplace = TokenMarketplace(token_manager) |
|
|
environment = Environment() |
|
|
virtual_world = VirtualWorld("AnnabanOS World", (100.0, 100.0)) |
|
|
|
|
|
|
|
|
def initialize_demo_environment(): |
|
|
"""Initialize the demo environment with agents and collectives.""" |
|
|
global environment, virtual_world, token_manager, marketplace |
|
|
|
|
|
logger.info("Initializing demo environment") |
|
|
|
|
|
|
|
|
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) |
|
|
|
|
|
|
|
|
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) |
|
|
|
|
|
|
|
|
cua = ConversationalUserAgent("Assistant") |
|
|
cua.earn_tokens(50, "Initial allocation") |
|
|
|
|
|
|
|
|
environment.register_agent(task_agent1) |
|
|
environment.register_agent(task_agent2) |
|
|
environment.register_agent(social_agent1) |
|
|
environment.register_agent(social_agent2) |
|
|
environment.register_agent(cua) |
|
|
|
|
|
|
|
|
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") |
|
|
|
|
|
|
|
|
environment.register_collective(collective) |
|
|
|
|
|
|
|
|
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": "💬"}) |
|
|
|
|
|
|
|
|
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"})) |
|
|
|
|
|
|
|
|
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})) |
|
|
|
|
|
|
|
|
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} |
|
|
) |
|
|
|
|
|
|
|
|
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}) |
|
|
|
|
|
|
|
|
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_demo_environment() |
|
|
|
|
|
|
|
|
|
|
|
@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/<agent_id>', 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/<collective_id>', 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_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_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_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 |
|
|
|
|
|
|
|
|
for _ in range(cycles): |
|
|
|
|
|
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) |
|
|
|
|
|
|
|
|
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}) |
|
|
|
|
|
|
|
|
@app.route('/', defaults={'path': ''}) |
|
|
@app.route('/<path:path>') |
|
|
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) |
|
|
|
|
|
|