Spaces:
Paused
Paused
Commit ·
157e65c
1
Parent(s): 6fd66df
new deign
Browse files- .claude/settings.local.json +5 -1
- CLAUDE.md +115 -23
- CLAUDE_SVELTE_FRONTEND_GUIDE.md +186 -0
- README.md +95 -3
- app.py +436 -150
- frontend/app.html +12 -0
- frontend/frontend/.gitignore +23 -0
- frontend/frontend/.npmrc +1 -0
- frontend/frontend/README.md +38 -0
- frontend/frontend/package.json +23 -0
- frontend/frontend/src/app.d.ts +13 -0
- frontend/frontend/src/app.html +12 -0
- frontend/frontend/src/routes/+page.svelte +2 -0
- frontend/frontend/static/favicon.png +0 -0
- frontend/frontend/svelte.config.js +18 -0
- frontend/frontend/tsconfig.json +19 -0
- frontend/frontend/vite.config.ts +6 -0
- frontend/package.json +31 -0
- frontend/postcss.config.js +6 -0
- frontend/src/app.css +153 -0
- frontend/src/routes/+layout.svelte +5 -0
- frontend/src/routes/+page.svelte +14 -0
- frontend/svelte.config.js +14 -0
- frontend/tailwind.config.js +58 -0
- frontend/tsconfig.json +13 -0
- frontend/vite.config.ts +18 -0
- requirements.txt +1 -0
.claude/settings.local.json
CHANGED
|
@@ -7,7 +7,11 @@
|
|
| 7 |
"WebFetch(domain:huggingface.co)",
|
| 8 |
"WebFetch(domain:huggingface.co)",
|
| 9 |
"WebFetch(domain:huggingface.co)",
|
| 10 |
-
"Bash(rm:*)"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
],
|
| 12 |
"deny": []
|
| 13 |
}
|
|
|
|
| 7 |
"WebFetch(domain:huggingface.co)",
|
| 8 |
"WebFetch(domain:huggingface.co)",
|
| 9 |
"WebFetch(domain:huggingface.co)",
|
| 10 |
+
"Bash(rm:*)",
|
| 11 |
+
"Bash(ls:*)",
|
| 12 |
+
"Bash(find:*)",
|
| 13 |
+
"Bash(npm create:*)",
|
| 14 |
+
"Bash(npx sv@latest create:*)"
|
| 15 |
],
|
| 16 |
"deny": []
|
| 17 |
}
|
CLAUDE.md
CHANGED
|
@@ -4,51 +4,102 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|
| 4 |
|
| 5 |
## Project Overview
|
| 6 |
|
| 7 |
-
DigiPal is an advanced AI-powered virtual monster companion application built with Gradio 5.34.2, featuring deep AI conversations using Qwen 2.5 models, comprehensive monster care systems,
|
| 8 |
|
| 9 |
## Architecture
|
| 10 |
|
| 11 |
### Core Technologies
|
| 12 |
- **Frontend**: Gradio 5.34.2 with custom CSS and streaming support
|
| 13 |
- **AI Models**: Qwen 2.5-1.5B-Instruct for conversations, Faster Whisper for speech
|
|
|
|
| 14 |
- **Framework**: Python 3.11+ with asyncio for concurrent operations
|
| 15 |
- **Database**: SQLite for monster persistence with async operations
|
| 16 |
-
- **Deployment**: Hugging Face Spaces with Zero GPU optimization
|
| 17 |
|
| 18 |
### Component Structure
|
| 19 |
```
|
| 20 |
src/
|
| 21 |
-
├── ai/
|
| 22 |
-
│ ├── qwen_processor.py
|
| 23 |
-
│ └── speech_engine.py
|
| 24 |
-
├── core/
|
| 25 |
-
│ ├── monster_engine.py
|
| 26 |
-
│
|
| 27 |
-
├──
|
| 28 |
-
│ ├──
|
| 29 |
-
│ └──
|
| 30 |
-
├──
|
| 31 |
-
│
|
| 32 |
-
|
| 33 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
```
|
| 35 |
|
| 36 |
## Development Commands
|
| 37 |
|
|
|
|
| 38 |
```bash
|
| 39 |
-
# Run the
|
| 40 |
python app.py
|
| 41 |
|
| 42 |
# Run with debug logging
|
| 43 |
LOG_LEVEL=DEBUG python app.py
|
| 44 |
|
| 45 |
# Run with specific configuration
|
| 46 |
-
SERVER_PORT=8080 SHARE=true python app.py
|
| 47 |
|
| 48 |
-
#
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
```
|
| 53 |
|
| 54 |
## Key Implementation Details
|
|
@@ -59,6 +110,7 @@ ruff src/ # Linting
|
|
| 59 |
- **Evolution stages**: egg → baby → child → adult → champion → ultimate
|
| 60 |
- **Complex evolution requirements**: age, level, care quality, training, battles, social interaction
|
| 61 |
- **Personality types**: friendly, energetic, calm, curious, brave with stat modifiers
|
|
|
|
| 62 |
|
| 63 |
### AI Conversation System
|
| 64 |
- **Qwen 2.5 integration** with quantization support (8-bit) for GPU efficiency
|
|
@@ -67,6 +119,13 @@ ruff src/ # Linting
|
|
| 67 |
- **Conversation history management** with automatic truncation
|
| 68 |
- **Flash Attention 2** optimization when available
|
| 69 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 70 |
### State Management
|
| 71 |
- **Async SQLite operations** for monster persistence
|
| 72 |
- **Browser state management** for session continuity
|
|
@@ -95,17 +154,27 @@ CREATE TABLE monsters (
|
|
| 95 |
|
| 96 |
## Environment Variables
|
| 97 |
|
| 98 |
-
|
| 99 |
- `LOG_LEVEL`: Logging level (DEBUG, INFO, WARNING, ERROR)
|
| 100 |
- `SERVER_NAME`: Server hostname (default: 0.0.0.0)
|
| 101 |
- `SERVER_PORT`: Server port (default: 7860)
|
| 102 |
- `SHARE`: Enable public sharing (true/false)
|
| 103 |
- `DEBUG`: Enable debug mode (true/false)
|
| 104 |
- `MAX_THREADS`: Maximum Gradio threads (default: 40)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 105 |
- `CUDA_VISIBLE_DEVICES`: GPU device selection
|
| 106 |
- `TRANSFORMERS_CACHE`: Model cache directory
|
| 107 |
- `HF_HOME`: HuggingFace cache directory
|
| 108 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 109 |
## Hugging Face Space Configuration
|
| 110 |
|
| 111 |
Configured as a Gradio Space with:
|
|
@@ -134,4 +203,27 @@ Key ZeroGPU considerations:
|
|
| 134 |
- Decorators applied at function level, not class level
|
| 135 |
- Duration specified based on expected GPU usage time
|
| 136 |
- Fallback to CPU operations when GPU not available
|
| 137 |
-
- Wrapper functions handle Spaces environment detection
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
|
| 5 |
## Project Overview
|
| 6 |
|
| 7 |
+
DigiPal is an advanced AI-powered virtual monster companion application built with Gradio 5.34.2, featuring deep AI conversations using Qwen 2.5 models, comprehensive monster care systems, sophisticated evolution mechanics, and 3D model generation capabilities. This is a complex multi-component system designed for deployment on Hugging Face Spaces with Zero GPU optimization.
|
| 8 |
|
| 9 |
## Architecture
|
| 10 |
|
| 11 |
### Core Technologies
|
| 12 |
- **Frontend**: Gradio 5.34.2 with custom CSS and streaming support
|
| 13 |
- **AI Models**: Qwen 2.5-1.5B-Instruct for conversations, Faster Whisper for speech
|
| 14 |
+
- **3D Pipeline**: Hunyuan3D and open-source alternatives for 3D model generation
|
| 15 |
- **Framework**: Python 3.11+ with asyncio for concurrent operations
|
| 16 |
- **Database**: SQLite for monster persistence with async operations
|
| 17 |
+
- **Deployment**: Hugging Face Spaces with Zero GPU optimization, Docker support
|
| 18 |
|
| 19 |
### Component Structure
|
| 20 |
```
|
| 21 |
src/
|
| 22 |
+
├── ai/ # AI processing components
|
| 23 |
+
│ ├── qwen_processor.py # Qwen 2.5 conversation engine
|
| 24 |
+
│ └── speech_engine.py # Whisper speech recognition
|
| 25 |
+
├── core/ # Core game logic
|
| 26 |
+
│ ├── monster_engine.py # Monster stats, evolution, persistence
|
| 27 |
+
│ ├── monster_engine_dw1.py # DW1-aligned monster mechanics
|
| 28 |
+
│ ├── evolution_system.py # Evolution mechanics
|
| 29 |
+
│ ├── monster_3d_integration.py # 3D model integration
|
| 30 |
+
│ └── monster_3d_hunyuan_integration.py # Hunyuan3D specific integration
|
| 31 |
+
├── pipelines/ # 3D generation pipelines
|
| 32 |
+
│ ├── hunyuan3d_pipeline.py # Hunyuan3D integration
|
| 33 |
+
│ ├── opensource_3d_pipeline.py # Open-source 3D with MCP support
|
| 34 |
+
│ ├── opensource_3d_pipeline_v2.py # Enhanced 3D pipeline
|
| 35 |
+
│ └── text_to_3d_pipeline.py # Text-to-3D abstraction
|
| 36 |
+
├── ui/ # User interface
|
| 37 |
+
│ ├── gradio_interface.py # Main Gradio interface
|
| 38 |
+
│ ├── gradio_interface_v2.py # V2 interface with 3D features
|
| 39 |
+
│ └── state_manager.py # Browser state management
|
| 40 |
+
├── deployment/ # Deployment optimization
|
| 41 |
+
│ └── zero_gpu_optimizer.py # Zero GPU resource management
|
| 42 |
+
└── utils/ # Utilities
|
| 43 |
+
└── performance_tracker.py # Performance monitoring
|
| 44 |
```
|
| 45 |
|
| 46 |
## Development Commands
|
| 47 |
|
| 48 |
+
### Running the Application
|
| 49 |
```bash
|
| 50 |
+
# Run the unified backend with API server
|
| 51 |
python app.py
|
| 52 |
|
| 53 |
# Run with debug logging
|
| 54 |
LOG_LEVEL=DEBUG python app.py
|
| 55 |
|
| 56 |
# Run with specific configuration
|
| 57 |
+
SERVER_PORT=8080 API_PORT=8081 SHARE=true python app.py
|
| 58 |
|
| 59 |
+
# Run with MCP enabled
|
| 60 |
+
MCP_ENDPOINT=https://your-mcp-server MCP_API_KEY=your-key python app.py
|
| 61 |
+
```
|
| 62 |
+
|
| 63 |
+
### Running the Svelte Frontend
|
| 64 |
+
```bash
|
| 65 |
+
# Navigate to frontend directory
|
| 66 |
+
cd frontend
|
| 67 |
+
|
| 68 |
+
# Install dependencies (first time only)
|
| 69 |
+
npm install
|
| 70 |
+
|
| 71 |
+
# Run development server
|
| 72 |
+
npm run dev
|
| 73 |
+
|
| 74 |
+
# Build for production
|
| 75 |
+
npm run build
|
| 76 |
+
|
| 77 |
+
# Preview production build
|
| 78 |
+
npm run preview
|
| 79 |
+
```
|
| 80 |
+
|
| 81 |
+
### Docker Development
|
| 82 |
+
```bash
|
| 83 |
+
# Build Docker image
|
| 84 |
+
docker build -t digipal .
|
| 85 |
+
|
| 86 |
+
# Run Docker container
|
| 87 |
+
docker run -p 7860:7860 digipal
|
| 88 |
+
|
| 89 |
+
# Run with volume mounting for data persistence
|
| 90 |
+
docker run -p 7860:7860 -v $(pwd)/data:/app/data digipal
|
| 91 |
+
```
|
| 92 |
+
|
| 93 |
+
### Development Tools
|
| 94 |
+
```bash
|
| 95 |
+
# Code formatting (requires black installation)
|
| 96 |
+
black src/
|
| 97 |
+
|
| 98 |
+
# Linting (requires ruff installation)
|
| 99 |
+
ruff src/
|
| 100 |
+
|
| 101 |
+
# Testing (test suite not yet implemented)
|
| 102 |
+
pytest
|
| 103 |
```
|
| 104 |
|
| 105 |
## Key Implementation Details
|
|
|
|
| 110 |
- **Evolution stages**: egg → baby → child → adult → champion → ultimate
|
| 111 |
- **Complex evolution requirements**: age, level, care quality, training, battles, social interaction
|
| 112 |
- **Personality types**: friendly, energetic, calm, curious, brave with stat modifiers
|
| 113 |
+
- **DW1 alignment**: Optional mode following Digimon World 1 mechanics
|
| 114 |
|
| 115 |
### AI Conversation System
|
| 116 |
- **Qwen 2.5 integration** with quantization support (8-bit) for GPU efficiency
|
|
|
|
| 119 |
- **Conversation history management** with automatic truncation
|
| 120 |
- **Flash Attention 2** optimization when available
|
| 121 |
|
| 122 |
+
### 3D Generation Pipeline
|
| 123 |
+
- **Multiple model providers**: Hunyuan3D, open-source models via Hugging Face, MCP protocol
|
| 124 |
+
- **Text-to-3D conversion**: Generate 3D models from text descriptions
|
| 125 |
+
- **Model caching**: Efficient reuse of generated 3D assets
|
| 126 |
+
- **Async generation**: Non-blocking 3D model creation
|
| 127 |
+
- **MCP integration**: Access to external model services via Model Context Protocol
|
| 128 |
+
|
| 129 |
### State Management
|
| 130 |
- **Async SQLite operations** for monster persistence
|
| 131 |
- **Browser state management** for session continuity
|
|
|
|
| 154 |
|
| 155 |
## Environment Variables
|
| 156 |
|
| 157 |
+
### Core Configuration
|
| 158 |
- `LOG_LEVEL`: Logging level (DEBUG, INFO, WARNING, ERROR)
|
| 159 |
- `SERVER_NAME`: Server hostname (default: 0.0.0.0)
|
| 160 |
- `SERVER_PORT`: Server port (default: 7860)
|
| 161 |
- `SHARE`: Enable public sharing (true/false)
|
| 162 |
- `DEBUG`: Enable debug mode (true/false)
|
| 163 |
- `MAX_THREADS`: Maximum Gradio threads (default: 40)
|
| 164 |
+
|
| 165 |
+
### Feature Toggles (V2)
|
| 166 |
+
- `ENABLE_3D`: Enable 3D generation features (default: true)
|
| 167 |
+
- `ENABLE_AI`: Enable AI conversation features (default: true)
|
| 168 |
+
|
| 169 |
+
### GPU Configuration
|
| 170 |
- `CUDA_VISIBLE_DEVICES`: GPU device selection
|
| 171 |
- `TRANSFORMERS_CACHE`: Model cache directory
|
| 172 |
- `HF_HOME`: HuggingFace cache directory
|
| 173 |
|
| 174 |
+
### MCP Configuration
|
| 175 |
+
- `MCP_ENDPOINT`: MCP service endpoint URL
|
| 176 |
+
- `MCP_API_KEY`: MCP service authentication key
|
| 177 |
+
|
| 178 |
## Hugging Face Space Configuration
|
| 179 |
|
| 180 |
Configured as a Gradio Space with:
|
|
|
|
| 203 |
- Decorators applied at function level, not class level
|
| 204 |
- Duration specified based on expected GPU usage time
|
| 205 |
- Fallback to CPU operations when GPU not available
|
| 206 |
+
- Wrapper functions handle Spaces environment detection
|
| 207 |
+
|
| 208 |
+
## MCP (Model Context Protocol) Integration
|
| 209 |
+
|
| 210 |
+
DigiPal supports MCP for flexible model deployment:
|
| 211 |
+
- **ModelProvider enum**: Includes MCP alongside HUGGINGFACE, LOCAL, and SPACES
|
| 212 |
+
- **MCPFluxWrapper**: Integrates Flux text-to-image models through MCP
|
| 213 |
+
- **Configuration options**: MCP endpoint and API key support
|
| 214 |
+
- **Server mode**: Gradio interface can run as an MCP server
|
| 215 |
+
|
| 216 |
+
## Project Architecture
|
| 217 |
+
|
| 218 |
+
### Backend
|
| 219 |
+
- **Unified app.py**: FastAPI server on port 7861 with all features enabled
|
| 220 |
+
- **Gradio Admin**: Running on port 7860 as fallback/admin interface
|
| 221 |
+
- **WebSocket Support**: Real-time updates for stats and model changes
|
| 222 |
+
|
| 223 |
+
### Frontend
|
| 224 |
+
- **SvelteKit Application**: Located in `/frontend` directory
|
| 225 |
+
- **Voice-First UI**: DigiVice-style interface with voice commands
|
| 226 |
+
- **3D Rendering**: Using Threlte for monster visualization
|
| 227 |
+
- **Cyberpunk-Retro Theme**: Custom styling with neon effects
|
| 228 |
+
|
| 229 |
+
See [CLAUDE_SVELTE_FRONTEND_GUIDE.md](CLAUDE_SVELTE_FRONTEND_GUIDE.md) for detailed frontend documentation.
|
CLAUDE_SVELTE_FRONTEND_GUIDE.md
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# **Claude Development Guide: DigiPal Svelte Frontend**
|
| 2 |
+
|
| 3 |
+
This document outlines the plan for the complete UI overhaul of DigiPal, moving from Gradio to a custom SvelteKit application with voice-first interaction.
|
| 4 |
+
|
| 5 |
+
## **Status: Implementation Complete ✅**
|
| 6 |
+
|
| 7 |
+
All major components have been implemented:
|
| 8 |
+
- ✅ Unified backend with FastAPI + WebSocket support
|
| 9 |
+
- ✅ SvelteKit frontend structure
|
| 10 |
+
- ✅ Voice-first interaction system
|
| 11 |
+
- ✅ DigiVice-style UI components
|
| 12 |
+
- ✅ 3D rendering with Threlte
|
| 13 |
+
- ✅ MCP integration
|
| 14 |
+
- ✅ Real-time WebSocket updates
|
| 15 |
+
- ✅ Cyberpunk-retro styling
|
| 16 |
+
|
| 17 |
+
## **1. Project Architecture**
|
| 18 |
+
|
| 19 |
+
### **Backend (Python)**
|
| 20 |
+
- **Main Application**: `app.py` - Unified application with all features enabled
|
| 21 |
+
- **API Server**: FastAPI on port 7861
|
| 22 |
+
- **Gradio Admin**: Running on port 7860 as fallback/admin interface
|
| 23 |
+
- **WebSocket**: Real-time stat updates and model changes
|
| 24 |
+
- **MCP Support**: Configurable via environment variables
|
| 25 |
+
|
| 26 |
+
### **Frontend (SvelteKit)**
|
| 27 |
+
Located in `/frontend` directory:
|
| 28 |
+
- **Framework**: SvelteKit with TypeScript
|
| 29 |
+
- **3D Rendering**: Threlte (Three.js wrapper for Svelte)
|
| 30 |
+
- **Styling**: Tailwind CSS with custom cyberpunk-retro theme
|
| 31 |
+
- **Voice**: Web Speech API with intent parsing
|
| 32 |
+
- **State**: Svelte stores for reactive state management
|
| 33 |
+
|
| 34 |
+
## **2. Running the Application**
|
| 35 |
+
|
| 36 |
+
### **Backend Setup**
|
| 37 |
+
```bash
|
| 38 |
+
# Install Python dependencies
|
| 39 |
+
pip install -r requirements.txt
|
| 40 |
+
|
| 41 |
+
# Run the unified backend
|
| 42 |
+
python app.py
|
| 43 |
+
|
| 44 |
+
# Or with MCP enabled
|
| 45 |
+
MCP_ENDPOINT=https://your-mcp-endpoint MCP_API_KEY=your-key python app.py
|
| 46 |
+
```
|
| 47 |
+
|
| 48 |
+
### **Frontend Setup**
|
| 49 |
+
```bash
|
| 50 |
+
# Navigate to frontend directory
|
| 51 |
+
cd frontend
|
| 52 |
+
|
| 53 |
+
# Install dependencies
|
| 54 |
+
npm install
|
| 55 |
+
|
| 56 |
+
# Run development server
|
| 57 |
+
npm run dev
|
| 58 |
+
|
| 59 |
+
# Build for production
|
| 60 |
+
npm run build
|
| 61 |
+
```
|
| 62 |
+
|
| 63 |
+
## **3. API Endpoints**
|
| 64 |
+
|
| 65 |
+
The backend exposes these REST endpoints on port 7861:
|
| 66 |
+
|
| 67 |
+
- `GET /api/monsters` - List all monsters
|
| 68 |
+
- `POST /api/monsters` - Create new monster
|
| 69 |
+
- `GET /api/monsters/{id}` - Get monster details
|
| 70 |
+
- `POST /api/monsters/{id}/action` - Perform care action
|
| 71 |
+
- `POST /api/monsters/{id}/talk` - Send message
|
| 72 |
+
- `POST /api/monsters/{id}/generate-3d` - Generate 3D model
|
| 73 |
+
- `WS /api/monsters/{id}/ws` - WebSocket for real-time updates
|
| 74 |
+
|
| 75 |
+
## **4. Voice Commands**
|
| 76 |
+
|
| 77 |
+
The system recognizes these voice intents:
|
| 78 |
+
|
| 79 |
+
### **Care Actions**
|
| 80 |
+
- "Feed [food type]" → `feed` action
|
| 81 |
+
- "Train [skill]" → `train` action
|
| 82 |
+
- "Play with monster" → `play` action
|
| 83 |
+
- "Clean monster" → `clean` action
|
| 84 |
+
- "Heal monster" → `heal` action
|
| 85 |
+
- "Let monster rest" → `rest` action
|
| 86 |
+
- "Discipline monster" → `discipline` action
|
| 87 |
+
|
| 88 |
+
### **3D Generation**
|
| 89 |
+
- "Generate 3D model" → triggers 3D generation
|
| 90 |
+
- "Create a [description]" → generates with description
|
| 91 |
+
|
| 92 |
+
### **Conversation**
|
| 93 |
+
- Any other speech → sent as conversation to monster
|
| 94 |
+
|
| 95 |
+
## **5. Component Structure**
|
| 96 |
+
|
| 97 |
+
### **Core Components**
|
| 98 |
+
- `Device.svelte` - Main device container
|
| 99 |
+
- `Screen.svelte` - 3D display with CRT effect
|
| 100 |
+
- `MonsterScene.svelte` - Three.js scene for monster
|
| 101 |
+
- `Dpad.svelte` - Directional pad control
|
| 102 |
+
- `ActionButton.svelte` - A/B buttons
|
| 103 |
+
- `VoiceButton.svelte` - Voice activation
|
| 104 |
+
- `HolographicStats.svelte` - Stats overlay
|
| 105 |
+
|
| 106 |
+
### **Services**
|
| 107 |
+
- `api.ts` - Backend communication
|
| 108 |
+
- `voice.ts` - Speech recognition & intent parsing
|
| 109 |
+
- `mcp.ts` - Model Context Protocol integration
|
| 110 |
+
|
| 111 |
+
### **Stores**
|
| 112 |
+
- `monsterStore.ts` - Monster state management
|
| 113 |
+
- `voiceStore.ts` - Voice input state
|
| 114 |
+
|
| 115 |
+
## **6. Styling Guide**
|
| 116 |
+
|
| 117 |
+
The UI uses a cyberpunk-retro aesthetic:
|
| 118 |
+
|
| 119 |
+
### **Color Palette**
|
| 120 |
+
- DigiPal Orange: `#FF6B00`
|
| 121 |
+
- DigiPal Teal: `#00CED1`
|
| 122 |
+
- DigiPal Gray: `#2D2D2D`
|
| 123 |
+
- Neon Magenta: `#FF00FF`
|
| 124 |
+
- Neon Cyan: `#00FFFF`
|
| 125 |
+
|
| 126 |
+
### **Effects**
|
| 127 |
+
- CRT scanlines animation
|
| 128 |
+
- Holographic glitch effect
|
| 129 |
+
- Neon glow shadows
|
| 130 |
+
- Pixel fonts for UI text
|
| 131 |
+
|
| 132 |
+
## **7. MCP Integration**
|
| 133 |
+
|
| 134 |
+
When MCP is configured, the system will:
|
| 135 |
+
1. Use MCP for AI conversations instead of local Qwen
|
| 136 |
+
2. Use MCP for 3D generation instead of local pipeline
|
| 137 |
+
3. Optionally use MCP for speech-to-text
|
| 138 |
+
|
| 139 |
+
Configure via environment variables:
|
| 140 |
+
```bash
|
| 141 |
+
MCP_ENDPOINT=https://your-mcp-server.com
|
| 142 |
+
MCP_API_KEY=your-api-key
|
| 143 |
+
```
|
| 144 |
+
|
| 145 |
+
## **8. Development Tips**
|
| 146 |
+
|
| 147 |
+
### **Adding New Voice Commands**
|
| 148 |
+
1. Update intent parsing in `voice.ts`
|
| 149 |
+
2. Add handler in `voiceStore.ts`
|
| 150 |
+
3. Implement action in `monsterStore.ts`
|
| 151 |
+
|
| 152 |
+
### **Adding New UI Components**
|
| 153 |
+
1. Create component in `src/lib/components/`
|
| 154 |
+
2. Apply cyberpunk-retro styling
|
| 155 |
+
3. Connect to appropriate stores
|
| 156 |
+
|
| 157 |
+
### **Extending 3D Features**
|
| 158 |
+
1. Update `MonsterScene.svelte` for new animations
|
| 159 |
+
2. Add model loading logic
|
| 160 |
+
3. Implement interactive features
|
| 161 |
+
|
| 162 |
+
## **9. Production Deployment**
|
| 163 |
+
|
| 164 |
+
### **Build Process**
|
| 165 |
+
```bash
|
| 166 |
+
# Backend
|
| 167 |
+
docker build -t digipal .
|
| 168 |
+
|
| 169 |
+
# Frontend
|
| 170 |
+
cd frontend && npm run build
|
| 171 |
+
```
|
| 172 |
+
|
| 173 |
+
### **Environment Variables**
|
| 174 |
+
- `API_PORT`: Backend API port (default: 7861)
|
| 175 |
+
- `SERVER_PORT`: Gradio port (default: 7860)
|
| 176 |
+
- `MCP_ENDPOINT`: MCP server URL
|
| 177 |
+
- `MCP_API_KEY`: MCP authentication
|
| 178 |
+
|
| 179 |
+
## **10. Future Enhancements**
|
| 180 |
+
|
| 181 |
+
- [ ] PWA support for mobile devices
|
| 182 |
+
- [ ] Offline voice recognition
|
| 183 |
+
- [ ] Multiplayer monster interactions
|
| 184 |
+
- [ ] AR mode using device camera
|
| 185 |
+
- [ ] Custom shader effects for monsters
|
| 186 |
+
- [ ] Voice synthesis for monster responses
|
README.md
CHANGED
|
@@ -18,13 +18,15 @@ tags:
|
|
| 18 |
- monster-raising
|
| 19 |
- conversation
|
| 20 |
- speech-recognition
|
|
|
|
|
|
|
| 21 |
suggested_hardware: zero-a10g
|
| 22 |
suggested_storage: medium
|
| 23 |
---
|
| 24 |
|
| 25 |
# 🐾 DigiPal - Advanced AI Monster Companion
|
| 26 |
|
| 27 |
-
The next generation of virtual monster companions powered by **Qwen 2.5**, **Whisper**,
|
| 28 |
|
| 29 |
## ✨ Features
|
| 30 |
|
|
@@ -39,12 +41,21 @@ The next generation of virtual monster companions powered by **Qwen 2.5**, **Whi
|
|
| 39 |
- **Real-time stat degradation** that continues even when offline
|
| 40 |
- **Complex evolution requirements** inspired by classic monster-raising games
|
| 41 |
- **Training mini-games** that affect monster development
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
|
| 43 |
### 🌟 Next-Generation Features
|
| 44 |
- **Cross-session persistence** with browser state management
|
| 45 |
- **Real-time streaming updates** using Gradio 5.34.2
|
| 46 |
- **Zero GPU optimization** for efficient resource usage
|
| 47 |
- **Advanced breeding system** with genetic inheritance
|
|
|
|
| 48 |
|
| 49 |
## 🚀 Technology Stack
|
| 50 |
|
|
@@ -52,15 +63,67 @@ The next generation of virtual monster companions powered by **Qwen 2.5**, **Whi
|
|
| 52 |
- **Gradio 5.34.2** with modern state management
|
| 53 |
- **Qwen 2.5 models** optimized for conversation
|
| 54 |
- **Faster Whisper** for efficient speech processing
|
|
|
|
| 55 |
- **Zero GPU deployment** for scalable AI inference
|
|
|
|
| 56 |
|
| 57 |
## 🎯 Getting Started
|
| 58 |
|
|
|
|
| 59 |
1. **Create Your Monster**: Choose a name and personality type
|
| 60 |
2. **Start Caring**: Feed, train, and interact with your companion
|
| 61 |
3. **Build Relationships**: Use voice or text chat to bond
|
| 62 |
4. **Watch Evolution**: Meet requirements to unlock new forms
|
| 63 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 64 |
|
| 65 |
## 💡 Tips for Best Experience
|
| 66 |
|
|
@@ -68,7 +131,36 @@ The next generation of virtual monster companions powered by **Qwen 2.5**, **Whi
|
|
| 68 |
- **Balanced care** prevents evolution mistakes
|
| 69 |
- **Voice chat** creates deeper emotional connections
|
| 70 |
- **Training variety** unlocks special evolution paths
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 71 |
|
| 72 |
---
|
| 73 |
|
| 74 |
-
*Experience the future of AI companionship with DigiPal!*
|
|
|
|
| 18 |
- monster-raising
|
| 19 |
- conversation
|
| 20 |
- speech-recognition
|
| 21 |
+
- 3d-generation
|
| 22 |
+
- text-to-3d
|
| 23 |
suggested_hardware: zero-a10g
|
| 24 |
suggested_storage: medium
|
| 25 |
---
|
| 26 |
|
| 27 |
# 🐾 DigiPal - Advanced AI Monster Companion
|
| 28 |
|
| 29 |
+
The next generation of virtual monster companions powered by **Qwen 2.5**, **Whisper**, advanced AI technologies, and **3D model generation**. Experience deep emotional connections with your digital pet through natural conversation, comprehensive care systems, sophisticated evolution mechanics, and bring your monsters to life in 3D!
|
| 30 |
|
| 31 |
## ✨ Features
|
| 32 |
|
|
|
|
| 41 |
- **Real-time stat degradation** that continues even when offline
|
| 42 |
- **Complex evolution requirements** inspired by classic monster-raising games
|
| 43 |
- **Training mini-games** that affect monster development
|
| 44 |
+
- **DW1-aligned mechanics** option for authentic Digimon World 1 experience
|
| 45 |
+
|
| 46 |
+
### 🎨 3D Model Generation (V2)
|
| 47 |
+
- **Text-to-3D conversion** using Hunyuan3D and open-source models
|
| 48 |
+
- **Multiple model providers** including HuggingFace, local models, and MCP protocol
|
| 49 |
+
- **Real-time 3D visualization** of your monster companions
|
| 50 |
+
- **Async generation pipeline** for smooth user experience
|
| 51 |
+
- **Model caching** for efficient reuse of generated assets
|
| 52 |
|
| 53 |
### 🌟 Next-Generation Features
|
| 54 |
- **Cross-session persistence** with browser state management
|
| 55 |
- **Real-time streaming updates** using Gradio 5.34.2
|
| 56 |
- **Zero GPU optimization** for efficient resource usage
|
| 57 |
- **Advanced breeding system** with genetic inheritance
|
| 58 |
+
- **MCP (Model Context Protocol)** support for flexible model deployment
|
| 59 |
|
| 60 |
## 🚀 Technology Stack
|
| 61 |
|
|
|
|
| 63 |
- **Gradio 5.34.2** with modern state management
|
| 64 |
- **Qwen 2.5 models** optimized for conversation
|
| 65 |
- **Faster Whisper** for efficient speech processing
|
| 66 |
+
- **Hunyuan3D** for high-quality 3D model generation
|
| 67 |
- **Zero GPU deployment** for scalable AI inference
|
| 68 |
+
- **Docker support** for containerized deployment
|
| 69 |
|
| 70 |
## 🎯 Getting Started
|
| 71 |
|
| 72 |
+
### Option 1: Basic Version (V1)
|
| 73 |
1. **Create Your Monster**: Choose a name and personality type
|
| 74 |
2. **Start Caring**: Feed, train, and interact with your companion
|
| 75 |
3. **Build Relationships**: Use voice or text chat to bond
|
| 76 |
4. **Watch Evolution**: Meet requirements to unlock new forms
|
| 77 |
+
|
| 78 |
+
### Option 2: Enhanced Version with 3D (V2)
|
| 79 |
+
1. **All V1 features** plus:
|
| 80 |
+
2. **Generate 3D Models**: Create visual representations of your monsters
|
| 81 |
+
3. **Customize Appearance**: Use text descriptions to shape your monster's look
|
| 82 |
+
4. **View in 3D**: Interact with generated 3D models in real-time
|
| 83 |
+
|
| 84 |
+
## 🛠️ Running Locally
|
| 85 |
+
|
| 86 |
+
### Requirements
|
| 87 |
+
- Python 3.11+
|
| 88 |
+
- CUDA-capable GPU (recommended) or CPU
|
| 89 |
+
- 8GB+ RAM (16GB+ recommended for 3D features)
|
| 90 |
+
|
| 91 |
+
### Installation
|
| 92 |
+
```bash
|
| 93 |
+
# Clone the repository
|
| 94 |
+
git clone https://github.com/yourusername/digipal.git
|
| 95 |
+
cd digipal
|
| 96 |
+
|
| 97 |
+
# Install dependencies
|
| 98 |
+
pip install -r requirements.txt
|
| 99 |
+
|
| 100 |
+
# Run V1 (basic features)
|
| 101 |
+
python app.py
|
| 102 |
+
|
| 103 |
+
# Run V2 (with 3D generation)
|
| 104 |
+
python app_v2.py
|
| 105 |
+
```
|
| 106 |
+
|
| 107 |
+
### Docker Deployment
|
| 108 |
+
```bash
|
| 109 |
+
# Build the Docker image
|
| 110 |
+
docker build -t digipal .
|
| 111 |
+
|
| 112 |
+
# Run the container
|
| 113 |
+
docker run -p 7860:7860 -v $(pwd)/data:/app/data digipal
|
| 114 |
+
```
|
| 115 |
+
|
| 116 |
+
### Configuration Options
|
| 117 |
+
```bash
|
| 118 |
+
# Enable debug mode
|
| 119 |
+
LOG_LEVEL=DEBUG python app.py
|
| 120 |
+
|
| 121 |
+
# Disable specific features (V2 only)
|
| 122 |
+
ENABLE_3D=false python app_v2.py
|
| 123 |
+
|
| 124 |
+
# Custom port and sharing
|
| 125 |
+
SERVER_PORT=8080 SHARE=true python app.py
|
| 126 |
+
```
|
| 127 |
|
| 128 |
## 💡 Tips for Best Experience
|
| 129 |
|
|
|
|
| 131 |
- **Balanced care** prevents evolution mistakes
|
| 132 |
- **Voice chat** creates deeper emotional connections
|
| 133 |
- **Training variety** unlocks special evolution paths
|
| 134 |
+
- **3D generation** works best with detailed descriptions
|
| 135 |
+
- **Save frequently** to preserve your monster's progress
|
| 136 |
+
|
| 137 |
+
## 🔧 Advanced Features
|
| 138 |
+
|
| 139 |
+
### MCP Integration
|
| 140 |
+
DigiPal supports Model Context Protocol for flexible AI model deployment:
|
| 141 |
+
- Configure external model services via `MCP_ENDPOINT` and `MCP_API_KEY`
|
| 142 |
+
- Access various AI models through a standardized protocol
|
| 143 |
+
- Enable MCP server mode for integration with other tools
|
| 144 |
+
|
| 145 |
+
### Development Mode
|
| 146 |
+
- **Code formatting**: `black src/`
|
| 147 |
+
- **Linting**: `ruff src/`
|
| 148 |
+
- **Testing**: `pytest` (test suite in development)
|
| 149 |
+
|
| 150 |
+
## 📚 Documentation
|
| 151 |
+
|
| 152 |
+
- [CLAUDE.md](CLAUDE.md) - Development guide for Claude AI assistance
|
| 153 |
+
- [DIGIPAL_V2_GUIDE.md](DIGIPAL_V2_GUIDE.md) - Detailed V2 features guide
|
| 154 |
+
- [docs/HUNYUAN3D_INTEGRATION.md](docs/HUNYUAN3D_INTEGRATION.md) - 3D pipeline documentation
|
| 155 |
+
|
| 156 |
+
## 🤝 Contributing
|
| 157 |
+
|
| 158 |
+
Contributions are welcome! Please read our contributing guidelines and submit pull requests to our repository.
|
| 159 |
+
|
| 160 |
+
## 📄 License
|
| 161 |
+
|
| 162 |
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
| 163 |
|
| 164 |
---
|
| 165 |
|
| 166 |
+
*Experience the future of AI companionship with DigiPal - where virtual monsters come to life in conversation and 3D!*
|
app.py
CHANGED
|
@@ -1,183 +1,469 @@
|
|
| 1 |
-
#!/usr/bin/env python3
|
| 2 |
"""
|
| 3 |
-
DigiPal - Advanced AI Monster Companion
|
| 4 |
-
|
| 5 |
-
Optimized for Qwen 2.5 models and Zero GPU deployment
|
| 6 |
"""
|
| 7 |
|
|
|
|
|
|
|
|
|
|
| 8 |
import os
|
| 9 |
import sys
|
| 10 |
-
import logging
|
| 11 |
-
import asyncio
|
| 12 |
from pathlib import Path
|
| 13 |
-
from typing import Dict, Any
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
|
| 15 |
-
#
|
| 16 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
|
| 18 |
-
#
|
| 19 |
-
|
| 20 |
-
from src.deployment.zero_gpu_optimizer import ZeroGPUOptimizer
|
| 21 |
-
from src.utils.performance_tracker import PerformanceTracker
|
| 22 |
|
| 23 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
try:
|
| 25 |
-
import
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
def gpu_initialization_check():
|
| 38 |
-
return "Running without ZeroGPU"
|
| 39 |
-
|
| 40 |
-
def setup_logging(log_level: str = "INFO"):
|
| 41 |
-
"""Setup comprehensive logging configuration"""
|
| 42 |
-
|
| 43 |
-
# Create logs directory
|
| 44 |
-
logs_dir = Path("logs")
|
| 45 |
-
logs_dir.mkdir(exist_ok=True)
|
| 46 |
-
|
| 47 |
-
# Configure logging
|
| 48 |
-
logging.basicConfig(
|
| 49 |
-
level=getattr(logging, log_level.upper()),
|
| 50 |
-
format='%(asctime)s - %(name)s - %(levelname)s - %(funcName)s:%(lineno)d - %(message)s',
|
| 51 |
-
handlers=[
|
| 52 |
-
logging.FileHandler(logs_dir / "digipal.log"),
|
| 53 |
-
logging.StreamHandler(sys.stdout)
|
| 54 |
-
]
|
| 55 |
)
|
| 56 |
|
| 57 |
-
#
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
|
|
|
| 61 |
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
# Create necessary directories
|
| 66 |
-
directories = [
|
| 67 |
-
"data/saves",
|
| 68 |
-
"data/monsters",
|
| 69 |
-
"data/models",
|
| 70 |
-
"data/cache",
|
| 71 |
-
"logs",
|
| 72 |
-
"config"
|
| 73 |
-
]
|
| 74 |
-
|
| 75 |
-
for directory in directories:
|
| 76 |
-
Path(directory).mkdir(parents=True, exist_ok=True)
|
| 77 |
-
|
| 78 |
-
# Set environment variables for optimization
|
| 79 |
-
os.environ["TOKENIZERS_PARALLELISM"] = "false" # Avoid tokenizer warnings
|
| 80 |
-
os.environ["TRANSFORMERS_CACHE"] = str(Path("data/cache").absolute())
|
| 81 |
-
os.environ["HF_HOME"] = str(Path("data/cache").absolute())
|
| 82 |
-
|
| 83 |
-
# CUDA optimization settings
|
| 84 |
-
if "CUDA_VISIBLE_DEVICES" not in os.environ:
|
| 85 |
-
os.environ["CUDA_VISIBLE_DEVICES"] = "0"
|
| 86 |
-
|
| 87 |
-
# Memory optimization
|
| 88 |
-
os.environ["PYTORCH_CUDA_ALLOC_CONF"] = "max_split_size_mb:128"
|
| 89 |
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 98 |
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
|
|
|
|
|
|
|
|
|
| 102 |
|
| 103 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 104 |
|
| 105 |
-
#
|
| 106 |
-
|
| 107 |
-
await interface.initialize()
|
| 108 |
|
| 109 |
return {
|
| 110 |
-
"
|
| 111 |
-
"
|
| 112 |
-
"
|
| 113 |
-
"
|
|
|
|
| 114 |
}
|
| 115 |
-
|
| 116 |
except Exception as e:
|
| 117 |
-
logger.error(f"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 118 |
raise
|
|
|
|
|
|
|
|
|
|
| 119 |
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
# Setup environment first
|
| 124 |
-
setup_logging(os.getenv("LOG_LEVEL", "INFO"))
|
| 125 |
-
setup_environment()
|
| 126 |
-
|
| 127 |
-
logger = logging.getLogger(__name__)
|
| 128 |
-
logger.info("Starting DigiPal Advanced Monster Companion...")
|
| 129 |
-
|
| 130 |
try:
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
"
|
| 156 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 157 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 158 |
|
| 159 |
-
|
| 160 |
-
if os.getenv("SSL_ENABLED", "false").lower() == "true":
|
| 161 |
-
launch_config.update({
|
| 162 |
-
"ssl_keyfile": os.getenv("SSL_KEYFILE"),
|
| 163 |
-
"ssl_certfile": os.getenv("SSL_CERTFILE"),
|
| 164 |
-
"ssl_keyfile_password": os.getenv("SSL_PASSWORD")
|
| 165 |
-
})
|
| 166 |
|
| 167 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 168 |
|
| 169 |
-
#
|
| 170 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 171 |
|
| 172 |
-
|
| 173 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 174 |
except Exception as e:
|
| 175 |
-
logger.error(f"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 176 |
raise
|
| 177 |
-
|
| 178 |
-
logger.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 179 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 180 |
if __name__ == "__main__":
|
| 181 |
-
#
|
| 182 |
-
|
| 183 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
"""
|
| 2 |
+
DigiPal - Advanced AI Monster Companion with 3D Generation
|
| 3 |
+
Unified application with all features enabled by default
|
|
|
|
| 4 |
"""
|
| 5 |
|
| 6 |
+
import asyncio
|
| 7 |
+
import json
|
| 8 |
+
import logging
|
| 9 |
import os
|
| 10 |
import sys
|
|
|
|
|
|
|
| 11 |
from pathlib import Path
|
| 12 |
+
from typing import Dict, Any, Optional, List
|
| 13 |
+
from datetime import datetime
|
| 14 |
+
import uvicorn
|
| 15 |
+
from fastapi import FastAPI, WebSocket, WebSocketDisconnect, HTTPException
|
| 16 |
+
from fastapi.middleware.cors import CORSMiddleware
|
| 17 |
+
from fastapi.responses import JSONResponse
|
| 18 |
+
from pydantic import BaseModel
|
| 19 |
+
import gradio as gr
|
| 20 |
+
import torch
|
| 21 |
+
import spaces
|
| 22 |
+
|
| 23 |
+
# Add src to path
|
| 24 |
+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src'))
|
| 25 |
+
|
| 26 |
+
# Configure logging
|
| 27 |
+
logging.basicConfig(
|
| 28 |
+
level=logging.INFO,
|
| 29 |
+
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
| 30 |
+
)
|
| 31 |
+
logger = logging.getLogger(__name__)
|
| 32 |
|
| 33 |
+
# Environment configuration - All features enabled by default
|
| 34 |
+
ENV_CONFIG = {
|
| 35 |
+
"LOG_LEVEL": os.getenv("LOG_LEVEL", "INFO"),
|
| 36 |
+
"SERVER_NAME": os.getenv("SERVER_NAME", "0.0.0.0"),
|
| 37 |
+
"SERVER_PORT": int(os.getenv("SERVER_PORT", "7860")),
|
| 38 |
+
"API_PORT": int(os.getenv("API_PORT", "7861")),
|
| 39 |
+
"SHARE": os.getenv("SHARE", "false").lower() == "true",
|
| 40 |
+
"DEBUG": os.getenv("DEBUG", "false").lower() == "true",
|
| 41 |
+
"MAX_THREADS": int(os.getenv("MAX_THREADS", "40")),
|
| 42 |
+
"MCP_ENDPOINT": os.getenv("MCP_ENDPOINT", ""),
|
| 43 |
+
"MCP_API_KEY": os.getenv("MCP_API_KEY", "")
|
| 44 |
+
}
|
| 45 |
|
| 46 |
+
# HuggingFace Spaces detection
|
| 47 |
+
IS_SPACES = os.getenv("SPACE_ID") is not None
|
|
|
|
|
|
|
| 48 |
|
| 49 |
+
# API Models
|
| 50 |
+
class CreateMonsterRequest(BaseModel):
|
| 51 |
+
name: str
|
| 52 |
+
personality: str
|
| 53 |
+
|
| 54 |
+
class MonsterActionRequest(BaseModel):
|
| 55 |
+
action: str
|
| 56 |
+
params: Dict[str, Any] = {}
|
| 57 |
+
|
| 58 |
+
class MonsterTalkRequest(BaseModel):
|
| 59 |
+
message: str
|
| 60 |
+
|
| 61 |
+
class Generate3DRequest(BaseModel):
|
| 62 |
+
description: Optional[str] = None
|
| 63 |
+
|
| 64 |
+
# Import core modules after environment setup
|
| 65 |
try:
|
| 66 |
+
from src.core.monster_engine_dw1 import Monster, PersonalityType
|
| 67 |
+
from src.core.evolution_system import EvolutionSystem
|
| 68 |
+
from src.ai.qwen_processor import QwenProcessor
|
| 69 |
+
from src.ai.speech_engine import SpeechEngine
|
| 70 |
+
from src.ui.state_manager import StateManager
|
| 71 |
+
from src.deployment.zero_gpu_optimizer import get_optimal_device
|
| 72 |
+
from src.pipelines.text_to_3d_pipeline import Text3DPipeline
|
| 73 |
+
from src.pipelines.hunyuan3d_pipeline import Hunyuan3DClient
|
| 74 |
+
from src.pipelines.opensource_3d_pipeline_v2 import (
|
| 75 |
+
OpenSourcePipelineV2,
|
| 76 |
+
PipelineConfig,
|
| 77 |
+
ModelProvider
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 78 |
)
|
| 79 |
|
| 80 |
+
# UI imports
|
| 81 |
+
from src.ui.gradio_interface_v2 import create_interface
|
| 82 |
+
except ImportError as e:
|
| 83 |
+
logger.error(f"Failed to import required modules: {e}")
|
| 84 |
+
sys.exit(1)
|
| 85 |
|
| 86 |
+
# Initialize FastAPI app
|
| 87 |
+
app = FastAPI(title="DigiPal API", version="1.0.0")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 88 |
|
| 89 |
+
# Add CORS middleware for frontend communication
|
| 90 |
+
app.add_middleware(
|
| 91 |
+
CORSMiddleware,
|
| 92 |
+
allow_origins=["*"], # In production, replace with specific origins
|
| 93 |
+
allow_credentials=True,
|
| 94 |
+
allow_methods=["*"],
|
| 95 |
+
allow_headers=["*"],
|
| 96 |
+
)
|
| 97 |
+
|
| 98 |
+
# Global state management
|
| 99 |
+
class AppState:
|
| 100 |
+
def __init__(self):
|
| 101 |
+
self.monsters: Dict[str, Monster] = {}
|
| 102 |
+
self.state_manager = StateManager()
|
| 103 |
+
self.qwen_processor = None
|
| 104 |
+
self.speech_engine = None
|
| 105 |
+
self.evolution_system = EvolutionSystem()
|
| 106 |
+
self.text3d_pipeline = None
|
| 107 |
+
self.active_connections: Dict[str, WebSocket] = {}
|
| 108 |
+
self.initialized = False
|
| 109 |
|
| 110 |
+
async def initialize(self):
|
| 111 |
+
"""Initialize AI components and pipelines"""
|
| 112 |
+
if self.initialized:
|
| 113 |
+
return
|
| 114 |
+
|
| 115 |
+
logger.info("Initializing AI components...")
|
| 116 |
|
| 117 |
+
# Initialize AI processors
|
| 118 |
+
try:
|
| 119 |
+
self.qwen_processor = QwenProcessor()
|
| 120 |
+
self.speech_engine = SpeechEngine()
|
| 121 |
+
|
| 122 |
+
# Initialize 3D pipeline with MCP if available
|
| 123 |
+
if ENV_CONFIG["MCP_ENDPOINT"]:
|
| 124 |
+
logger.info("Using MCP for 3D generation")
|
| 125 |
+
pipeline_config = PipelineConfig(
|
| 126 |
+
model_provider=ModelProvider.MCP,
|
| 127 |
+
mcp_endpoint=ENV_CONFIG["MCP_ENDPOINT"],
|
| 128 |
+
mcp_api_key=ENV_CONFIG["MCP_API_KEY"]
|
| 129 |
+
)
|
| 130 |
+
else:
|
| 131 |
+
logger.info("Using local models for 3D generation")
|
| 132 |
+
pipeline_config = PipelineConfig(
|
| 133 |
+
model_provider=ModelProvider.HUGGINGFACE
|
| 134 |
+
)
|
| 135 |
+
|
| 136 |
+
self.text3d_pipeline = Text3DPipeline(
|
| 137 |
+
pipeline_type="opensource_v2",
|
| 138 |
+
config=pipeline_config
|
| 139 |
+
)
|
| 140 |
+
|
| 141 |
+
self.initialized = True
|
| 142 |
+
logger.info("All components initialized successfully")
|
| 143 |
+
|
| 144 |
+
except Exception as e:
|
| 145 |
+
logger.error(f"Failed to initialize components: {e}")
|
| 146 |
+
raise
|
| 147 |
+
|
| 148 |
+
# Create global app state
|
| 149 |
+
app_state = AppState()
|
| 150 |
+
|
| 151 |
+
# WebSocket connection manager
|
| 152 |
+
class ConnectionManager:
|
| 153 |
+
def __init__(self):
|
| 154 |
+
self.active_connections: Dict[str, WebSocket] = {}
|
| 155 |
+
|
| 156 |
+
async def connect(self, websocket: WebSocket, monster_id: str):
|
| 157 |
+
await websocket.accept()
|
| 158 |
+
self.active_connections[monster_id] = websocket
|
| 159 |
+
|
| 160 |
+
def disconnect(self, monster_id: str):
|
| 161 |
+
if monster_id in self.active_connections:
|
| 162 |
+
del self.active_connections[monster_id]
|
| 163 |
+
|
| 164 |
+
async def send_update(self, monster_id: str, data: dict):
|
| 165 |
+
if monster_id in self.active_connections:
|
| 166 |
+
try:
|
| 167 |
+
await self.active_connections[monster_id].send_json(data)
|
| 168 |
+
except:
|
| 169 |
+
self.disconnect(monster_id)
|
| 170 |
+
|
| 171 |
+
manager = ConnectionManager()
|
| 172 |
+
|
| 173 |
+
# API Endpoints
|
| 174 |
+
@app.on_event("startup")
|
| 175 |
+
async def startup_event():
|
| 176 |
+
"""Initialize app state on startup"""
|
| 177 |
+
await app_state.initialize()
|
| 178 |
+
|
| 179 |
+
@app.get("/health")
|
| 180 |
+
async def health_check():
|
| 181 |
+
"""Health check endpoint"""
|
| 182 |
+
return {"status": "healthy", "initialized": app_state.initialized}
|
| 183 |
+
|
| 184 |
+
@app.get("/api/monsters")
|
| 185 |
+
async def list_monsters():
|
| 186 |
+
"""List all available saved monsters"""
|
| 187 |
+
try:
|
| 188 |
+
saved_monsters = await app_state.state_manager.list_saved_monsters()
|
| 189 |
+
return {"monsters": saved_monsters}
|
| 190 |
+
except Exception as e:
|
| 191 |
+
logger.error(f"Error listing monsters: {e}")
|
| 192 |
+
raise HTTPException(status_code=500, detail=str(e))
|
| 193 |
+
|
| 194 |
+
@app.post("/api/monsters")
|
| 195 |
+
async def create_monster(request: CreateMonsterRequest):
|
| 196 |
+
"""Create a new monster"""
|
| 197 |
+
try:
|
| 198 |
+
# Create new monster
|
| 199 |
+
personality = PersonalityType[request.personality.upper()]
|
| 200 |
+
monster = Monster(name=request.name, personality=personality)
|
| 201 |
+
|
| 202 |
+
# Save to state
|
| 203 |
+
app_state.monsters[monster.id] = monster
|
| 204 |
|
| 205 |
+
# Save to database
|
| 206 |
+
await app_state.state_manager.save_monster(monster)
|
|
|
|
| 207 |
|
| 208 |
return {
|
| 209 |
+
"id": monster.id,
|
| 210 |
+
"name": monster.name,
|
| 211 |
+
"personality": monster.personality.value,
|
| 212 |
+
"stage": monster.stage.value,
|
| 213 |
+
"stats": monster.get_stats()
|
| 214 |
}
|
|
|
|
| 215 |
except Exception as e:
|
| 216 |
+
logger.error(f"Error creating monster: {e}")
|
| 217 |
+
raise HTTPException(status_code=500, detail=str(e))
|
| 218 |
+
|
| 219 |
+
@app.get("/api/monsters/{monster_id}")
|
| 220 |
+
async def get_monster(monster_id: str):
|
| 221 |
+
"""Load a specific monster's full state"""
|
| 222 |
+
try:
|
| 223 |
+
# Check if already loaded
|
| 224 |
+
if monster_id in app_state.monsters:
|
| 225 |
+
monster = app_state.monsters[monster_id]
|
| 226 |
+
else:
|
| 227 |
+
# Load from database
|
| 228 |
+
monster = await app_state.state_manager.load_monster_by_id(monster_id)
|
| 229 |
+
if not monster:
|
| 230 |
+
raise HTTPException(status_code=404, detail="Monster not found")
|
| 231 |
+
app_state.monsters[monster_id] = monster
|
| 232 |
+
|
| 233 |
+
return {
|
| 234 |
+
"id": monster.id,
|
| 235 |
+
"name": monster.name,
|
| 236 |
+
"personality": monster.personality.value,
|
| 237 |
+
"stage": monster.stage.value,
|
| 238 |
+
"stats": monster.get_stats(),
|
| 239 |
+
"model_url": monster.model_url,
|
| 240 |
+
"conversation_history": monster.conversation_history[-10:] # Last 10 messages
|
| 241 |
+
}
|
| 242 |
+
except HTTPException:
|
| 243 |
raise
|
| 244 |
+
except Exception as e:
|
| 245 |
+
logger.error(f"Error loading monster: {e}")
|
| 246 |
+
raise HTTPException(status_code=500, detail=str(e))
|
| 247 |
|
| 248 |
+
@app.post("/api/monsters/{monster_id}/action")
|
| 249 |
+
async def perform_action(monster_id: str, request: MonsterActionRequest):
|
| 250 |
+
"""Perform a care action on the monster"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 251 |
try:
|
| 252 |
+
if monster_id not in app_state.monsters:
|
| 253 |
+
raise HTTPException(status_code=404, detail="Monster not found")
|
| 254 |
+
|
| 255 |
+
monster = app_state.monsters[monster_id]
|
| 256 |
+
result = {}
|
| 257 |
+
|
| 258 |
+
# Handle different actions
|
| 259 |
+
if request.action == "feed":
|
| 260 |
+
food_type = request.params.get("food_type", "balanced")
|
| 261 |
+
result = monster.feed(food_type)
|
| 262 |
+
elif request.action == "train":
|
| 263 |
+
training_type = request.params.get("training_type", "strength")
|
| 264 |
+
result = monster.train(training_type)
|
| 265 |
+
elif request.action == "play":
|
| 266 |
+
result = monster.play()
|
| 267 |
+
elif request.action == "clean":
|
| 268 |
+
result = monster.clean()
|
| 269 |
+
elif request.action == "heal":
|
| 270 |
+
result = monster.heal()
|
| 271 |
+
elif request.action == "discipline":
|
| 272 |
+
result = monster.discipline()
|
| 273 |
+
elif request.action == "rest":
|
| 274 |
+
result = monster.rest()
|
| 275 |
+
else:
|
| 276 |
+
raise HTTPException(status_code=400, detail=f"Unknown action: {request.action}")
|
| 277 |
+
|
| 278 |
+
# Save state
|
| 279 |
+
await app_state.state_manager.save_monster(monster)
|
| 280 |
+
|
| 281 |
+
# Send real-time update
|
| 282 |
+
await manager.send_update(monster_id, {
|
| 283 |
+
"type": "stats_update",
|
| 284 |
+
"stats": monster.get_stats(),
|
| 285 |
+
"stage": monster.stage.value
|
| 286 |
+
})
|
| 287 |
+
|
| 288 |
+
return {
|
| 289 |
+
"success": True,
|
| 290 |
+
"result": result,
|
| 291 |
+
"stats": monster.get_stats()
|
| 292 |
}
|
| 293 |
+
except HTTPException:
|
| 294 |
+
raise
|
| 295 |
+
except Exception as e:
|
| 296 |
+
logger.error(f"Error performing action: {e}")
|
| 297 |
+
raise HTTPException(status_code=500, detail=str(e))
|
| 298 |
+
|
| 299 |
+
@app.post("/api/monsters/{monster_id}/talk")
|
| 300 |
+
async def talk_to_monster(monster_id: str, request: MonsterTalkRequest):
|
| 301 |
+
"""Send a text message to the monster"""
|
| 302 |
+
try:
|
| 303 |
+
if monster_id not in app_state.monsters:
|
| 304 |
+
raise HTTPException(status_code=404, detail="Monster not found")
|
| 305 |
|
| 306 |
+
monster = app_state.monsters[monster_id]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 307 |
|
| 308 |
+
# Use MCP if available, otherwise use local processor
|
| 309 |
+
if ENV_CONFIG["MCP_ENDPOINT"] and hasattr(app_state.qwen_processor, 'use_mcp'):
|
| 310 |
+
response = await app_state.qwen_processor.generate_response_mcp(
|
| 311 |
+
monster, request.message
|
| 312 |
+
)
|
| 313 |
+
else:
|
| 314 |
+
response = app_state.qwen_processor.generate_response(
|
| 315 |
+
monster, request.message
|
| 316 |
+
)
|
| 317 |
|
| 318 |
+
# Update conversation history
|
| 319 |
+
monster.conversation_history.append({
|
| 320 |
+
"role": "user",
|
| 321 |
+
"content": request.message,
|
| 322 |
+
"timestamp": datetime.now().isoformat()
|
| 323 |
+
})
|
| 324 |
+
monster.conversation_history.append({
|
| 325 |
+
"role": "assistant",
|
| 326 |
+
"content": response,
|
| 327 |
+
"timestamp": datetime.now().isoformat()
|
| 328 |
+
})
|
| 329 |
|
| 330 |
+
# Save state
|
| 331 |
+
await app_state.state_manager.save_monster(monster)
|
| 332 |
+
|
| 333 |
+
return {
|
| 334 |
+
"response": response,
|
| 335 |
+
"stats": monster.get_stats()
|
| 336 |
+
}
|
| 337 |
+
except HTTPException:
|
| 338 |
+
raise
|
| 339 |
except Exception as e:
|
| 340 |
+
logger.error(f"Error talking to monster: {e}")
|
| 341 |
+
raise HTTPException(status_code=500, detail=str(e))
|
| 342 |
+
|
| 343 |
+
@app.post("/api/monsters/{monster_id}/generate-3d")
|
| 344 |
+
async def generate_3d_model(monster_id: str, request: Generate3DRequest):
|
| 345 |
+
"""Trigger 3D model generation for the monster"""
|
| 346 |
+
try:
|
| 347 |
+
if monster_id not in app_state.monsters:
|
| 348 |
+
raise HTTPException(status_code=404, detail="Monster not found")
|
| 349 |
+
|
| 350 |
+
monster = app_state.monsters[monster_id]
|
| 351 |
+
|
| 352 |
+
# Generate description if not provided
|
| 353 |
+
if not request.description:
|
| 354 |
+
description = f"A {monster.personality.value} {monster.stage.value} digital monster"
|
| 355 |
+
else:
|
| 356 |
+
description = request.description
|
| 357 |
+
|
| 358 |
+
# Generate 3D model
|
| 359 |
+
logger.info(f"Generating 3D model for {monster.name}: {description}")
|
| 360 |
+
model_path = await app_state.text3d_pipeline.generate(
|
| 361 |
+
description,
|
| 362 |
+
output_dir=f"data/models/{monster_id}"
|
| 363 |
+
)
|
| 364 |
+
|
| 365 |
+
# Update monster with model URL
|
| 366 |
+
monster.model_url = f"/models/{monster_id}/{Path(model_path).name}"
|
| 367 |
+
await app_state.state_manager.save_monster(monster)
|
| 368 |
+
|
| 369 |
+
# Send update via WebSocket
|
| 370 |
+
await manager.send_update(monster_id, {
|
| 371 |
+
"type": "model_update",
|
| 372 |
+
"model_url": monster.model_url
|
| 373 |
+
})
|
| 374 |
+
|
| 375 |
+
return {
|
| 376 |
+
"success": True,
|
| 377 |
+
"model_url": monster.model_url
|
| 378 |
+
}
|
| 379 |
+
except HTTPException:
|
| 380 |
raise
|
| 381 |
+
except Exception as e:
|
| 382 |
+
logger.error(f"Error generating 3D model: {e}")
|
| 383 |
+
raise HTTPException(status_code=500, detail=str(e))
|
| 384 |
+
|
| 385 |
+
@app.websocket("/api/monsters/{monster_id}/ws")
|
| 386 |
+
async def websocket_endpoint(websocket: WebSocket, monster_id: str):
|
| 387 |
+
"""WebSocket endpoint for real-time updates"""
|
| 388 |
+
await manager.connect(websocket, monster_id)
|
| 389 |
+
|
| 390 |
+
try:
|
| 391 |
+
# Send initial stats
|
| 392 |
+
if monster_id in app_state.monsters:
|
| 393 |
+
monster = app_state.monsters[monster_id]
|
| 394 |
+
await websocket.send_json({
|
| 395 |
+
"type": "initial_state",
|
| 396 |
+
"stats": monster.get_stats(),
|
| 397 |
+
"stage": monster.stage.value,
|
| 398 |
+
"model_url": monster.model_url
|
| 399 |
+
})
|
| 400 |
+
|
| 401 |
+
# Keep connection alive and handle stat degradation
|
| 402 |
+
while True:
|
| 403 |
+
await asyncio.sleep(30) # Update every 30 seconds
|
| 404 |
+
|
| 405 |
+
if monster_id in app_state.monsters:
|
| 406 |
+
monster = app_state.monsters[monster_id]
|
| 407 |
+
monster.update_time_based_stats()
|
| 408 |
+
|
| 409 |
+
await websocket.send_json({
|
| 410 |
+
"type": "stats_update",
|
| 411 |
+
"stats": monster.get_stats(),
|
| 412 |
+
"stage": monster.stage.value
|
| 413 |
+
})
|
| 414 |
+
|
| 415 |
+
except WebSocketDisconnect:
|
| 416 |
+
manager.disconnect(monster_id)
|
| 417 |
|
| 418 |
+
# Gradio interface for fallback/admin
|
| 419 |
+
def create_gradio_interface():
|
| 420 |
+
"""Create Gradio interface as admin panel"""
|
| 421 |
+
interface = create_interface()
|
| 422 |
+
return interface
|
| 423 |
+
|
| 424 |
+
# Main entry point
|
| 425 |
if __name__ == "__main__":
|
| 426 |
+
# Create necessary directories
|
| 427 |
+
os.makedirs("data/saves", exist_ok=True)
|
| 428 |
+
os.makedirs("data/models", exist_ok=True)
|
| 429 |
+
os.makedirs("data/cache", exist_ok=True)
|
| 430 |
+
os.makedirs("logs", exist_ok=True)
|
| 431 |
+
|
| 432 |
+
# Log startup info
|
| 433 |
+
logger.info("=" * 60)
|
| 434 |
+
logger.info("DigiPal - Advanced AI Monster Companion")
|
| 435 |
+
logger.info("=" * 60)
|
| 436 |
+
logger.info(f"Environment: {'HuggingFace Spaces' if IS_SPACES else 'Local'}")
|
| 437 |
+
logger.info(f"API Port: {ENV_CONFIG['API_PORT']}")
|
| 438 |
+
logger.info(f"Gradio Port: {ENV_CONFIG['SERVER_PORT']}")
|
| 439 |
+
logger.info(f"MCP Enabled: {bool(ENV_CONFIG['MCP_ENDPOINT'])}")
|
| 440 |
+
logger.info("=" * 60)
|
| 441 |
+
|
| 442 |
+
# Run both FastAPI and Gradio
|
| 443 |
+
async def run_servers():
|
| 444 |
+
# Start FastAPI server
|
| 445 |
+
config = uvicorn.Config(
|
| 446 |
+
app,
|
| 447 |
+
host=ENV_CONFIG["SERVER_NAME"],
|
| 448 |
+
port=ENV_CONFIG["API_PORT"],
|
| 449 |
+
log_level=ENV_CONFIG["LOG_LEVEL"].lower()
|
| 450 |
+
)
|
| 451 |
+
server = uvicorn.Server(config)
|
| 452 |
+
|
| 453 |
+
# Create Gradio interface
|
| 454 |
+
gr_interface = create_gradio_interface()
|
| 455 |
+
|
| 456 |
+
# Run both servers concurrently
|
| 457 |
+
await asyncio.gather(
|
| 458 |
+
server.serve(),
|
| 459 |
+
gr_interface.launch(
|
| 460 |
+
server_name=ENV_CONFIG["SERVER_NAME"],
|
| 461 |
+
server_port=ENV_CONFIG["SERVER_PORT"],
|
| 462 |
+
share=ENV_CONFIG["SHARE"],
|
| 463 |
+
max_threads=ENV_CONFIG["MAX_THREADS"],
|
| 464 |
+
show_error=True
|
| 465 |
+
)
|
| 466 |
+
)
|
| 467 |
+
|
| 468 |
+
# Run the servers
|
| 469 |
+
asyncio.run(run_servers())
|
frontend/app.html
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!doctype html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="utf-8" />
|
| 5 |
+
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
| 6 |
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
| 7 |
+
%sveltekit.head%
|
| 8 |
+
</head>
|
| 9 |
+
<body data-sveltekit-preload-data="hover" class="bg-black text-white">
|
| 10 |
+
<div style="display: contents">%sveltekit.body%</div>
|
| 11 |
+
</body>
|
| 12 |
+
</html>
|
frontend/frontend/.gitignore
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
node_modules
|
| 2 |
+
|
| 3 |
+
# Output
|
| 4 |
+
.output
|
| 5 |
+
.vercel
|
| 6 |
+
.netlify
|
| 7 |
+
.wrangler
|
| 8 |
+
/.svelte-kit
|
| 9 |
+
/build
|
| 10 |
+
|
| 11 |
+
# OS
|
| 12 |
+
.DS_Store
|
| 13 |
+
Thumbs.db
|
| 14 |
+
|
| 15 |
+
# Env
|
| 16 |
+
.env
|
| 17 |
+
.env.*
|
| 18 |
+
!.env.example
|
| 19 |
+
!.env.test
|
| 20 |
+
|
| 21 |
+
# Vite
|
| 22 |
+
vite.config.js.timestamp-*
|
| 23 |
+
vite.config.ts.timestamp-*
|
frontend/frontend/.npmrc
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
engine-strict=true
|
frontend/frontend/README.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# sv
|
| 2 |
+
|
| 3 |
+
Everything you need to build a Svelte project, powered by [`sv`](https://github.com/sveltejs/cli).
|
| 4 |
+
|
| 5 |
+
## Creating a project
|
| 6 |
+
|
| 7 |
+
If you're seeing this, you've probably already done this step. Congrats!
|
| 8 |
+
|
| 9 |
+
```bash
|
| 10 |
+
# create a new project in the current directory
|
| 11 |
+
npx sv create
|
| 12 |
+
|
| 13 |
+
# create a new project in my-app
|
| 14 |
+
npx sv create my-app
|
| 15 |
+
```
|
| 16 |
+
|
| 17 |
+
## Developing
|
| 18 |
+
|
| 19 |
+
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
|
| 20 |
+
|
| 21 |
+
```bash
|
| 22 |
+
npm run dev
|
| 23 |
+
|
| 24 |
+
# or start the server and open the app in a new browser tab
|
| 25 |
+
npm run dev -- --open
|
| 26 |
+
```
|
| 27 |
+
|
| 28 |
+
## Building
|
| 29 |
+
|
| 30 |
+
To create a production version of your app:
|
| 31 |
+
|
| 32 |
+
```bash
|
| 33 |
+
npm run build
|
| 34 |
+
```
|
| 35 |
+
|
| 36 |
+
You can preview the production build with `npm run preview`.
|
| 37 |
+
|
| 38 |
+
> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.
|
frontend/frontend/package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"name": "frontend",
|
| 3 |
+
"private": true,
|
| 4 |
+
"version": "0.0.1",
|
| 5 |
+
"type": "module",
|
| 6 |
+
"scripts": {
|
| 7 |
+
"dev": "vite dev",
|
| 8 |
+
"build": "vite build",
|
| 9 |
+
"preview": "vite preview",
|
| 10 |
+
"prepare": "svelte-kit sync || echo ''",
|
| 11 |
+
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
| 12 |
+
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"
|
| 13 |
+
},
|
| 14 |
+
"devDependencies": {
|
| 15 |
+
"@sveltejs/adapter-auto": "^6.0.0",
|
| 16 |
+
"@sveltejs/kit": "^2.16.0",
|
| 17 |
+
"@sveltejs/vite-plugin-svelte": "^5.0.0",
|
| 18 |
+
"svelte": "^5.0.0",
|
| 19 |
+
"svelte-check": "^4.0.0",
|
| 20 |
+
"typescript": "^5.0.0",
|
| 21 |
+
"vite": "^6.2.6"
|
| 22 |
+
}
|
| 23 |
+
}
|
frontend/frontend/src/app.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// See https://svelte.dev/docs/kit/types#app.d.ts
|
| 2 |
+
// for information about these interfaces
|
| 3 |
+
declare global {
|
| 4 |
+
namespace App {
|
| 5 |
+
// interface Error {}
|
| 6 |
+
// interface Locals {}
|
| 7 |
+
// interface PageData {}
|
| 8 |
+
// interface PageState {}
|
| 9 |
+
// interface Platform {}
|
| 10 |
+
}
|
| 11 |
+
}
|
| 12 |
+
|
| 13 |
+
export {};
|
frontend/frontend/src/app.html
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!doctype html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="utf-8" />
|
| 5 |
+
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
| 6 |
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
| 7 |
+
%sveltekit.head%
|
| 8 |
+
</head>
|
| 9 |
+
<body data-sveltekit-preload-data="hover">
|
| 10 |
+
<div style="display: contents">%sveltekit.body%</div>
|
| 11 |
+
</body>
|
| 12 |
+
</html>
|
frontend/frontend/src/routes/+page.svelte
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<h1>Welcome to SvelteKit</h1>
|
| 2 |
+
<p>Visit <a href="https://svelte.dev/docs/kit">svelte.dev/docs/kit</a> to read the documentation</p>
|
frontend/frontend/static/favicon.png
ADDED
|
|
frontend/frontend/svelte.config.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import adapter from '@sveltejs/adapter-auto';
|
| 2 |
+
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
| 3 |
+
|
| 4 |
+
/** @type {import('@sveltejs/kit').Config} */
|
| 5 |
+
const config = {
|
| 6 |
+
// Consult https://svelte.dev/docs/kit/integrations
|
| 7 |
+
// for more information about preprocessors
|
| 8 |
+
preprocess: vitePreprocess(),
|
| 9 |
+
|
| 10 |
+
kit: {
|
| 11 |
+
// adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list.
|
| 12 |
+
// If your environment is not supported, or you settled on a specific environment, switch out the adapter.
|
| 13 |
+
// See https://svelte.dev/docs/kit/adapters for more information about adapters.
|
| 14 |
+
adapter: adapter()
|
| 15 |
+
}
|
| 16 |
+
};
|
| 17 |
+
|
| 18 |
+
export default config;
|
frontend/frontend/tsconfig.json
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"extends": "./.svelte-kit/tsconfig.json",
|
| 3 |
+
"compilerOptions": {
|
| 4 |
+
"allowJs": true,
|
| 5 |
+
"checkJs": true,
|
| 6 |
+
"esModuleInterop": true,
|
| 7 |
+
"forceConsistentCasingInFileNames": true,
|
| 8 |
+
"resolveJsonModule": true,
|
| 9 |
+
"skipLibCheck": true,
|
| 10 |
+
"sourceMap": true,
|
| 11 |
+
"strict": true,
|
| 12 |
+
"moduleResolution": "bundler"
|
| 13 |
+
}
|
| 14 |
+
// Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias
|
| 15 |
+
// except $lib which is handled by https://svelte.dev/docs/kit/configuration#files
|
| 16 |
+
//
|
| 17 |
+
// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
|
| 18 |
+
// from the referenced tsconfig.json - TypeScript does not merge them in
|
| 19 |
+
}
|
frontend/frontend/vite.config.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { sveltekit } from '@sveltejs/kit/vite';
|
| 2 |
+
import { defineConfig } from 'vite';
|
| 3 |
+
|
| 4 |
+
export default defineConfig({
|
| 5 |
+
plugins: [sveltekit()]
|
| 6 |
+
});
|
frontend/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"name": "digipal-frontend",
|
| 3 |
+
"version": "1.0.0",
|
| 4 |
+
"private": true,
|
| 5 |
+
"scripts": {
|
| 6 |
+
"dev": "vite dev",
|
| 7 |
+
"build": "vite build",
|
| 8 |
+
"preview": "vite preview",
|
| 9 |
+
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
| 10 |
+
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"
|
| 11 |
+
},
|
| 12 |
+
"devDependencies": {
|
| 13 |
+
"@sveltejs/adapter-auto": "^3.0.0",
|
| 14 |
+
"@sveltejs/kit": "^2.0.0",
|
| 15 |
+
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
| 16 |
+
"@types/three": "^0.160.0",
|
| 17 |
+
"svelte": "^4.2.7",
|
| 18 |
+
"svelte-check": "^3.6.0",
|
| 19 |
+
"tslib": "^2.4.1",
|
| 20 |
+
"typescript": "^5.0.0",
|
| 21 |
+
"vite": "^5.0.3"
|
| 22 |
+
},
|
| 23 |
+
"dependencies": {
|
| 24 |
+
"@threlte/core": "^7.1.0",
|
| 25 |
+
"@threlte/extras": "^8.7.5",
|
| 26 |
+
"three": "^0.160.1",
|
| 27 |
+
"tailwindcss": "^3.4.0",
|
| 28 |
+
"autoprefixer": "^10.4.16",
|
| 29 |
+
"postcss": "^8.4.32"
|
| 30 |
+
}
|
| 31 |
+
}
|
frontend/postcss.config.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
export default {
|
| 2 |
+
plugins: {
|
| 3 |
+
tailwindcss: {},
|
| 4 |
+
autoprefixer: {},
|
| 5 |
+
},
|
| 6 |
+
}
|
frontend/src/app.css
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
@import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&family=Inter:wght@400;500;600;700&display=swap');
|
| 2 |
+
@tailwind base;
|
| 3 |
+
@tailwind components;
|
| 4 |
+
@tailwind utilities;
|
| 5 |
+
|
| 6 |
+
@layer base {
|
| 7 |
+
body {
|
| 8 |
+
@apply bg-black text-white;
|
| 9 |
+
}
|
| 10 |
+
}
|
| 11 |
+
|
| 12 |
+
@layer components {
|
| 13 |
+
/* CRT effect */
|
| 14 |
+
.crt-effect {
|
| 15 |
+
position: relative;
|
| 16 |
+
overflow: hidden;
|
| 17 |
+
}
|
| 18 |
+
|
| 19 |
+
.crt-effect::before {
|
| 20 |
+
content: " ";
|
| 21 |
+
display: block;
|
| 22 |
+
position: absolute;
|
| 23 |
+
top: 0;
|
| 24 |
+
left: 0;
|
| 25 |
+
bottom: 0;
|
| 26 |
+
right: 0;
|
| 27 |
+
background: linear-gradient(
|
| 28 |
+
rgba(18, 16, 16, 0) 50%,
|
| 29 |
+
rgba(0, 0, 0, 0.25) 50%
|
| 30 |
+
);
|
| 31 |
+
background-size: 100% 2px;
|
| 32 |
+
z-index: 2;
|
| 33 |
+
pointer-events: none;
|
| 34 |
+
animation: scan-lines 8s linear infinite;
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
.crt-effect::after {
|
| 38 |
+
content: " ";
|
| 39 |
+
display: block;
|
| 40 |
+
position: absolute;
|
| 41 |
+
top: 0;
|
| 42 |
+
left: 0;
|
| 43 |
+
bottom: 0;
|
| 44 |
+
right: 0;
|
| 45 |
+
background: rgba(18, 16, 16, 0.1);
|
| 46 |
+
opacity: 0;
|
| 47 |
+
z-index: 2;
|
| 48 |
+
pointer-events: none;
|
| 49 |
+
animation: flicker 0.15s infinite;
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
/* Holographic button */
|
| 53 |
+
.holographic-button {
|
| 54 |
+
@apply relative px-4 py-2 font-pixel text-xs uppercase tracking-wider;
|
| 55 |
+
background: linear-gradient(45deg, #00CED1, #FF6B00, #00CED1);
|
| 56 |
+
background-size: 200% 200%;
|
| 57 |
+
animation: hologram 3s ease-in-out infinite;
|
| 58 |
+
clip-path: polygon(10% 0%, 100% 0%, 90% 100%, 0% 100%);
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
.holographic-button:hover {
|
| 62 |
+
@apply brightness-125;
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
/* Device frame */
|
| 66 |
+
.device-frame {
|
| 67 |
+
@apply relative bg-digipal-gray rounded-3xl p-8 shadow-2xl;
|
| 68 |
+
background-image:
|
| 69 |
+
radial-gradient(circle at 20% 80%, #FF6B00 0%, transparent 50%),
|
| 70 |
+
radial-gradient(circle at 80% 20%, #00CED1 0%, transparent 50%),
|
| 71 |
+
radial-gradient(circle at 40% 40%, #2D2D2D 0%, transparent 50%);
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
/* D-pad button */
|
| 75 |
+
.dpad-button {
|
| 76 |
+
@apply bg-gray-800 hover:bg-gray-700 active:bg-gray-900 transition-colors;
|
| 77 |
+
@apply border-2 border-gray-600;
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
/* Action button */
|
| 81 |
+
.action-button {
|
| 82 |
+
@apply rounded-full bg-gradient-to-br from-gray-700 to-gray-900;
|
| 83 |
+
@apply hover:from-gray-600 hover:to-gray-800 active:from-gray-800 active:to-black;
|
| 84 |
+
@apply transition-all duration-150 transform active:scale-95;
|
| 85 |
+
@apply shadow-lg;
|
| 86 |
+
}
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
@keyframes flicker {
|
| 90 |
+
0% {
|
| 91 |
+
opacity: 0.27861;
|
| 92 |
+
}
|
| 93 |
+
5% {
|
| 94 |
+
opacity: 0.34769;
|
| 95 |
+
}
|
| 96 |
+
10% {
|
| 97 |
+
opacity: 0.23604;
|
| 98 |
+
}
|
| 99 |
+
15% {
|
| 100 |
+
opacity: 0.90626;
|
| 101 |
+
}
|
| 102 |
+
20% {
|
| 103 |
+
opacity: 0.18128;
|
| 104 |
+
}
|
| 105 |
+
25% {
|
| 106 |
+
opacity: 0.83891;
|
| 107 |
+
}
|
| 108 |
+
30% {
|
| 109 |
+
opacity: 0.65583;
|
| 110 |
+
}
|
| 111 |
+
35% {
|
| 112 |
+
opacity: 0.67807;
|
| 113 |
+
}
|
| 114 |
+
40% {
|
| 115 |
+
opacity: 0.26559;
|
| 116 |
+
}
|
| 117 |
+
45% {
|
| 118 |
+
opacity: 0.84693;
|
| 119 |
+
}
|
| 120 |
+
50% {
|
| 121 |
+
opacity: 0.96019;
|
| 122 |
+
}
|
| 123 |
+
55% {
|
| 124 |
+
opacity: 0.08594;
|
| 125 |
+
}
|
| 126 |
+
60% {
|
| 127 |
+
opacity: 0.20313;
|
| 128 |
+
}
|
| 129 |
+
65% {
|
| 130 |
+
opacity: 0.71988;
|
| 131 |
+
}
|
| 132 |
+
70% {
|
| 133 |
+
opacity: 0.53455;
|
| 134 |
+
}
|
| 135 |
+
75% {
|
| 136 |
+
opacity: 0.37288;
|
| 137 |
+
}
|
| 138 |
+
80% {
|
| 139 |
+
opacity: 0.71428;
|
| 140 |
+
}
|
| 141 |
+
85% {
|
| 142 |
+
opacity: 0.70419;
|
| 143 |
+
}
|
| 144 |
+
90% {
|
| 145 |
+
opacity: 0.7003;
|
| 146 |
+
}
|
| 147 |
+
95% {
|
| 148 |
+
opacity: 0.36108;
|
| 149 |
+
}
|
| 150 |
+
100% {
|
| 151 |
+
opacity: 0.24387;
|
| 152 |
+
}
|
| 153 |
+
}
|
frontend/src/routes/+layout.svelte
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<script>
|
| 2 |
+
import '../app.css';
|
| 3 |
+
</script>
|
| 4 |
+
|
| 5 |
+
<slot />
|
frontend/src/routes/+page.svelte
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<script lang="ts">
|
| 2 |
+
import Device from '$lib/components/Device.svelte';
|
| 3 |
+
import { monsterStore } from '$lib/stores/monsterStore';
|
| 4 |
+
import { onMount } from 'svelte';
|
| 5 |
+
|
| 6 |
+
onMount(() => {
|
| 7 |
+
// Initialize the app
|
| 8 |
+
monsterStore.initialize();
|
| 9 |
+
});
|
| 10 |
+
</script>
|
| 11 |
+
|
| 12 |
+
<main class="min-h-screen flex items-center justify-center bg-gradient-to-br from-gray-900 via-black to-gray-900">
|
| 13 |
+
<Device />
|
| 14 |
+
</main>
|
frontend/svelte.config.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import adapter from '@sveltejs/adapter-auto';
|
| 2 |
+
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
| 3 |
+
|
| 4 |
+
/** @type {import('@sveltejs/kit').Config} */
|
| 5 |
+
const config = {
|
| 6 |
+
// Consult https://kit.svelte.dev/docs/integrations#preprocessors
|
| 7 |
+
preprocess: vitePreprocess(),
|
| 8 |
+
|
| 9 |
+
kit: {
|
| 10 |
+
adapter: adapter()
|
| 11 |
+
}
|
| 12 |
+
};
|
| 13 |
+
|
| 14 |
+
export default config;
|
frontend/tailwind.config.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/** @type {import('tailwindcss').Config} */
|
| 2 |
+
export default {
|
| 3 |
+
content: ['./src/**/*.{html,js,svelte,ts}'],
|
| 4 |
+
theme: {
|
| 5 |
+
extend: {
|
| 6 |
+
colors: {
|
| 7 |
+
'digipal-orange': '#FF6B00',
|
| 8 |
+
'digipal-teal': '#00CED1',
|
| 9 |
+
'digipal-gray': '#2D2D2D',
|
| 10 |
+
'neon-magenta': '#FF00FF',
|
| 11 |
+
'neon-cyan': '#00FFFF',
|
| 12 |
+
},
|
| 13 |
+
fontFamily: {
|
| 14 |
+
'pixel': ['Press Start 2P', 'monospace'],
|
| 15 |
+
'modern': ['Inter', 'sans-serif'],
|
| 16 |
+
},
|
| 17 |
+
animation: {
|
| 18 |
+
'scan-lines': 'scan-lines 8s linear infinite',
|
| 19 |
+
'glitch': 'glitch 2s ease-in-out infinite alternate',
|
| 20 |
+
'hologram': 'hologram 3s ease-in-out infinite',
|
| 21 |
+
},
|
| 22 |
+
keyframes: {
|
| 23 |
+
'scan-lines': {
|
| 24 |
+
'0%': { transform: 'translateY(0)' },
|
| 25 |
+
'100%': { transform: 'translateY(100%)' },
|
| 26 |
+
},
|
| 27 |
+
'glitch': {
|
| 28 |
+
'0%': {
|
| 29 |
+
textShadow: '0.05em 0 0 #00fffc, -0.03em -0.04em 0 #fc00ff, 0.025em 0.04em 0 #fffc00'
|
| 30 |
+
},
|
| 31 |
+
'15%': {
|
| 32 |
+
textShadow: '0.05em 0 0 #00fffc, -0.03em -0.04em 0 #fc00ff, 0.025em 0.04em 0 #fffc00'
|
| 33 |
+
},
|
| 34 |
+
'16%': {
|
| 35 |
+
textShadow: '-0.05em -0.025em 0 #00fffc, 0.025em 0.035em 0 #fc00ff, -0.05em -0.05em 0 #fffc00'
|
| 36 |
+
},
|
| 37 |
+
'49%': {
|
| 38 |
+
textShadow: '-0.05em -0.025em 0 #00fffc, 0.025em 0.035em 0 #fc00ff, -0.05em -0.05em 0 #fffc00'
|
| 39 |
+
},
|
| 40 |
+
'50%': {
|
| 41 |
+
textShadow: '0.05em 0.035em 0 #00fffc, 0.03em 0 0 #fc00ff, 0 -0.04em 0 #fffc00'
|
| 42 |
+
},
|
| 43 |
+
'99%': {
|
| 44 |
+
textShadow: '0.05em 0.035em 0 #00fffc, 0.03em 0 0 #fc00ff, 0 -0.04em 0 #fffc00'
|
| 45 |
+
},
|
| 46 |
+
'100%': {
|
| 47 |
+
textShadow: '-0.05em 0 0 #00fffc, -0.025em -0.04em 0 #fc00ff, -0.04em -0.025em 0 #fffc00'
|
| 48 |
+
},
|
| 49 |
+
},
|
| 50 |
+
'hologram': {
|
| 51 |
+
'0%, 100%': { opacity: '1' },
|
| 52 |
+
'50%': { opacity: '0.7' },
|
| 53 |
+
},
|
| 54 |
+
},
|
| 55 |
+
},
|
| 56 |
+
},
|
| 57 |
+
plugins: [],
|
| 58 |
+
}
|
frontend/tsconfig.json
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"extends": "./.svelte-kit/tsconfig.json",
|
| 3 |
+
"compilerOptions": {
|
| 4 |
+
"allowJs": true,
|
| 5 |
+
"checkJs": true,
|
| 6 |
+
"esModuleInterop": true,
|
| 7 |
+
"forceConsistentCasingInFileNames": true,
|
| 8 |
+
"resolveJsonModule": true,
|
| 9 |
+
"skipLibCheck": true,
|
| 10 |
+
"sourceMap": true,
|
| 11 |
+
"strict": true
|
| 12 |
+
}
|
| 13 |
+
}
|
frontend/vite.config.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { sveltekit } from '@sveltejs/kit/vite';
|
| 2 |
+
import { defineConfig } from 'vite';
|
| 3 |
+
|
| 4 |
+
export default defineConfig({
|
| 5 |
+
plugins: [sveltekit()],
|
| 6 |
+
server: {
|
| 7 |
+
proxy: {
|
| 8 |
+
'/api': {
|
| 9 |
+
target: 'http://localhost:7861',
|
| 10 |
+
changeOrigin: true
|
| 11 |
+
},
|
| 12 |
+
'/api/ws': {
|
| 13 |
+
target: 'ws://localhost:7861',
|
| 14 |
+
ws: true
|
| 15 |
+
}
|
| 16 |
+
}
|
| 17 |
+
}
|
| 18 |
+
});
|
requirements.txt
CHANGED
|
@@ -21,6 +21,7 @@ webrtcvad>=2.0.10
|
|
| 21 |
fastapi>=0.108.0
|
| 22 |
uvicorn[standard]>=0.25.0
|
| 23 |
pydantic>=2.5.0
|
|
|
|
| 24 |
|
| 25 |
# Advanced State Management
|
| 26 |
apscheduler>=3.10.4
|
|
|
|
| 21 |
fastapi>=0.108.0
|
| 22 |
uvicorn[standard]>=0.25.0
|
| 23 |
pydantic>=2.5.0
|
| 24 |
+
websockets>=12.0
|
| 25 |
|
| 26 |
# Advanced State Management
|
| 27 |
apscheduler>=3.10.4
|