diff --git a/conversation_history.db b/conversation_history.db index 7999f81..11e38c6 100644 Binary files a/conversation_history.db and b/conversation_history.db differ diff --git a/conversation_history.db-shm b/conversation_history.db-shm index ac2fed6..36ed04c 100644 Binary files a/conversation_history.db-shm and b/conversation_history.db-shm differ diff --git a/conversation_history.db-wal b/conversation_history.db-wal index d5abc74..e69de29 100644 Binary files a/conversation_history.db-wal and b/conversation_history.db-wal differ diff --git a/discord_bot.log b/discord_bot.log index 2a3da44..c7b00ca 100644 --- a/discord_bot.log +++ b/discord_bot.log @@ -26807,3 +26807,259 @@ Max Tokens: 1000 2025-02-11 19:46:23 - DEBUG - discord_bot - save_state:62 - Queue state saved - Pending messages: 0 2025-02-11 19:47:23 - INFO - discord_bot - _process_queue:295 - Queue processor 37c33154 heartbeat - Active: True, Queue size: 0, Processing: 0, Total processed: 1859 2025-02-11 19:47:23 - DEBUG - discord_bot - save_state:62 - Queue state saved - Pending messages: 0 +2025-02-11 19:48:53 - INFO - discord_bot - _process_queue:295 - Queue processor 37c33154 heartbeat - Active: True, Queue size: 0, Processing: 0, Total processed: 1859 +2025-02-11 19:48:53 - DEBUG - discord_bot - save_state:62 - Queue state saved - Pending messages: 0 +2025-02-11 19:49:53 - INFO - discord_bot - _process_queue:295 - Queue processor 37c33154 heartbeat - Active: True, Queue size: 0, Processing: 0, Total processed: 1859 +2025-02-11 19:49:53 - DEBUG - discord_bot - save_state:62 - Queue state saved - Pending messages: 0 +2025-02-11 19:50:53 - INFO - discord_bot - _process_queue:295 - Queue processor 37c33154 heartbeat - Active: True, Queue size: 0, Processing: 0, Total processed: 1859 +2025-02-11 19:50:53 - DEBUG - discord_bot - save_state:62 - Queue state saved - Pending messages: 0 +2025-02-11 19:51:53 - INFO - discord_bot - _process_queue:295 - Queue processor 37c33154 heartbeat - Active: True, Queue size: 0, Processing: 0, Total processed: 1859 +2025-02-11 19:51:53 - DEBUG - discord_bot - save_state:62 - Queue state saved - Pending messages: 0 +2025-02-11 19:52:53 - INFO - discord_bot - _process_queue:295 - Queue processor 37c33154 heartbeat - Active: True, Queue size: 0, Processing: 0, Total processed: 1859 +2025-02-11 19:52:53 - DEBUG - discord_bot - save_state:62 - Queue state saved - Pending messages: 0 +2025-02-11 19:53:53 - INFO - discord_bot - _process_queue:295 - Queue processor 37c33154 heartbeat - Active: True, Queue size: 0, Processing: 0, Total processed: 1859 +2025-02-11 19:53:53 - DEBUG - discord_bot - save_state:62 - Queue state saved - Pending messages: 0 +2025-02-11 19:54:53 - INFO - discord_bot - _process_queue:295 - Queue processor 37c33154 heartbeat - Active: True, Queue size: 0, Processing: 0, Total processed: 1859 +2025-02-11 19:54:53 - DEBUG - discord_bot - save_state:62 - Queue state saved - Pending messages: 0 +2025-02-11 19:55:53 - INFO - discord_bot - _process_queue:295 - Queue processor 37c33154 heartbeat - Active: True, Queue size: 0, Processing: 0, Total processed: 1859 +2025-02-11 19:55:53 - DEBUG - discord_bot - save_state:62 - Queue state saved - Pending messages: 0 +2025-02-11 19:56:53 - INFO - discord_bot - _process_queue:295 - Queue processor 37c33154 heartbeat - Active: True, Queue size: 0, Processing: 0, Total processed: 1859 +2025-02-11 19:56:53 - DEBUG - discord_bot - save_state:62 - Queue state saved - Pending messages: 0 +2025-02-11 19:57:32 - INFO - discord_bot - :211 - Using database path: conversation_history.db +2025-02-11 19:57:32 - INFO - discord_bot - load_responses:250 - Loaded responses from file +2025-02-11 19:57:53 - INFO - discord_bot - _process_queue:295 - Queue processor 37c33154 heartbeat - Active: True, Queue size: 0, Processing: 0, Total processed: 1859 +2025-02-11 19:57:53 - DEBUG - discord_bot - save_state:62 - Queue state saved - Pending messages: 0 +2025-02-11 19:58:53 - INFO - discord_bot - _process_queue:295 - Queue processor 37c33154 heartbeat - Active: True, Queue size: 0, Processing: 0, Total processed: 1859 +2025-02-11 19:58:53 - DEBUG - discord_bot - save_state:62 - Queue state saved - Pending messages: 0 +2025-02-11 19:59:31 - INFO - discord_bot - :211 - Using database path: conversation_history.db +2025-02-11 19:59:31 - INFO - discord_bot - load_responses:250 - Loaded responses from file +2025-02-11 19:59:53 - INFO - discord_bot - _process_queue:295 - Queue processor 37c33154 heartbeat - Active: True, Queue size: 0, Processing: 0, Total processed: 1859 +2025-02-11 19:59:53 - DEBUG - discord_bot - save_state:62 - Queue state saved - Pending messages: 0 +2025-02-11 20:00:53 - INFO - discord_bot - _process_queue:295 - Queue processor 37c33154 heartbeat - Active: True, Queue size: 0, Processing: 0, Total processed: 1859 +2025-02-11 20:00:53 - DEBUG - discord_bot - save_state:62 - Queue state saved - Pending messages: 0 +2025-02-11 20:00:59 - INFO - discord_bot - :211 - Using database path: conversation_history.db +2025-02-11 20:00:59 - INFO - discord_bot - load_responses:250 - Loaded responses from file +2025-02-11 20:00:59 - INFO - discord_bot - validate_config:290 - Vision API Configuration: +Model: meta-llama/llama-3.2-90b-vision-instruct:free +Base URL: https://openrouter.ai/api/v1/chat/completions +Timeout: 30.0 +Max Tokens: 1000 +2025-02-11 20:00:59 - WARNING - discord_bot - validate_config:326 - GLHF API is not fully configured. API features will be disabled. +2025-02-11 20:00:59 - INFO - discord_bot - validate_config:356 - Configuration validated successfully +2025-02-11 20:00:59 - INFO - discord_bot - load_state:40 - Queue state loaded from file - Pending messages: 0 +2025-02-11 20:00:59 - DEBUG - asyncio - __init__:64 - Using selector: KqueueSelector +2025-02-11 20:01:02 - INFO - discord_bot - on_ready:118 - CobraSilver#8886 has connected to Discord! +2025-02-11 20:01:02 - INFO - discord_bot - init_db:184 - Initializing database schema... +2025-02-11 20:01:02 - INFO - discord_bot - _init_connection:96 - Database connection initialized with optimized settings +2025-02-11 20:01:02 - INFO - discord_bot - init_db:201 - Users table created/verified +2025-02-11 20:01:02 - INFO - discord_bot - init_db:216 - Threads table created/verified +2025-02-11 20:01:02 - INFO - discord_bot - init_db:236 - Messages table created/verified +2025-02-11 20:01:02 - INFO - discord_bot - init_db:271 - All indices created/verified +2025-02-11 20:01:02 - INFO - discord_bot - init_db:274 - Database schema initialized successfully +2025-02-11 20:01:02 - INFO - discord_bot - start:38 - API manager started +2025-02-11 20:01:02 - INFO - discord_bot - on_ready:134 - Started API health check loop +2025-02-11 20:01:03 - DEBUG - discord_bot - save_state:62 - Queue state saved - Pending messages: 0 +2025-02-11 20:01:03 - INFO - discord_bot - _process_queue:207 - Queue processor 6e6e803c starting +2025-02-11 20:01:03 - DEBUG - discord_bot - save_state:62 - Queue state saved - Pending messages: 0 +2025-02-11 20:01:06 - INFO - discord_bot - shutdown:260 - Received SIGINT +2025-02-11 20:01:06 - DEBUG - discord_bot - save_state:62 - Queue state saved - Pending messages: 0 +2025-02-11 20:01:06 - WARNING - discord_bot - _process_queue:329 - Queue processor 6e6e803c exited - Processed: 1859, Failed: 46 +2025-02-11 20:01:06 - INFO - discord_bot - shutdown:260 - Received SIGTERM +2025-02-11 20:01:06 - INFO - discord_bot - stop:208 - Initiating shutdown... +2025-02-11 20:01:06 - INFO - discord_bot - shutdown:46 - API manager shutdown +2025-02-11 20:01:06 - INFO - discord_bot - stop:230 - Stopped API health check loop +2025-02-11 20:01:06 - INFO - discord_bot - stop:208 - Initiating shutdown... +2025-02-11 20:01:06 - DEBUG - discord_bot - _close_connection:107 - Database connection closed +2025-02-11 20:01:06 - INFO - discord_bot - stop:253 - Shutdown complete +2025-02-11 20:01:06 - INFO - discord_bot - stop:253 - Shutdown complete +2025-02-11 20:01:06 - INFO - discord_bot - run_bot:320 - Bot shutdown complete +2025-02-11 20:01:40 - INFO - discord_bot - shutdown:247 - Received SIGTERM +2025-02-11 20:01:40 - DEBUG - discord_bot - save_state:62 - Queue state saved - Pending messages: 0 +2025-02-11 20:01:40 - WARNING - discord_bot - _process_queue:329 - Queue processor 37c33154 exited - Processed: 1859, Failed: 46 +2025-02-11 20:01:40 - INFO - discord_bot - shutdown:247 - Received SIGTERM +2025-02-11 20:01:40 - INFO - discord_bot - stop:200 - Initiating shutdown... +2025-02-11 20:01:40 - INFO - discord_bot - shutdown:46 - API manager shutdown +2025-02-11 20:01:40 - INFO - discord_bot - stop:217 - Stopped API health check loop +2025-02-11 20:01:40 - INFO - discord_bot - stop:240 - Shutdown complete +2025-02-11 20:01:40 - INFO - discord_bot - stop:200 - Initiating shutdown... +2025-02-11 20:01:40 - INFO - discord_bot - stop:240 - Shutdown complete +2025-02-11 20:01:40 - INFO - discord_bot - run_bot:307 - Bot shutdown complete +2025-02-11 20:01:40 - INFO - discord_bot - :211 - Using database path: conversation_history.db +2025-02-11 20:01:40 - INFO - discord_bot - load_responses:250 - Loaded responses from file +2025-02-11 20:01:41 - INFO - discord_bot - validate_config:290 - Vision API Configuration: +Model: meta-llama/llama-3.2-90b-vision-instruct:free +Base URL: https://openrouter.ai/api/v1/chat/completions +Timeout: 30.0 +Max Tokens: 1000 +2025-02-11 20:01:41 - WARNING - discord_bot - validate_config:326 - GLHF API is not fully configured. API features will be disabled. +2025-02-11 20:01:41 - INFO - discord_bot - validate_config:356 - Configuration validated successfully +2025-02-11 20:01:41 - INFO - discord_bot - load_state:40 - Queue state loaded from file - Pending messages: 0 +2025-02-11 20:01:41 - DEBUG - asyncio - __init__:64 - Using selector: KqueueSelector +2025-02-11 20:01:43 - INFO - discord_bot - on_ready:118 - CobraSilver#8886 has connected to Discord! +2025-02-11 20:01:43 - INFO - discord_bot - init_db:184 - Initializing database schema... +2025-02-11 20:01:43 - INFO - discord_bot - _init_connection:96 - Database connection initialized with optimized settings +2025-02-11 20:01:43 - INFO - discord_bot - init_db:201 - Users table created/verified +2025-02-11 20:01:43 - INFO - discord_bot - init_db:216 - Threads table created/verified +2025-02-11 20:01:43 - INFO - discord_bot - init_db:236 - Messages table created/verified +2025-02-11 20:01:43 - INFO - discord_bot - init_db:271 - All indices created/verified +2025-02-11 20:01:43 - INFO - discord_bot - init_db:274 - Database schema initialized successfully +2025-02-11 20:01:43 - INFO - discord_bot - start:38 - API manager started +2025-02-11 20:01:43 - INFO - discord_bot - on_ready:134 - Started API health check loop +2025-02-11 20:01:44 - DEBUG - discord_bot - save_state:62 - Queue state saved - Pending messages: 0 +2025-02-11 20:01:44 - INFO - discord_bot - _process_queue:207 - Queue processor 2685dbfc starting +2025-02-11 20:01:44 - DEBUG - discord_bot - save_state:62 - Queue state saved - Pending messages: 0 +2025-02-11 20:01:46 - INFO - discord_bot - shutdown:260 - Received SIGINT +2025-02-11 20:01:46 - DEBUG - discord_bot - save_state:62 - Queue state saved - Pending messages: 0 +2025-02-11 20:01:46 - WARNING - discord_bot - _process_queue:329 - Queue processor 2685dbfc exited - Processed: 1859, Failed: 46 +2025-02-11 20:01:46 - INFO - discord_bot - shutdown:260 - Received SIGTERM +2025-02-11 20:01:46 - INFO - discord_bot - stop:208 - Initiating shutdown... +2025-02-11 20:01:46 - INFO - discord_bot - shutdown:46 - API manager shutdown +2025-02-11 20:01:46 - INFO - discord_bot - stop:230 - Stopped API health check loop +2025-02-11 20:01:46 - INFO - discord_bot - stop:208 - Initiating shutdown... +2025-02-11 20:01:46 - DEBUG - discord_bot - _close_connection:107 - Database connection closed +2025-02-11 20:01:46 - INFO - discord_bot - stop:253 - Shutdown complete +2025-02-11 20:01:46 - INFO - discord_bot - stop:253 - Shutdown complete +2025-02-11 20:01:46 - INFO - discord_bot - run_bot:320 - Bot shutdown complete +2025-02-11 20:02:30 - INFO - discord_bot - :211 - Using database path: conversation_history.db +2025-02-11 20:02:30 - INFO - discord_bot - load_responses:250 - Loaded responses from file +2025-02-11 20:02:30 - INFO - discord_bot - validate_config:290 - Vision API Configuration: +Model: meta-llama/llama-3.2-90b-vision-instruct:free +Base URL: https://openrouter.ai/api/v1/chat/completions +Timeout: 30.0 +Max Tokens: 1000 +2025-02-11 20:02:30 - WARNING - discord_bot - validate_config:326 - GLHF API is not fully configured. API features will be disabled. +2025-02-11 20:02:30 - INFO - discord_bot - validate_config:356 - Configuration validated successfully +2025-02-11 20:02:30 - INFO - discord_bot - load_state:40 - Queue state loaded from file - Pending messages: 0 +2025-02-11 20:02:30 - DEBUG - asyncio - __init__:64 - Using selector: KqueueSelector +2025-02-11 20:02:33 - INFO - discord_bot - on_ready:118 - CobraSilver#8886 has connected to Discord! +2025-02-11 20:02:33 - INFO - discord_bot - init_db:184 - Initializing database schema... +2025-02-11 20:02:33 - INFO - discord_bot - _init_connection:96 - Database connection initialized with optimized settings +2025-02-11 20:02:33 - INFO - discord_bot - init_db:201 - Users table created/verified +2025-02-11 20:02:33 - INFO - discord_bot - init_db:216 - Threads table created/verified +2025-02-11 20:02:33 - INFO - discord_bot - init_db:236 - Messages table created/verified +2025-02-11 20:02:33 - INFO - discord_bot - init_db:271 - All indices created/verified +2025-02-11 20:02:33 - INFO - discord_bot - init_db:274 - Database schema initialized successfully +2025-02-11 20:02:33 - INFO - discord_bot - start:38 - API manager started +2025-02-11 20:02:33 - INFO - discord_bot - on_ready:134 - Started API health check loop +2025-02-11 20:02:33 - INFO - discord_bot - shutdown:260 - Received SIGINT +2025-02-11 20:02:33 - INFO - discord_bot - stop:208 - Initiating shutdown... +2025-02-11 20:02:33 - INFO - discord_bot - stop:208 - Initiating shutdown... +2025-02-11 20:02:33 - INFO - discord_bot - shutdown:46 - API manager shutdown +2025-02-11 20:02:33 - INFO - discord_bot - stop:230 - Stopped API health check loop +2025-02-11 20:02:33 - INFO - discord_bot - shutdown:260 - Received SIGTERM +2025-02-11 20:02:33 - INFO - discord_bot - stop:253 - Shutdown complete +2025-02-11 20:02:33 - INFO - discord_bot - stop:253 - Shutdown complete +2025-02-11 20:02:33 - INFO - discord_bot - run_bot:320 - Bot shutdown complete +2025-02-11 20:02:33 - ERROR - asyncio - default_exception_handler:1864 - Task was destroyed but it is pending! +task: wait_for=<_GatheringFuture finished result=[CancelledError(''), CancelledError('')]>> +2025-02-11 20:03:46 - INFO - discord_bot - :211 - Using database path: conversation_history.db +2025-02-11 20:03:46 - INFO - discord_bot - load_responses:250 - Loaded responses from file +2025-02-11 20:03:47 - INFO - discord_bot - validate_config:290 - Vision API Configuration: +Model: meta-llama/llama-3.2-90b-vision-instruct:free +Base URL: https://openrouter.ai/api/v1/chat/completions +Timeout: 30.0 +Max Tokens: 1000 +2025-02-11 20:03:47 - WARNING - discord_bot - validate_config:326 - GLHF API is not fully configured. API features will be disabled. +2025-02-11 20:03:47 - INFO - discord_bot - validate_config:356 - Configuration validated successfully +2025-02-11 20:03:47 - INFO - discord_bot - load_state:40 - Queue state loaded from file - Pending messages: 0 +2025-02-11 20:03:47 - DEBUG - asyncio - __init__:64 - Using selector: KqueueSelector +2025-02-11 20:03:49 - INFO - discord_bot - on_ready:118 - CobraSilver#8886 has connected to Discord! +2025-02-11 20:03:49 - INFO - discord_bot - init_db:184 - Initializing database schema... +2025-02-11 20:03:49 - INFO - discord_bot - _init_connection:96 - Database connection initialized with optimized settings +2025-02-11 20:03:49 - INFO - discord_bot - init_db:201 - Users table created/verified +2025-02-11 20:03:49 - INFO - discord_bot - init_db:216 - Threads table created/verified +2025-02-11 20:03:49 - INFO - discord_bot - init_db:236 - Messages table created/verified +2025-02-11 20:03:49 - INFO - discord_bot - init_db:271 - All indices created/verified +2025-02-11 20:03:49 - INFO - discord_bot - init_db:274 - Database schema initialized successfully +2025-02-11 20:03:49 - INFO - discord_bot - start:38 - API manager started +2025-02-11 20:03:49 - INFO - discord_bot - on_ready:134 - Started API health check loop +2025-02-11 20:03:50 - DEBUG - discord_bot - save_state:62 - Queue state saved - Pending messages: 0 +2025-02-11 20:03:50 - INFO - discord_bot - _process_queue:207 - Queue processor b04dd0ef starting +2025-02-11 20:03:50 - DEBUG - discord_bot - save_state:62 - Queue state saved - Pending messages: 0 +2025-02-11 20:03:52 - INFO - discord_bot - shutdown:260 - Received SIGINT +2025-02-11 20:03:52 - DEBUG - discord_bot - save_state:62 - Queue state saved - Pending messages: 0 +2025-02-11 20:03:52 - WARNING - discord_bot - _process_queue:329 - Queue processor b04dd0ef exited - Processed: 1859, Failed: 46 +2025-02-11 20:03:52 - INFO - discord_bot - shutdown:260 - Received SIGTERM +2025-02-11 20:03:52 - INFO - discord_bot - stop:208 - Initiating shutdown... +2025-02-11 20:03:52 - INFO - discord_bot - shutdown:46 - API manager shutdown +2025-02-11 20:03:52 - INFO - discord_bot - stop:230 - Stopped API health check loop +2025-02-11 20:03:52 - INFO - discord_bot - stop:208 - Initiating shutdown... +2025-02-11 20:03:52 - DEBUG - discord_bot - _close_connection:107 - Database connection closed +2025-02-11 20:03:52 - INFO - discord_bot - stop:253 - Shutdown complete +2025-02-11 20:03:52 - INFO - discord_bot - stop:253 - Shutdown complete +2025-02-11 20:03:52 - INFO - discord_bot - run_bot:320 - Bot shutdown complete +2025-02-11 20:05:20 - INFO - discord_bot - :211 - Using database path: conversation_history.db +2025-02-11 20:05:20 - INFO - discord_bot - load_responses:250 - Loaded responses from file +2025-02-11 20:05:21 - INFO - discord_bot - validate_config:290 - Vision API Configuration: +Model: meta-llama/llama-3.2-90b-vision-instruct:free +Base URL: https://openrouter.ai/api/v1/chat/completions +Timeout: 30.0 +Max Tokens: 1000 +2025-02-11 20:05:21 - WARNING - discord_bot - validate_config:326 - GLHF API is not fully configured. API features will be disabled. +2025-02-11 20:05:21 - INFO - discord_bot - validate_config:356 - Configuration validated successfully +2025-02-11 20:05:21 - INFO - discord_bot - load_state:40 - Queue state loaded from file - Pending messages: 0 +2025-02-11 20:05:21 - DEBUG - asyncio - __init__:64 - Using selector: KqueueSelector +2025-02-11 20:05:23 - INFO - discord_bot - on_ready:118 - CobraSilver#8886 has connected to Discord! +2025-02-11 20:05:23 - INFO - discord_bot - init_db:184 - Initializing database schema... +2025-02-11 20:05:23 - INFO - discord_bot - _init_connection:96 - Database connection initialized with optimized settings +2025-02-11 20:05:23 - INFO - discord_bot - init_db:201 - Users table created/verified +2025-02-11 20:05:23 - INFO - discord_bot - init_db:216 - Threads table created/verified +2025-02-11 20:05:23 - INFO - discord_bot - init_db:236 - Messages table created/verified +2025-02-11 20:05:23 - INFO - discord_bot - init_db:271 - All indices created/verified +2025-02-11 20:05:23 - INFO - discord_bot - init_db:274 - Database schema initialized successfully +2025-02-11 20:05:23 - INFO - discord_bot - start:38 - API manager started +2025-02-11 20:05:23 - INFO - discord_bot - on_ready:134 - Started API health check loop +2025-02-11 20:05:24 - DEBUG - discord_bot - save_state:62 - Queue state saved - Pending messages: 0 +2025-02-11 20:05:24 - INFO - discord_bot - _process_queue:207 - Queue processor 9d6f2bbe starting +2025-02-11 20:05:24 - DEBUG - discord_bot - save_state:62 - Queue state saved - Pending messages: 0 +2025-02-11 20:05:51 - INFO - discord_bot - shutdown:260 - Received SIGINT +2025-02-11 20:05:51 - DEBUG - discord_bot - save_state:62 - Queue state saved - Pending messages: 0 +2025-02-11 20:05:51 - WARNING - discord_bot - _process_queue:329 - Queue processor 9d6f2bbe exited - Processed: 1859, Failed: 46 +2025-02-11 20:05:51 - INFO - discord_bot - shutdown:260 - Received SIGTERM +2025-02-11 20:05:51 - INFO - discord_bot - stop:208 - Initiating shutdown... +2025-02-11 20:05:51 - INFO - discord_bot - shutdown:46 - API manager shutdown +2025-02-11 20:05:51 - INFO - discord_bot - stop:230 - Stopped API health check loop +2025-02-11 20:05:51 - INFO - discord_bot - stop:208 - Initiating shutdown... +2025-02-11 20:05:51 - DEBUG - discord_bot - _close_connection:107 - Database connection closed +2025-02-11 20:05:51 - INFO - discord_bot - stop:253 - Shutdown complete +2025-02-11 20:05:51 - INFO - discord_bot - stop:253 - Shutdown complete +2025-02-11 20:05:51 - INFO - discord_bot - run_bot:320 - Bot shutdown complete +2025-02-11 20:06:02 - INFO - discord_bot - :211 - Using database path: conversation_history.db +2025-02-11 20:06:02 - INFO - discord_bot - load_responses:250 - Loaded responses from file +2025-02-11 20:06:02 - INFO - discord_bot - validate_config:290 - Vision API Configuration: +Model: meta-llama/llama-3.2-90b-vision-instruct:free +Base URL: https://openrouter.ai/api/v1/chat/completions +Timeout: 30.0 +Max Tokens: 1000 +2025-02-11 20:06:02 - WARNING - discord_bot - validate_config:326 - GLHF API is not fully configured. API features will be disabled. +2025-02-11 20:06:02 - INFO - discord_bot - validate_config:356 - Configuration validated successfully +2025-02-11 20:06:02 - INFO - discord_bot - load_state:40 - Queue state loaded from file - Pending messages: 0 +2025-02-11 20:06:02 - DEBUG - asyncio - __init__:64 - Using selector: KqueueSelector +2025-02-11 20:06:05 - INFO - discord_bot - on_ready:118 - CobraSilver#8886 has connected to Discord! +2025-02-11 20:06:05 - INFO - discord_bot - init_db:184 - Initializing database schema... +2025-02-11 20:06:05 - INFO - discord_bot - _init_connection:96 - Database connection initialized with optimized settings +2025-02-11 20:06:05 - INFO - discord_bot - init_db:201 - Users table created/verified +2025-02-11 20:06:05 - INFO - discord_bot - init_db:216 - Threads table created/verified +2025-02-11 20:06:05 - INFO - discord_bot - init_db:236 - Messages table created/verified +2025-02-11 20:06:05 - INFO - discord_bot - init_db:271 - All indices created/verified +2025-02-11 20:06:05 - INFO - discord_bot - init_db:274 - Database schema initialized successfully +2025-02-11 20:06:05 - INFO - discord_bot - start:38 - API manager started +2025-02-11 20:06:05 - INFO - discord_bot - on_ready:134 - Started API health check loop +2025-02-11 20:06:06 - DEBUG - discord_bot - save_state:62 - Queue state saved - Pending messages: 0 +2025-02-11 20:06:06 - INFO - discord_bot - _process_queue:207 - Queue processor 4d1c3e50 starting +2025-02-11 20:06:06 - DEBUG - discord_bot - save_state:62 - Queue state saved - Pending messages: 0 +2025-02-11 20:07:06 - INFO - discord_bot - _process_queue:295 - Queue processor 4d1c3e50 heartbeat - Active: True, Queue size: 0, Processing: 0, Total processed: 1859 +2025-02-11 20:07:06 - DEBUG - discord_bot - save_state:62 - Queue state saved - Pending messages: 0 +2025-02-11 20:07:08 - INFO - discord_bot - shutdown:260 - Received SIGINT +2025-02-11 20:07:08 - DEBUG - discord_bot - save_state:62 - Queue state saved - Pending messages: 0 +2025-02-11 20:07:08 - WARNING - discord_bot - _process_queue:329 - Queue processor 4d1c3e50 exited - Processed: 1859, Failed: 46 +2025-02-11 20:07:08 - INFO - discord_bot - stop:208 - Initiating shutdown... +2025-02-11 20:07:08 - INFO - discord_bot - stop:208 - Initiating shutdown... +2025-02-11 20:07:08 - INFO - discord_bot - shutdown:46 - API manager shutdown +2025-02-11 20:07:08 - INFO - discord_bot - stop:230 - Stopped API health check loop +2025-02-11 20:07:08 - INFO - discord_bot - shutdown:260 - Received SIGTERM +2025-02-11 20:07:08 - INFO - discord_bot - stop:253 - Shutdown complete +2025-02-11 20:07:08 - INFO - discord_bot - stop:253 - Shutdown complete +2025-02-11 20:07:08 - INFO - discord_bot - run_bot:320 - Bot shutdown complete +2025-02-11 20:07:08 - ERROR - asyncio - default_exception_handler:1864 - Task was destroyed but it is pending! +task: wait_for=<_GatheringFuture finished result=[CancelledError(''), CancelledError('')]>> diff --git a/discord_glhf/__main__.py b/discord_glhf/__main__.py new file mode 100644 index 0000000..1962bef --- /dev/null +++ b/discord_glhf/__main__.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python3 +"""Main entry point for the Discord bot.""" + +from .bot import run_bot + +if __name__ == '__main__': + run_bot() \ No newline at end of file diff --git a/discord_glhf/__pycache__/__main__.cpython-313.pyc b/discord_glhf/__pycache__/__main__.cpython-313.pyc new file mode 100644 index 0000000..35d9a53 Binary files /dev/null and b/discord_glhf/__pycache__/__main__.cpython-313.pyc differ diff --git a/discord_glhf/__pycache__/bot.cpython-313.pyc b/discord_glhf/__pycache__/bot.cpython-313.pyc index de02447..5466ff2 100644 Binary files a/discord_glhf/__pycache__/bot.cpython-313.pyc and b/discord_glhf/__pycache__/bot.cpython-313.pyc differ diff --git a/discord_glhf/__pycache__/http_server.cpython-313.pyc b/discord_glhf/__pycache__/http_server.cpython-313.pyc new file mode 100644 index 0000000..50158aa Binary files /dev/null and b/discord_glhf/__pycache__/http_server.cpython-313.pyc differ diff --git a/discord_glhf/bot.py b/discord_glhf/bot.py index 200ccaa..d8449f1 100644 --- a/discord_glhf/bot.py +++ b/discord_glhf/bot.py @@ -25,6 +25,8 @@ from .queue_manager import QueueManager from .api import APIManager from .handlers import MessageHandler, ImageHandler, ToolHandler, EventHandler from .training import TrainingManager +from .http_server import HTTPServer +from aiohttp import web class DiscordBot: @@ -46,6 +48,9 @@ class DiscordBot: self.tool_handler = None self.event_handler = None self.training_manager = TrainingManager() # Initialize training manager + self.http_server = None + self.internal_app = web.Application() + self.internal_runner = None async def _initialize_services(self) -> None: """Initialize API and queue services.""" @@ -144,6 +149,20 @@ class DiscordBot: await self.training_manager.start() logger.info("Training manager started") + # Set up internal API routes + self.internal_app.router.add_post('/api/prompt', self._handle_prompt) + self.internal_runner = web.AppRunner(self.internal_app) + await self.internal_runner.setup() + internal_site = web.TCPSite(self.internal_runner, 'localhost', int(os.getenv('HTTP_PORT', '8000'))) + await internal_site.start() + logger.info("Internal API server started") + + # Start HTTP server for backend prompts + http_port = int(os.getenv('WEB_PORT', '8080')) + self.http_server = HTTPServer(self.event_handler) + await self.http_server.start(port=http_port) + logger.info(f"Web server started on port {http_port}") + # Set bot status activity = Game(name="with roller coasters") await self.bot.change_presence(activity=activity) @@ -211,6 +230,11 @@ class DiscordBot: await self.training_manager.stop() logger.info("Training manager stopped") + # Stop HTTP server + if self.http_server: + await self.http_server.stop() + logger.info("HTTP server stopped") + # Stop API manager if self.api_manager and self.api_manager.is_running: await self.api_manager.shutdown() diff --git a/discord_glhf/handlers/__pycache__/event_handler.cpython-313.pyc b/discord_glhf/handlers/__pycache__/event_handler.cpython-313.pyc index fcb3770..288f2cc 100644 Binary files a/discord_glhf/handlers/__pycache__/event_handler.cpython-313.pyc and b/discord_glhf/handlers/__pycache__/event_handler.cpython-313.pyc differ diff --git a/discord_glhf/handlers/event_handler.py b/discord_glhf/handlers/event_handler.py index b9ef687..9dd54cd 100644 --- a/discord_glhf/handlers/event_handler.py +++ b/discord_glhf/handlers/event_handler.py @@ -532,6 +532,77 @@ class EventHandler: }, ) + async def send_prompt_to_channel(self, prompt: str, channel_id: int) -> None: + """Send a prompt to the LLM and post response in Discord channel.""" + try: + # Get the channel + channel = self.bot.get_channel(channel_id) + if not channel: + logger.error(f"Could not find channel {channel_id}") + return + + # Build messages array with system prompt + messages = [ + { + "role": "system", + "content": SYSTEM_PROMPT, + "metadata": { + "bot_owner_id": str(BOT_OWNER_ID), + "current_user": { + "user_id": "0" # System user + } + } + }, + { + "role": "user", + "content": prompt, + "context": { + "timeout_env": "GLHF_TIMEOUT" + } + } + ] + + # Get response from API + response = await self.api_manager.get_completion(messages) + if not response: + logger.error("No response received from API") + return + + # Parse tool calls and get processed response + tool_calls, final_response, mentioned_users = self.tool_handler.parse_tool_calls( + response, channel_id=channel.id + ) + + # Execute tool calls + for tool_name, args in tool_calls: + try: + if tool_name == "create_embed": + await self.tool_handler.create_embed( + channel=channel, content=args["content"] + ) + elif tool_name == "create_thread": + await self.tool_handler.create_thread( + channel.id, args["name"] + ) + except Exception as e: + logger.error(f"Error executing tool {tool_name}: {e}") + + # Send the response + if final_response: + logger.info(f"Bot response to backend prompt: {final_response}") + await self.message_handler.safe_send(channel, final_response) + + except Exception as e: + logger.error(f"Error processing backend prompt: {e}") + await self.report_error( + e, + { + "action": "send_prompt_to_channel", + "channel_id": channel_id, + "prompt": prompt, + }, + ) + async def store_message( self, user_id: int, diff --git a/discord_glhf/http_server.py b/discord_glhf/http_server.py new file mode 100644 index 0000000..acb72a1 --- /dev/null +++ b/discord_glhf/http_server.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python3 +"""HTTP server for backend prompt handling.""" + +from aiohttp import web +import os +import json +import logging +from typing import Optional + +from .config import logger, AUTO_RESPONSE_CHANNEL_ID + +class HTTPServer: + """HTTP server that accepts prompts from backend.""" + + def __init__(self, event_handler): + """Initialize with event handler reference.""" + self.event_handler = event_handler + self.app = web.Application() + self.app.router.add_post('/api/prompt', self.handle_prompt) + self.runner: Optional[web.AppRunner] = None + + async def handle_prompt(self, request: web.Request) -> web.Response: + """Handle incoming prompt requests.""" + try: + # Validate API key if provided in environment + expected_key = os.getenv('BACKEND_API_KEY') + if expected_key: + provided_key = request.headers.get('X-API-Key') + if not provided_key or provided_key != expected_key: + return web.Response( + status=401, + text=json.dumps({"error": "Invalid API key"}), + content_type='application/json' + ) + + # Parse request body + try: + body = await request.json() + except json.JSONDecodeError: + return web.Response( + status=400, + text=json.dumps({"error": "Invalid JSON"}), + content_type='application/json' + ) + + # Validate required fields + prompt = body.get('prompt') + if not prompt: + return web.Response( + status=400, + text=json.dumps({"error": "Missing required field: prompt"}), + content_type='application/json' + ) + + # Use provided channel_id or default + channel_id = body.get('channel_id', AUTO_RESPONSE_CHANNEL_ID) + + # Send prompt to channel + await self.event_handler.send_prompt_to_channel(prompt, channel_id) + + return web.Response( + text=json.dumps({"status": "processing"}), + content_type='application/json' + ) + + except Exception as e: + logger.error(f"Error handling prompt request: {e}") + return web.Response( + status=500, + text=json.dumps({"error": str(e)}), + content_type='application/json' + ) + + async def start(self, host: str = '127.0.0.1', port: int = 8000): + """Start the HTTP server.""" + self.runner = web.AppRunner(self.app) + await self.runner.setup() + site = web.TCPSite(self.runner, host, port) + await site.start() + logger.info(f"HTTP server started on http://{host}:{port}") + + async def stop(self): + """Stop the HTTP server.""" + if self.runner: + await self.runner.cleanup() + logger.info("HTTP server stopped") \ No newline at end of file diff --git a/discord_glhf/start.sh b/discord_glhf/start.sh new file mode 100755 index 0000000..a5bce32 --- /dev/null +++ b/discord_glhf/start.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# Start both the Discord bot and web interface + +# Function to stop background processes on exit +cleanup() { + echo "Stopping processes..." + kill $(jobs -p) 2>/dev/null + exit +} + +# Set up trap for cleanup +trap cleanup SIGINT SIGTERM + +# Export default ports if not set +export HTTP_PORT=${HTTP_PORT:-8000} +export WEB_PORT=${WEB_PORT:-8080} + +# Start the Discord bot in background +echo "Starting Discord bot..." +python3 -m discord_glhf & + +# Wait a moment for bot to initialize +sleep 2 + +# Start the web interface +echo "Starting web interface on port ${WEB_PORT}..." +cd $(dirname "$0") +PYTHONPATH=/Volumes/macminissd/Projects/discord_glhf /Users/talor/Projects/discord_glhf/.venv/bin/python3 web/app.py + +# This will be caught by the trap +wait \ No newline at end of file diff --git a/discord_glhf/web/__init__.py b/discord_glhf/web/__init__.py new file mode 100644 index 0000000..ce7afa7 --- /dev/null +++ b/discord_glhf/web/__init__.py @@ -0,0 +1,3 @@ +"""Web interface package for the Discord bot.""" + +from .app import run_webserver \ No newline at end of file diff --git a/discord_glhf/web/__main__.py b/discord_glhf/web/__main__.py new file mode 100644 index 0000000..332ce1d --- /dev/null +++ b/discord_glhf/web/__main__.py @@ -0,0 +1,6 @@ +"""Main entry point for the web interface.""" + +from .app import run_webserver + +if __name__ == '__main__': + run_webserver() \ No newline at end of file diff --git a/discord_glhf/web/__pycache__/__init__.cpython-313.pyc b/discord_glhf/web/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000..8d75ff5 Binary files /dev/null and b/discord_glhf/web/__pycache__/__init__.cpython-313.pyc differ diff --git a/discord_glhf/web/__pycache__/app.cpython-313.pyc b/discord_glhf/web/__pycache__/app.cpython-313.pyc new file mode 100644 index 0000000..12553b0 Binary files /dev/null and b/discord_glhf/web/__pycache__/app.cpython-313.pyc differ diff --git a/discord_glhf/web/app.py b/discord_glhf/web/app.py new file mode 100644 index 0000000..32ad231 --- /dev/null +++ b/discord_glhf/web/app.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 +"""Web interface for sending prompts to the Discord bot.""" + +from flask import Flask, render_template, request, jsonify +import requests +import os +from pathlib import Path + +app = Flask(__name__) +app.template_folder = str(Path(__file__).parent / 'templates') + +# Get configuration from environment variables +API_PORT = int(os.getenv('HTTP_PORT', '8000')) +BACKEND_API_KEY = os.getenv('BACKEND_API_KEY') + +@app.route('/') +def index(): + """Render the main interface.""" + return render_template('index.html') + +@app.route('/api/prompt', methods=['POST']) +def send_prompt(): + """Handle prompt submission.""" + try: + data = request.get_json() + if not data or 'prompt' not in data: + return jsonify({'error': 'Missing prompt'}), 400 + + # Forward the request to the bot's HTTP server + headers = {'Content-Type': 'application/json'} + if BACKEND_API_KEY: + headers['X-API-Key'] = BACKEND_API_KEY + + response = requests.post( + f'http://localhost:{API_PORT}/api/prompt', + json=data, + headers=headers + ) + + return response.json(), response.status_code + + except Exception as e: + return jsonify({'error': str(e)}), 500 + +def run_webserver(port=5000): + """Run the web server.""" + app.run(host='0.0.0.0', port=port, debug=True) + +def run(): + """Run the web server.""" + port = int(os.getenv('WEB_PORT', '5000')) + app.run(host='0.0.0.0', port=port) + +if __name__ == '__main__': + run() \ No newline at end of file diff --git a/discord_glhf/web/templates/index.html b/discord_glhf/web/templates/index.html new file mode 100644 index 0000000..d21537a --- /dev/null +++ b/discord_glhf/web/templates/index.html @@ -0,0 +1,100 @@ + + + + + + Discord Bot Prompt Interface + + + +
+
+

Discord Bot Prompt Interface

+ +
+
+
+ + +
+ +
+ + +
+ +
+ +
+
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 3deb3c6..26fadf4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,6 +12,7 @@ dependencies = [ "audioop-lts>=0.2.1", "discord>=2.3.2", "discord-py>=2.4.0", + "flask>=3.1.0", "ipdb>=0.13.13", "jishaku>=2.6.0", "litellm>=1.53.3", @@ -19,6 +20,7 @@ dependencies = [ "promptic>=2.3.1", "python-dotenv>=1.0.1", "pyyaml>=6.0.2", + "requests>=2.32.3", "tenacity>=9.0.0", "termcolor>=2.5.0", ] diff --git a/queue_state.json b/queue_state.json index bf8a21f..d74af84 100644 --- a/queue_state.json +++ b/queue_state.json @@ -1,11 +1,11 @@ { "total_processed": 1859, "failed_messages": 46, - "last_processed_time": 1739321243.26745, + "last_processed_time": 1739322428.929682, "user_queues": {}, - "last_save": 1739321243.267452, - "processor_id": "37c33154", - "active": true, + "last_save": 1739322428.929683, + "processor_id": null, + "active": false, "pending_messages": [], "last_channel_id": "743661026050048040" } \ No newline at end of file diff --git a/uv.lock b/uv.lock index d974788..75e6ede 100644 --- a/uv.lock +++ b/uv.lock @@ -186,6 +186,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5d/35/be73b6015511aa0173ec595fc579133b797ad532996f2998fd6b8d1bbe6b/audioop_lts-0.2.1-cp313-cp313t-win_arm64.whl", hash = "sha256:78bfb3703388c780edf900be66e07de5a3d4105ca8e8720c5c4d67927e0b15d0", size = 23918 }, ] +[[package]] +name = "blinker" +version = "1.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/21/28/9b3f50ce0e048515135495f198351908d99540d69bfdc8c1d15b73dc55ce/blinker-1.9.0.tar.gz", hash = "sha256:b4ce2265a7abece45e7cc896e98dbebe6cead56bcf805a3d23136d145f5445bf", size = 22460 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl", hash = "sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc", size = 8458 }, +] + [[package]] name = "braceexpand" version = "0.1.7" @@ -233,7 +242,7 @@ name = "click" version = "8.1.7" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "platform_system == 'Windows'" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/96/d3/f04c7bfcf5c1862a2a5b845c6b2b360488cf47af55dfa79c98f6a6bf98b5/click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de", size = 336121 } wheels = [ @@ -282,6 +291,7 @@ dependencies = [ { name = "audioop-lts" }, { name = "discord" }, { name = "discord-py" }, + { name = "flask" }, { name = "ipdb" }, { name = "jishaku" }, { name = "litellm" }, @@ -289,6 +299,7 @@ dependencies = [ { name = "promptic" }, { name = "python-dotenv" }, { name = "pyyaml" }, + { name = "requests" }, { name = "tenacity" }, { name = "termcolor" }, ] @@ -302,6 +313,7 @@ requires-dist = [ { name = "audioop-lts", specifier = ">=0.2.1" }, { name = "discord", specifier = ">=2.3.2" }, { name = "discord-py", specifier = ">=2.4.0" }, + { name = "flask", specifier = ">=3.1.0" }, { name = "ipdb", specifier = ">=0.13.13" }, { name = "jishaku", specifier = ">=2.6.0" }, { name = "litellm", specifier = ">=1.53.3" }, @@ -309,6 +321,7 @@ requires-dist = [ { name = "promptic", specifier = ">=2.3.1" }, { name = "python-dotenv", specifier = ">=1.0.1" }, { name = "pyyaml", specifier = ">=6.0.2" }, + { name = "requests", specifier = ">=2.32.3" }, { name = "tenacity", specifier = ">=9.0.0" }, { name = "termcolor", specifier = ">=2.5.0" }, ] @@ -352,6 +365,22 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b9/f8/feced7779d755758a52d1f6635d990b8d98dc0a29fa568bbe0625f18fdf3/filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0", size = 16163 }, ] +[[package]] +name = "flask" +version = "3.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "blinker" }, + { name = "click" }, + { name = "itsdangerous" }, + { name = "jinja2" }, + { name = "werkzeug" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/89/50/dff6380f1c7f84135484e176e0cac8690af72fa90e932ad2a0a60e28c69b/flask-3.1.0.tar.gz", hash = "sha256:5f873c5184c897c8d9d1b05df1e3d01b14910ce69607a117bd3277098a5836ac", size = 680824 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/af/47/93213ee66ef8fae3b93b3e29206f6b251e65c97bd91d8e1c5596ef15af0a/flask-3.1.0-py3-none-any.whl", hash = "sha256:d667207822eb83f1c4b50949b1623c8fc8d51f2341d65f72e1a1815397551136", size = 102979 }, +] + [[package]] name = "frozenlist" version = "1.5.0" @@ -503,6 +532,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/1d/f3/1332ba2f682b07b304ad34cad2f003adcfeb349486103f4b632335074a7c/ipython-8.30.0-py3-none-any.whl", hash = "sha256:85ec56a7e20f6c38fce7727dcca699ae4ffc85985aa7b23635a8008f918ae321", size = 820765 }, ] +[[package]] +name = "itsdangerous" +version = "2.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9c/cb/8ac0172223afbccb63986cc25049b154ecfb5e85932587206f42317be31d/itsdangerous-2.2.0.tar.gz", hash = "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173", size = 54410 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/96/92447566d16df59b2a776c0fb82dbc4d9e07cd95062562af01e408583fc4/itsdangerous-2.2.0-py3-none-any.whl", hash = "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef", size = 16234 }, +] + [[package]] name = "janus" version = "1.1.0" @@ -1082,7 +1120,7 @@ name = "tqdm" version = "4.67.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "platform_system == 'Windows'" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/a8/4b/29b4ef32e036bb34e4ab51796dd745cdba7ed47ad142a9f4a1eb8e0c744d/tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2", size = 169737 } wheels = [ @@ -1134,6 +1172,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fd/84/fd2ba7aafacbad3c4201d395674fc6348826569da3c0937e75505ead3528/wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859", size = 34166 }, ] +[[package]] +name = "werkzeug" +version = "3.1.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9f/69/83029f1f6300c5fb2471d621ab06f6ec6b3324685a2ce0f9777fd4a8b71e/werkzeug-3.1.3.tar.gz", hash = "sha256:60723ce945c19328679790e3282cc758aa4a6040e4bb330f53d30fa546d44746", size = 806925 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/52/24/ab44c871b0f07f491e5d2ad12c9bd7358e527510618cb1b803a88e986db1/werkzeug-3.1.3-py3-none-any.whl", hash = "sha256:54b78bf3716d19a65be4fceccc0d1d7b89e608834989dfae50ea87564639213e", size = 224498 }, +] + [[package]] name = "yarl" version = "1.18.3"