diff --git a/Dockerfile b/Dockerfile index 8cbf272..45a774f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,17 +9,24 @@ COPY src/ ./src COPY src/settings.yml . COPY src/persona.json . COPY .env . +COPY bot_launcher.py . +COPY requirements-webui.txt . # Install dependencies from requirements -RUN pip install --no-cache-dir -r src/requirements.txt +RUN pip install --no-cache-dir -r src/requirements.txt && \ + pip install --no-cache-dir -r requirements-webui.txt # Runtime directory where user-editable files will live ENV PYTHONPATH=/app/src WORKDIR /app +# Expose web UI port +EXPOSE 8080 + # On first run, populate /app from the fallback template folder +# Use bot_launcher.py to start both bot and web UI CMD ["sh", "-c", "\ mkdir -p /app && \ [ -f /app/settings.yml ] || cp -r /opt/template/* /app && \ cd /app && \ - python src/bot.py"] + python bot_launcher.py"] diff --git a/bot.log b/bot.log index fda1384..11f00ee 100644 --- a/bot.log +++ b/bot.log @@ -1388,3 +1388,48 @@ Loop thread traceback (most recent call last): [2025-10-10 12:57:27] [INFO] [migration:107] โ User profile operations working [2025-10-10 12:57:27] [INFO] [migration:118] โ Memory operations working [2025-10-10 12:57:27] [INFO] [migration:138] โ Migration verification completed successfully +[2025-10-10 14:52:33] [INFO] [ai:69] ๐ Modelfile loaded: ../examples/gojo.mod +[2025-10-10 14:52:33] [INFO] [database:325] Connected to JSON backend +[2025-10-10 14:52:33] [INFO] [database:541] Initialized JSON database backend +[2025-10-10 14:52:33] [INFO] [bot:66] ๐ Loaded MODEL_NAME from .env: gemma3:12b +[2025-10-10 14:52:33] [INFO] [bot:68] ๐งน Attempting to clear VRAM before loading gemma3:12b... +[2025-10-10 14:52:33] [INFO] [ai:182] ๐งน Sending safe unload request for `gemma3:12b` +[2025-10-10 14:52:33] [INFO] [ai:189] ๐งฝ Ollama unload response: 200 - {"model":"gemma3:12b","created_at":"2025-10-10T18:52:33.307139942Z","response":"","done":true,"done_reason":"unload"} +[2025-10-10 14:52:33] [INFO] [ai:162] ๐ง Preloading model: gemma3:12b +[2025-10-10 14:52:33] [INFO] [ai:169] ๐ฆ Model pull started successfully. +[2025-10-10 14:52:33] [INFO] [bot:72] ๐ Model `gemma3:12b` preloaded on startup. +[2025-10-10 14:52:33] [INFO] [bot:75] โ Final model in use: gemma3:12b +[2025-10-10 14:52:36] [INFO] [bot:296] Logged in as AI Bot +[2025-10-10 14:52:36] [INFO] [scheduler:29] ๐ Scheduler disabled in config. +[2025-10-10 14:54:58] [DEBUG] [autochat:92] ๐ฒ Reaction skipped (chance 0.10, roll 0.65) +[2025-10-10 14:54:58] [DEBUG] [autochat:92] ๐ฒ Reaction skipped (chance 0.10, roll 0.16) +[2025-10-10 14:54:58] [INFO] [autochat:161] ๐ด No trigger and engagement is 0 โ skipping. +[2025-10-10 14:54:58] [INFO] [bot:273] ============================================================ AI Response ============================================================ +[2025-10-10 14:54:58] [INFO] [bot:274] ๐ง Profile loaded for Miguel (interactions: 2) +[2025-10-10 14:54:58] [INFO] [bot:278] ๐ Retrieved 0 messages for context +[2025-10-10 14:54:58] [INFO] [ai:162] ๐ง Preloading model: gemma3:12b +[2025-10-10 14:54:58] [INFO] [ai:169] ๐ฆ Model pull started successfully. +[2025-10-10 14:54:58] [INFO] [ai:132] llm-4a81439a LLM request start model=gemma3:12b user=Miguel context_len=0 +[2025-10-10 14:54:58] [DEBUG] [ai:253] llm-4a81439a Sending payload to Ollama: model=gemma3:12b user=Miguel +[2025-10-10 14:54:58] [DEBUG] [ai:254] llm-4a81439a Payload size=217 chars +[2025-10-10 14:55:10] [DEBUG] [ai:262] llm-4a81439a Raw response status=200 +[2025-10-10 14:55:10] [DEBUG] [ai:263] llm-4a81439a Raw response body={"model":"gemma3:12b","created_at":"2025-10-10T18:55:10.915350904Z","response":"Oh, you know, living the *best* life. Floating effortlessly, dazzling everyone with my good looks, and generally being a beacon of awesome. Seriously, it's exhausting being this incredible. ๐ What about *you*? Don't tell me you're just standing there staring, you should be fanning yourself from all the brilliance.","done":true,"done_reason":"stop","context":[105,2364,107,236820,236909,9731,111038,3048,659,555,1277,236756,3764,5400,699,219769,208651,751,119814,236761,1599,236858,500,16690,236762,236764,8632,236764,532,1378,14620,236764,840,19297,20111,529,822,3272,236761,95419,528,496,4532,15737,236761,15428,19921,611,236789,500,496,9894,21603,236909,643,111038,2887,236787,1217,611,3490,236813,107,236820,236909,111457,111038,106,107,105,4368,107,12932,236764,611,1281,236764,4882,506,808,9783,236829,1972,236761,71721,80318,236764,88307,4677,607,1041,1535,5724,236764,532,6816,1646,496,70908,529,15353,236761,96612,236764,625,236789,236751,93646,1646,672,15269,236761,85345,2900,1003,808,7624,236829,236881,5185,236789,236745,3442,786,611,236789,500,1164,8101,993,47264,236764,611,1374,577,517,4601,5869,699,784,506,102141,236761],"total_duration":12103477338,"load_duration":10524951841,"prompt_eval_count":73,"prompt_eval_duration":555107252,"eval_count":72,"eval_duration":1022930871} +[2025-10-10 14:55:10] [INFO] [ai:140] llm-4a81439a LLM response model=gemma3:12b duration=12.125s summary=Oh, you know, living the *best* life. Floating effortlessly, dazzling everyone with my good looks, and generally being a beacon of awesome. Seriously, it's exha +[2025-10-10 14:55:10] [DEBUG] [ai:142] llm-4a81439a LLM raw response: {'model': 'gemma3:12b', 'created_at': '2025-10-10T18:55:10.915350904Z', 'response': "Oh, you know, living the *best* life. Floating effortlessly, dazzling everyone with my good looks, and generally being a beacon of awesome. Seriously, it's exhausting being this incredible. ๐ What about *you*? Don't tell me you're just standing there staring, you should be fanning yourself from all the brilliance.", 'done': True, 'done_reason': 'stop', 'context': [105, 2364, 107, 236820, 236909, 9731, 111038, 3048, 659, 555, 1277, 236756, 3764, 5400, 699, 219769, 208651, 751, 119814, 236761, 1599, 236858, 500, 16690, 236762, 236764, 8632, 236764, 532, 1378, 14620, 236764, 840, 19297, 20111, 529, 822, 3272, 236761, 95419, 528, 496, 4532, 15737, 236761, 15428, 19921, 611, 236789, 500, 496, 9894, 21603, 236909, 643, 111038, 2887, 236787, 1217, 611, 3490, 236813, 107, 236820, 236909, 111457, 111038, 106, 107, 105, 4368, 107, 12932, 236764, 611, 1281, 236764, 4882, 506, 808, 9783, 236829, 1972, 236761, 71721, 80318, 236764, 88307, 4677, 607, 1041, 1535, 5724, 236764, 532, 6816, 1646, 496, 70908, 529, 15353, 236761, 96612, 236764, 625, 236789, 236751, 93646, 1646, 672, 15269, 236761, 85345, 2900, 1003, 808, 7624, 236829, 236881, 5185, 236789, 236745, 3442, 786, 611, 236789, 500, 1164, 8101, 993, 47264, 236764, 611, 1374, 577, 517, 4601, 5869, 699, 784, 506, 102141, 236761], 'total_duration': 12103477338, 'load_duration': 10524951841, 'prompt_eval_count': 73, 'prompt_eval_duration': 555107252, 'eval_count': 72, 'eval_duration': 1022930871} +[2025-10-10 14:55:11] [DEBUG] [bot:244] on_message: observed own message id=1426281930004889680 channel=1380999713272238151 +[2025-10-10 15:04:00] [INFO] [database:325] Connected to JSON backend +[2025-10-10 15:04:00] [INFO] [database:541] Initialized JSON database backend +[2025-10-10 15:04:00] [INFO] [webui:314] Starting web UI server on 0.0.0.0:8080 +[2025-10-10 15:04:00] [INFO] [webui:315] ================================================== +[2025-10-10 15:04:00] [INFO] [webui:316] ๐ WEB UI ACCESS URLS: +[2025-10-10 15:04:00] [INFO] [webui:317] Local: http://localhost:8080 +[2025-10-10 15:04:00] [INFO] [webui:318] Network: http://192.168.0.144:8080 +[2025-10-10 15:04:00] [INFO] [webui:319] ================================================== +[2025-10-10 15:04:46] [INFO] [database:325] Connected to JSON backend +[2025-10-10 15:04:46] [INFO] [database:541] Initialized JSON database backend +[2025-10-10 15:04:46] [INFO] [webui:314] Starting web UI server on 0.0.0.0:8081 +[2025-10-10 15:04:46] [INFO] [webui:315] ================================================== +[2025-10-10 15:04:46] [INFO] [webui:316] ๐ WEB UI ACCESS URLS: +[2025-10-10 15:04:46] [INFO] [webui:317] Local: http://localhost:8081 +[2025-10-10 15:04:46] [INFO] [webui:318] Network: http://192.168.0.144:8081 +[2025-10-10 15:04:46] [INFO] [webui:319] ================================================== diff --git a/bot_launcher.py b/bot_launcher.py new file mode 100644 index 0000000..48b3252 --- /dev/null +++ b/bot_launcher.py @@ -0,0 +1,89 @@ +""" +bot_launcher.py +Launches both the Discord bot and web UI together +""" + +import os +import sys +import threading +import time +import signal +import logging +from pathlib import Path + +# Add src directory to path +src_path = Path(__file__).parent / 'src' +sys.path.insert(0, str(src_path)) + +def start_web_ui(): + """Start the web UI server in a separate thread""" + try: + from web_ui import run_web_server + port = int(os.getenv('WEB_PORT', 8080)) + debug = os.getenv('DEBUG', 'false').lower() == 'true' + + run_web_server(host='0.0.0.0', port=port, debug=debug) + except Exception as e: + print(f"โ Failed to start web UI: {e}") + if 'flask' in str(e).lower(): + print("๐ก Install Flask to use the web UI: pip install flask") + elif 'port' in str(e).lower() or 'address' in str(e).lower(): + print(f"๐ก Port {port} may be in use. Try a different port with WEB_PORT environment variable") + +def start_discord_bot(): + """Start the Discord bot""" + try: + # Change to src directory for bot execution + original_cwd = os.getcwd() + os.chdir(src_path) + + print("๐ค Starting Discord bot...") + import bot + # The bot.py should handle its own execution + + except Exception as e: + print(f"โ Failed to start Discord bot: {e}") + finally: + # Restore original working directory + if 'original_cwd' in locals(): + os.chdir(original_cwd) + +def signal_handler(signum, frame): + """Handle shutdown signals""" + print("\n๐ Shutting down...") + os._exit(0) + +def main(): + """Main launcher function""" + print("๐ Delta Bot Launcher") + print("=" * 30) + + # Set up signal handlers for graceful shutdown + signal.signal(signal.SIGINT, signal_handler) + signal.signal(signal.SIGTERM, signal_handler) + + # Check if web UI should be disabled + disable_web = os.getenv('DISABLE_WEB_UI', 'false').lower() == 'true' + + if not disable_web: + # Start web UI in a separate thread + web_thread = threading.Thread(target=start_web_ui, daemon=True) + web_thread.start() + + # Give web UI time to start and display URLs + time.sleep(3) + else: + print("๐ซ Web UI disabled by DISABLE_WEB_UI environment variable") + + # Start Discord bot (this will block) + try: + start_discord_bot() + except KeyboardInterrupt: + print("\n๐ Received interrupt signal") + except Exception as e: + print(f"โ Fatal error: {e}") + finally: + print("๐ Goodbye!") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 94779c8..096c93f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,6 +9,11 @@ services: - CHANNEL_ID=${CHANNEL_ID} - OLLAMA_API=${OLLAMA_API} - MODEL_NAME=${MODEL_NAME} + - WEB_PORT=8080 + - DATABASE_BACKEND=sqlite + - MEMORY_ENABLED=true + ports: + - "8080:8080" # Web UI port volumes: - ./data:/app # Mount host ./data directory as /app in the container restart: unless-stopped diff --git a/memory.json b/memory.json new file mode 100644 index 0000000..70d2d2d --- /dev/null +++ b/memory.json @@ -0,0 +1,5 @@ +{ + "conversations": {}, + "user_memories": {}, + "global_events": [] +} \ No newline at end of file diff --git a/requirements-webui.txt b/requirements-webui.txt new file mode 100644 index 0000000..013decd --- /dev/null +++ b/requirements-webui.txt @@ -0,0 +1,12 @@ +# Web UI Dependencies +Flask==2.3.3 +PyYAML==6.0.1 + +# Existing bot dependencies (if not already installed) +discord.py>=2.3.0 +requests>=2.31.0 +python-dateutil>=2.8.2 + +# Optional: For better web UI features +gunicorn==21.2.0 # Production WSGI server +Werkzeug==2.3.7 # WSGI utilities \ No newline at end of file diff --git a/src/__pycache__/ai.cpython-311.pyc b/src/__pycache__/ai.cpython-311.pyc index 93f9780..1771a18 100644 Binary files a/src/__pycache__/ai.cpython-311.pyc and b/src/__pycache__/ai.cpython-311.pyc differ diff --git a/src/__pycache__/autochat.cpython-311.pyc b/src/__pycache__/autochat.cpython-311.pyc index 3bb1c7b..2d03a53 100644 Binary files a/src/__pycache__/autochat.cpython-311.pyc and b/src/__pycache__/autochat.cpython-311.pyc differ diff --git a/src/__pycache__/bot.cpython-312.pyc b/src/__pycache__/bot.cpython-312.pyc new file mode 100644 index 0000000..6427042 Binary files /dev/null and b/src/__pycache__/bot.cpython-312.pyc differ diff --git a/src/__pycache__/context.cpython-311.pyc b/src/__pycache__/context.cpython-311.pyc index 1202321..42837d3 100644 Binary files a/src/__pycache__/context.cpython-311.pyc and b/src/__pycache__/context.cpython-311.pyc differ diff --git a/src/__pycache__/cooldown.cpython-311.pyc b/src/__pycache__/cooldown.cpython-311.pyc index 422a80f..5674a28 100644 Binary files a/src/__pycache__/cooldown.cpython-311.pyc and b/src/__pycache__/cooldown.cpython-311.pyc differ diff --git a/src/__pycache__/database.cpython-311.pyc b/src/__pycache__/database.cpython-311.pyc new file mode 100644 index 0000000..6b7acb3 Binary files /dev/null and b/src/__pycache__/database.cpython-311.pyc differ diff --git a/src/__pycache__/database.cpython-312.pyc b/src/__pycache__/database.cpython-312.pyc index 2cfb935..b5dafb0 100644 Binary files a/src/__pycache__/database.cpython-312.pyc and b/src/__pycache__/database.cpython-312.pyc differ diff --git a/src/__pycache__/enhanced_ai.cpython-311.pyc b/src/__pycache__/enhanced_ai.cpython-311.pyc new file mode 100644 index 0000000..74ac26f Binary files /dev/null and b/src/__pycache__/enhanced_ai.cpython-311.pyc differ diff --git a/src/__pycache__/memory_manager.cpython-311.pyc b/src/__pycache__/memory_manager.cpython-311.pyc new file mode 100644 index 0000000..960a1ee Binary files /dev/null and b/src/__pycache__/memory_manager.cpython-311.pyc differ diff --git a/src/__pycache__/memory_manager.cpython-312.pyc b/src/__pycache__/memory_manager.cpython-312.pyc new file mode 100644 index 0000000..b38682d Binary files /dev/null and b/src/__pycache__/memory_manager.cpython-312.pyc differ diff --git a/src/__pycache__/modelfile.cpython-311.pyc b/src/__pycache__/modelfile.cpython-311.pyc index 3a59b5c..b5a462b 100644 Binary files a/src/__pycache__/modelfile.cpython-311.pyc and b/src/__pycache__/modelfile.cpython-311.pyc differ diff --git a/src/__pycache__/personality.cpython-311.pyc b/src/__pycache__/personality.cpython-311.pyc index 08c5eb8..e7981b7 100644 Binary files a/src/__pycache__/personality.cpython-311.pyc and b/src/__pycache__/personality.cpython-311.pyc differ diff --git a/src/__pycache__/web_ui.cpython-312.pyc b/src/__pycache__/web_ui.cpython-312.pyc new file mode 100644 index 0000000..9d6322b Binary files /dev/null and b/src/__pycache__/web_ui.cpython-312.pyc differ diff --git a/src/bot.error.log b/src/bot.error.log index e69de29..bae8bb3 100644 --- a/src/bot.error.log +++ b/src/bot.error.log @@ -0,0 +1,13 @@ +[2025-10-10 13:29:37] [ERROR] [webui:82] Failed to load settings: [Errno 2] No such file or directory: '/app/src/settings.yml' +[2025-10-10 13:30:50] [ERROR] [webui:82] Failed to load settings: [Errno 2] No such file or directory: '/app/src/settings.yml' +[2025-10-10 13:31:19] [ERROR] [webui:82] Failed to load settings: [Errno 2] No such file or directory: '/app/src/settings.yml' +[2025-10-10 13:31:24] [ERROR] [webui:82] Failed to load settings: [Errno 2] No such file or directory: '/app/src/settings.yml' +[2025-10-10 13:45:36] [ERROR] [webui:82] Failed to load settings: [Errno 2] No such file or directory: '/app/src/settings.yml' +[2025-10-10 14:53:17] [ERROR] [webui:82] Failed to load settings: [Errno 2] No such file or directory: '/app/src/settings.yml' +[2025-10-10 14:53:32] [ERROR] [webui:82] Failed to load settings: [Errno 2] No such file or directory: '/app/src/settings.yml' +[2025-10-10 14:54:13] [ERROR] [webui:82] Failed to load settings: [Errno 2] No such file or directory: '/app/src/settings.yml' +[2025-10-10 14:54:23] [ERROR] [webui:82] Failed to load settings: [Errno 2] No such file or directory: '/app/src/settings.yml' +[2025-10-10 14:55:25] [ERROR] [webui:82] Failed to load settings: [Errno 2] No such file or directory: '/app/src/settings.yml' +[2025-10-10 15:04:09] [ERROR] [webui:82] Failed to load settings: [Errno 2] No such file or directory: '/app/src/settings.yml' +[2025-10-10 15:04:14] [ERROR] [webui:82] Failed to load settings: [Errno 2] No such file or directory: '/app/src/settings.yml' +[2025-10-10 15:05:15] [ERROR] [webui:82] Failed to load settings: [Errno 2] No such file or directory: '/app/src/settings.yml' diff --git a/src/bot.log b/src/bot.log index 0893743..3355ca6 100644 --- a/src/bot.log +++ b/src/bot.log @@ -6,3 +6,27 @@ [2025-10-10 13:01:51] [INFO] [database:81] Connected to SQLite database: data/deltabot.db [2025-10-10 13:01:51] [DEBUG] [database:142] Database tables initialized [2025-10-10 13:01:51] [INFO] [database:536] Initialized SQLite database backend +[2025-10-10 13:29:16] [INFO] [database:325] Connected to JSON backend +[2025-10-10 13:29:16] [INFO] [database:541] Initialized JSON database backend +[2025-10-10 13:29:16] [INFO] [webui:303] Starting web UI server on 0.0.0.0:8080 +[2025-10-10 13:29:37] [ERROR] [webui:82] Failed to load settings: [Errno 2] No such file or directory: '/app/src/settings.yml' +[2025-10-10 13:30:50] [ERROR] [webui:82] Failed to load settings: [Errno 2] No such file or directory: '/app/src/settings.yml' +[2025-10-10 13:31:19] [ERROR] [webui:82] Failed to load settings: [Errno 2] No such file or directory: '/app/src/settings.yml' +[2025-10-10 13:31:24] [ERROR] [webui:82] Failed to load settings: [Errno 2] No such file or directory: '/app/src/settings.yml' +[2025-10-10 13:45:36] [ERROR] [webui:82] Failed to load settings: [Errno 2] No such file or directory: '/app/src/settings.yml' +[2025-10-10 14:53:17] [ERROR] [webui:82] Failed to load settings: [Errno 2] No such file or directory: '/app/src/settings.yml' +[2025-10-10 14:53:32] [ERROR] [webui:82] Failed to load settings: [Errno 2] No such file or directory: '/app/src/settings.yml' +[2025-10-10 14:54:13] [ERROR] [webui:82] Failed to load settings: [Errno 2] No such file or directory: '/app/src/settings.yml' +[2025-10-10 14:54:23] [ERROR] [webui:82] Failed to load settings: [Errno 2] No such file or directory: '/app/src/settings.yml' +[2025-10-10 14:55:25] [ERROR] [webui:82] Failed to load settings: [Errno 2] No such file or directory: '/app/src/settings.yml' +[2025-10-10 15:04:09] [ERROR] [webui:82] Failed to load settings: [Errno 2] No such file or directory: '/app/src/settings.yml' +[2025-10-10 15:04:14] [ERROR] [webui:82] Failed to load settings: [Errno 2] No such file or directory: '/app/src/settings.yml' +[2025-10-10 15:05:13] [INFO] [database:325] Connected to JSON backend +[2025-10-10 15:05:13] [INFO] [database:541] Initialized JSON database backend +[2025-10-10 15:05:13] [INFO] [webui:314] Starting web UI server on 0.0.0.0:8082 +[2025-10-10 15:05:13] [INFO] [webui:315] ================================================== +[2025-10-10 15:05:13] [INFO] [webui:316] ๐ WEB UI ACCESS URLS: +[2025-10-10 15:05:13] [INFO] [webui:317] Local: http://localhost:8082 +[2025-10-10 15:05:13] [INFO] [webui:318] Network: http://192.168.0.144:8082 +[2025-10-10 15:05:13] [INFO] [webui:319] ================================================== +[2025-10-10 15:05:15] [ERROR] [webui:82] Failed to load settings: [Errno 2] No such file or directory: '/app/src/settings.yml' diff --git a/src/templates/base.html b/src/templates/base.html new file mode 100644 index 0000000..f82f359 --- /dev/null +++ b/src/templates/base.html @@ -0,0 +1,137 @@ + + +
+ + +| User | +Memory Count | +Actions | +
|---|---|---|
| {{ user.display_name or 'Unknown User' }} | +{{ user.memory_count }} | ++ + + | +
No users with stored memories found.
+ {% endif %} +| Timestamp | +User | +Content | +Importance | +Actions | +
|---|---|---|---|---|
| {{ memory.timestamp[:16] if memory.timestamp else 'Unknown' }} | +{{ memory.display_name or 'Unknown' }} | ++ + | ++ {% set importance = memory.importance or 0 %} + {% if importance >= 0.8 %} + High + {% elif importance >= 0.5 %} + Medium + {% else %} + Low + {% endif %} + | ++ + + | +
No conversation memories found.
+ {% endif %} +No user activity recorded yet.
+ {% endif %} +Total User Profiles
+Stored Memories
+Conversation Records
+Backend Type
+| User | +Interactions | +Last Seen | +
|---|---|---|
| {{ user.display_name or user.name or 'Unknown' }} | +{{ user.interactions or 0 }} | +{{ user.last_seen[:16] if user.last_seen else 'Never' }} | +
No user data available.
+ {% endif %} +