Add Quart web interface and prompt handling; update queue state and logging
This commit is contained in:
@@ -192,11 +192,10 @@ class DiscordBot:
|
||||
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}")
|
||||
# Initialize and start web interface
|
||||
from discord_glhf.web.app import init_app
|
||||
self.web_app = init_app(self.event_handler)
|
||||
logger.info("Web interface initialized with event handler")
|
||||
|
||||
# Set bot status
|
||||
activity = Game(name="with roller coasters")
|
||||
|
||||
4
discord_glhf/discord_bot.log
Normal file
4
discord_glhf/discord_bot.log
Normal file
@@ -0,0 +1,4 @@
|
||||
2025-02-11 20:23:21 - INFO - discord_bot - <module>:211 - Using database path: conversation_history.db
|
||||
2025-02-11 20:23:21 - INFO - discord_bot - load_responses:250 - Loaded responses from file
|
||||
2025-02-11 20:23:21 - DEBUG - asyncio - __init__:64 - Using selector: KqueueSelector
|
||||
2025-02-11 20:23:21 - INFO - hypercorn.error - info:106 - Running on http://0.0.0.0:8080 (CTRL + C to quit)
|
||||
Binary file not shown.
@@ -44,6 +44,69 @@ class EventHandler:
|
||||
# Replace all mention formats with the proper mention
|
||||
return re.sub(pattern, mention, response)
|
||||
|
||||
async def send_prompt_to_channel(self, prompt: str, channel_id: int) -> None:
|
||||
"""Send a prompt to the specified channel."""
|
||||
try:
|
||||
channel = self.bot.get_channel(channel_id)
|
||||
if not channel:
|
||||
logger.error(f"Could not find channel {channel_id}")
|
||||
return
|
||||
|
||||
# Build context for the API call
|
||||
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 prompt: {final_response}")
|
||||
await self.message_handler.safe_send(channel, final_response)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error processing prompt: {e}")
|
||||
raise
|
||||
|
||||
async def handle_reaction(self, payload: RawReactionActionEvent) -> None:
|
||||
"""Handle reaction events on bot messages."""
|
||||
# Ignore our own reactions
|
||||
|
||||
@@ -4,7 +4,11 @@
|
||||
# Function to stop background processes on exit
|
||||
cleanup() {
|
||||
echo "Stopping processes..."
|
||||
if [ ! -z "$WEB_PID" ]; then
|
||||
kill $WEB_PID 2>/dev/null
|
||||
fi
|
||||
kill $(jobs -p) 2>/dev/null
|
||||
wait
|
||||
exit
|
||||
}
|
||||
|
||||
@@ -25,7 +29,11 @@ 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
|
||||
# Run web interface with proper Python path and virtualenv
|
||||
PYTHONPATH=/Volumes/macminissd/Projects/discord_glhf /Users/talor/Projects/discord_glhf/.venv/bin/python3 web/app.py &
|
||||
WEB_PID=$!
|
||||
# Wait a moment for web interface to start
|
||||
sleep 2
|
||||
|
||||
# This will be caught by the trap
|
||||
wait
|
||||
@@ -1,55 +1,71 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Web interface for sending prompts to the Discord bot."""
|
||||
|
||||
from flask import Flask, render_template, request, jsonify
|
||||
import requests
|
||||
from quart import Quart, render_template, request, jsonify
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
app = Flask(__name__)
|
||||
app.template_folder = str(Path(__file__).parent / 'templates')
|
||||
def async_route(f):
|
||||
@wraps(f)
|
||||
def wrapped(*args, **kwargs):
|
||||
return asyncio.run(f(*args, **kwargs))
|
||||
return wrapped
|
||||
|
||||
# Get configuration from environment variables
|
||||
API_PORT = int(os.getenv('HTTP_PORT', '8000'))
|
||||
BACKEND_API_KEY = os.getenv('BACKEND_API_KEY')
|
||||
from discord_glhf.config import AUTO_RESPONSE_CHANNEL_ID
|
||||
|
||||
app = Quart(__name__)
|
||||
app.template_folder = str(Path(__file__).parent / 'templates')
|
||||
event_handler = None
|
||||
|
||||
def init_app(bot_event_handler):
|
||||
"""Initialize the app with the bot's event handler."""
|
||||
global event_handler
|
||||
event_handler = bot_event_handler
|
||||
return app
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
async def index():
|
||||
"""Render the main interface."""
|
||||
return render_template('index.html')
|
||||
return await render_template('index.html')
|
||||
|
||||
@app.route('/api/prompt', methods=['POST'])
|
||||
def send_prompt():
|
||||
async def send_prompt():
|
||||
"""Handle prompt submission."""
|
||||
try:
|
||||
if not event_handler:
|
||||
return jsonify({'error': 'Bot not initialized'}), 503
|
||||
|
||||
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(
|
||||
'http://127.0.0.1:8000/api/prompt', # Use fixed internal API port
|
||||
json=data,
|
||||
headers=headers
|
||||
)
|
||||
|
||||
return response.json(), response.status_code
|
||||
channel_id = data.get('channel_id', AUTO_RESPONSE_CHANNEL_ID)
|
||||
await event_handler.send_prompt_to_channel(data['prompt'], channel_id)
|
||||
return jsonify({'status': 'processing'}), 200
|
||||
|
||||
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)
|
||||
import hypercorn.asyncio
|
||||
from hypercorn.config import Config
|
||||
|
||||
def run():
|
||||
"""Run the web server."""
|
||||
port = int(os.getenv('WEB_PORT', '5000'))
|
||||
app.run(host='0.0.0.0', port=port)
|
||||
config = Config()
|
||||
config.bind = [f"0.0.0.0:{port}"]
|
||||
config.use_reloader = True
|
||||
|
||||
if __name__ == '__main__':
|
||||
run()
|
||||
import asyncio
|
||||
loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(loop)
|
||||
try:
|
||||
loop.run_until_complete(hypercorn.asyncio.serve(app, config))
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
finally:
|
||||
loop.close()
|
||||
|
||||
if __name__ == "__main__":
|
||||
from discord_glhf.config import AUTO_RESPONSE_CHANNEL_ID
|
||||
port = int(os.getenv('WEB_PORT', '8080'))
|
||||
run_webserver(port)
|
||||
Reference in New Issue
Block a user