Initial implementation of autonomous Discord LLM fishbowl

Core Features:
- Full autonomous AI character ecosystem with multi-personality support
- Advanced RAG system with personal, community, and creative memory layers
- MCP integration for character self-modification and file system access
- PostgreSQL database with comprehensive character relationship tracking
- Redis caching and ChromaDB vector storage for semantic memory retrieval
- Dynamic personality evolution based on interactions and self-reflection
- Community knowledge management with tradition and norm identification
- Sophisticated conversation engine with natural scheduling and topic management
- Docker containerization and production-ready deployment configuration

Architecture:
- Multi-layer vector databases for personal, community, and creative knowledge
- Character file systems with personal and shared digital spaces
- Autonomous self-modification with safety validation and audit trails
- Memory importance scoring with time-based decay and consolidation
- Community health monitoring and cultural evolution tracking
- RAG-powered conversation context and relationship optimization

Characters can:
- Develop authentic personalities through experience-based learning
- Create and build upon original creative works and philosophical insights
- Form complex relationships with memory of past interactions
- Modify their own personality traits through self-reflection cycles
- Contribute to and learn from shared community knowledge
- Manage personal digital spaces with diaries, creative works, and reflections
- Engage in collaborative projects and community decision-making

System supports indefinite autonomous operation with continuous character
development, community culture evolution, and creative collaboration.
This commit is contained in:
2025-07-04 21:33:27 -07:00
commit f22a68afa6
42 changed files with 10456 additions and 0 deletions

247
src/main.py Normal file
View File

@@ -0,0 +1,247 @@
#!/usr/bin/env python3
"""
Discord Fishbowl - Autonomous AI Character Chat System
Main entry point for the application
"""
import asyncio
import signal
import sys
import os
from pathlib import Path
# Add src to Python path
sys.path.insert(0, str(Path(__file__).parent))
from utils.config import get_settings, validate_environment, setup_logging
from utils.logging import setup_logging_interceptor
from database.connection import init_database, create_tables, close_database
from bot.discord_client import FishbowlBot
from bot.message_handler import MessageHandler, CommandHandler
from conversation.engine import ConversationEngine
from conversation.scheduler import ConversationScheduler
from llm.client import llm_client
from rag.vector_store import vector_store_manager
from rag.community_knowledge import initialize_community_knowledge_rag
from mcp.self_modification_server import mcp_server
from mcp.file_system_server import filesystem_server
import logging
# Setup logging first
logger = setup_logging()
setup_logging_interceptor()
class FishbowlApplication:
"""Main application class"""
def __init__(self):
self.settings = None
self.conversation_engine = None
self.scheduler = None
self.discord_bot = None
self.message_handler = None
self.command_handler = None
self.shutdown_event = asyncio.Event()
# RAG and MCP systems
self.vector_store = None
self.community_knowledge = None
self.mcp_servers = []
async def initialize(self):
"""Initialize all components"""
try:
logger.info("Starting Discord Fishbowl initialization...")
# Validate environment
validate_environment()
# Load settings
self.settings = get_settings()
logger.info("Configuration loaded successfully")
# Initialize database
await init_database()
await create_tables()
logger.info("Database initialized")
# Check LLM availability
is_available = await llm_client.check_model_availability()
if not is_available:
logger.error("LLM model not available. Please check your LLM service.")
raise RuntimeError("LLM service unavailable")
logger.info(f"LLM model '{llm_client.model}' is available")
# Initialize RAG systems
logger.info("Initializing RAG systems...")
# Initialize vector store
self.vector_store = vector_store_manager
character_names = ["Alex", "Sage", "Luna", "Echo"] # From config
await self.vector_store.initialize(character_names)
logger.info("Vector store initialized")
# Initialize community knowledge RAG
self.community_knowledge = initialize_community_knowledge_rag(self.vector_store)
await self.community_knowledge.initialize(character_names)
logger.info("Community knowledge RAG initialized")
# Initialize MCP servers
logger.info("Initializing MCP servers...")
# Initialize file system server
await filesystem_server.initialize(self.vector_store, character_names)
self.mcp_servers.append(filesystem_server)
logger.info("File system MCP server initialized")
# Initialize conversation engine
self.conversation_engine = ConversationEngine()
logger.info("Conversation engine created")
# Initialize scheduler
self.scheduler = ConversationScheduler(self.conversation_engine)
logger.info("Conversation scheduler created")
# Initialize Discord bot
self.discord_bot = FishbowlBot(self.conversation_engine)
# Initialize message and command handlers
self.message_handler = MessageHandler(self.discord_bot, self.conversation_engine)
self.command_handler = CommandHandler(self.discord_bot, self.conversation_engine)
logger.info("Discord bot and handlers initialized")
logger.info("✅ All components initialized successfully")
except Exception as e:
logger.error(f"Failed to initialize application: {e}")
raise
async def start(self):
"""Start the application"""
try:
logger.info("🚀 Starting Discord Fishbowl...")
# Start conversation engine
await self.conversation_engine.initialize(self.discord_bot)
logger.info("Conversation engine started")
# Start scheduler
await self.scheduler.start()
logger.info("Conversation scheduler started")
# Start Discord bot
bot_task = asyncio.create_task(
self.discord_bot.start(self.settings.discord.token)
)
# Setup signal handlers
self._setup_signal_handlers()
logger.info("🎉 Discord Fishbowl is now running!")
logger.info("Characters will start chatting autonomously...")
# Wait for shutdown signal or bot completion
done, pending = await asyncio.wait(
[bot_task, asyncio.create_task(self.shutdown_event.wait())],
return_when=asyncio.FIRST_COMPLETED
)
# Cancel pending tasks
for task in pending:
task.cancel()
try:
await task
except asyncio.CancelledError:
pass
except Exception as e:
logger.error(f"Error during application startup: {e}")
raise
async def shutdown(self):
"""Graceful shutdown"""
try:
logger.info("🛑 Shutting down Discord Fishbowl...")
# Stop scheduler
if self.scheduler:
await self.scheduler.stop()
logger.info("Conversation scheduler stopped")
# Stop conversation engine
if self.conversation_engine:
await self.conversation_engine.stop()
logger.info("Conversation engine stopped")
# Close Discord bot
if self.discord_bot:
await self.discord_bot.close()
logger.info("Discord bot disconnected")
# Close database connections
await close_database()
logger.info("Database connections closed")
logger.info("✅ Shutdown completed successfully")
except Exception as e:
logger.error(f"Error during shutdown: {e}")
def _setup_signal_handlers(self):
"""Setup signal handlers for graceful shutdown"""
def signal_handler(signum, frame):
logger.info(f"Received signal {signum}, initiating shutdown...")
self.shutdown_event.set()
# Handle common shutdown signals
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
# On Windows, handle CTRL+C
if os.name == 'nt':
signal.signal(signal.SIGBREAK, signal_handler)
async def main():
"""Main entry point"""
app = FishbowlApplication()
try:
# Initialize application
await app.initialize()
# Start application
await app.start()
except KeyboardInterrupt:
logger.info("Received keyboard interrupt")
except Exception as e:
logger.error(f"Application error: {e}")
return 1
finally:
# Ensure cleanup
await app.shutdown()
return 0
def cli_main():
"""CLI entry point"""
try:
# Check Python version
if sys.version_info < (3, 8):
print("Error: Python 3.8 or higher is required")
return 1
# Run the async main function
return asyncio.run(main())
except KeyboardInterrupt:
print("\nApplication interrupted by user")
return 1
except Exception as e:
print(f"Fatal error: {e}")
return 1
if __name__ == "__main__":
sys.exit(cli_main())