Merge pull request #53 from bucolucas/add-always-on-keyboard

Add always-on keyboard for common commands
This commit is contained in:
2024-08-18 17:28:04 -05:00
committed by GitHub
+24 -11
View File
@@ -6,7 +6,7 @@ import logging
import sys import sys
import subprocess import subprocess
import requests import requests
from telegram import Update, __version__ as telegram_version, InlineKeyboardButton, InlineKeyboardMarkup from telegram import Update, __version__ as telegram_version, InlineKeyboardButton, InlineKeyboardMarkup, ReplyKeyboardMarkup
from telegram.ext import Application, CommandHandler, MessageHandler, filters, ContextTypes, CallbackQueryHandler from telegram.ext import Application, CommandHandler, MessageHandler, filters, ContextTypes, CallbackQueryHandler
from dotenv import load_dotenv from dotenv import load_dotenv
from tools.base_tool import BaseTool from tools.base_tool import BaseTool
@@ -59,9 +59,19 @@ functions = []
for tool in tools: for tool in tools:
functions.extend(tool.get_functions()) functions.extend(tool.get_functions())
def get_keyboard():
keyboard = [
['/switch', '/toggle'],
['/status', '/reset']
]
return ReplyKeyboardMarkup(keyboard, resize_keyboard=True)
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
logging.info("Bot started") logging.info("Bot started")
await update.message.reply_text("Hello! I'm your AI assistant. How can I help you today? You can send me images and then ask questions about them.") await update.message.reply_text(
"Hello! I'm your AI assistant. How can I help you today? You can send me images and then ask questions about them.",
reply_markup=get_keyboard()
)
async def clear(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: async def clear(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
user_id = update.effective_user.id user_id = update.effective_user.id
@@ -71,7 +81,7 @@ async def clear(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
tool.clear() tool.clear()
logging.info(f"Cleared conversation history and image for user {user_id}") logging.info(f"Cleared conversation history and image for user {user_id}")
await update.message.reply_text("Conversation history and image cleared. Let's start fresh!") await update.message.reply_text("Conversation history and image cleared. Let's start fresh!", reply_markup=get_keyboard())
async def update_status_message(context: ContextTypes.DEFAULT_TYPE, chat_id: int, message_id: int, status: str): async def update_status_message(context: ContextTypes.DEFAULT_TYPE, chat_id: int, message_id: int, status: str):
keyboard = [ keyboard = [
@@ -151,11 +161,11 @@ async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE) ->
await context.bot.delete_message(chat_id=update.effective_chat.id, message_id=status_message.message_id) await context.bot.delete_message(chat_id=update.effective_chat.id, message_id=status_message.message_id)
del processing_status[user_id] del processing_status[user_id]
await update.message.reply_text(messages[-1]["content"][0].text) await update.message.reply_text(messages[-1]["content"][0].text, reply_markup=get_keyboard())
except Exception as e: except Exception as e:
logging.error(f"An error occurred: {str(e)}") logging.error(f"An error occurred: {str(e)}")
await update.message.reply_text("Sorry, an error occurred while processing your request.") await update.message.reply_text("Sorry, an error occurred while processing your request.", reply_markup=get_keyboard())
def call_tool(function_call): def call_tool(function_call):
function_name = function_call.name function_name = function_call.name
@@ -191,7 +201,7 @@ def get_claude_response(messages):
return response return response
async def status(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: async def status(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
await update.message.reply_text("Currently using claude-3-5-sonnet-20240620") await update.message.reply_text("Currently using claude-3-5-sonnet-20240620", reply_markup=get_keyboard())
async def abort_processing(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: async def abort_processing(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
query = update.callback_query query = update.callback_query
@@ -214,9 +224,9 @@ async def handover(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
# Daemon bot initiating handover # Daemon bot initiating handover
apprentice_chat_id = os.getenv('APPRENTICE_CHAT_ID') apprentice_chat_id = os.getenv('APPRENTICE_CHAT_ID')
await context.bot.send_message(chat_id=apprentice_chat_id, text="Handover initiated. Taking control.") await context.bot.send_message(chat_id=apprentice_chat_id, text="Handover initiated. Taking control.")
await update.message.reply_text("Handover initiated. Apprentice bot is now in control.") await update.message.reply_text("Handover initiated. Apprentice bot is now in control.", reply_markup=get_keyboard())
else: else:
await update.message.reply_text("Handover can only be initiated by the daemon bot.") await update.message.reply_text("Handover can only be initiated by the daemon bot.", reply_markup=get_keyboard())
async def update_apprentice(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: async def update_apprentice(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
if context.bot.token == APPRENTICE_BOT_TOKEN: if context.bot.token == APPRENTICE_BOT_TOKEN:
@@ -228,12 +238,12 @@ async def update_apprentice(update: Update, context: ContextTypes.DEFAULT_TYPE)
os.execv(sys.executable, ['python'] + sys.argv) os.execv(sys.executable, ['python'] + sys.argv)
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
logging.error(f"Failed to pull latest changes: {e}") logging.error(f"Failed to pull latest changes: {e}")
await update.message.reply_text("Failed to update. Please check the logs.") await update.message.reply_text("Failed to update. Please check the logs.", reply_markup=get_keyboard())
except Exception as e: except Exception as e:
logging.error(f"Failed to restart the bot: {e}") logging.error(f"Failed to restart the bot: {e}")
await update.message.reply_text("Failed to restart. Please check the logs.") await update.message.reply_text("Failed to restart. Please check the logs.", reply_markup=get_keyboard())
else: else:
await update.message.reply_text("Update can only be performed by the apprentice bot.") await update.message.reply_text("Update can only be performed by the apprentice bot.", reply_markup=get_keyboard())
async def check_for_updates(context: ContextTypes.DEFAULT_TYPE) -> None: async def check_for_updates(context: ContextTypes.DEFAULT_TYPE) -> None:
url = f"https://api.github.com/repos/{GITHUB_REPO_OWNER}/{GITHUB_REPO_NAME}/pulls" url = f"https://api.github.com/repos/{GITHUB_REPO_OWNER}/{GITHUB_REPO_NAME}/pulls"
@@ -259,6 +269,9 @@ def main() -> None:
app.add_handler(CommandHandler("start", start)) app.add_handler(CommandHandler("start", start))
app.add_handler(CommandHandler("clear", clear)) app.add_handler(CommandHandler("clear", clear))
app.add_handler(CommandHandler("status", status)) app.add_handler(CommandHandler("status", status))
app.add_handler(CommandHandler("switch", start)) # Placeholder for /switch command
app.add_handler(CommandHandler("toggle", start)) # Placeholder for /toggle command
app.add_handler(CommandHandler("reset", clear)) # Use clear function for /reset command
app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_message)) app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_message))
app.add_handler(CallbackQueryHandler(abort_processing, pattern='^abort$')) app.add_handler(CallbackQueryHandler(abort_processing, pattern='^abort$'))