Update telegram interface #44

Merged
Berack96 merged 6 commits from update-telegram-interaction into main 2025-10-27 12:42:14 +01:00
2 changed files with 56 additions and 20 deletions
Showing only changes of commit 49a3c84350 - Show all commits

View File

@@ -133,3 +133,41 @@ class PipelineInputs:
social_tool = SocialAPIsTool()
copilot-pull-request-reviewer[bot] commented 2025-10-23 15:07:19 +02:00 (Migrated from github.com)
Review

Potential IndexError if self.current >= len(steps) after all steps complete. The update() method increments self.current beyond the list bounds when the last step finishes. Add bounds checking: if extra and self.current < len(steps):

        if extra and self.current < len(steps):
Potential IndexError if `self.current >= len(steps)` after all steps complete. The `update()` method increments `self.current` beyond the list bounds when the last step finishes. Add bounds checking: `if extra and self.current < len(steps):` ```suggestion if extra and self.current < len(steps): ```
social_tool.handler.set_retries(api.retry_attempts, api.retry_delay_seconds)
return market_tool, news_tool, social_tool
def __str__(self) -> str:
return "\n".join([
f"Query Check: {self.query_analyzer_model.label}",
f"Team Leader: {self.team_leader_model.label}",
f"Team: {self.team_model.label}",
f"Report: {self.report_generation_model.label}",
f"Strategy: {self.strategy.label}",
f"User Query: \"{self.user_query}\"",
])
class RunMessage:
def __init__(self, inputs: PipelineInputs, prefix: str = "", suffix: str = ""):
self.base_message = f"Running configurations: \n{prefix}{inputs}{suffix}\n\n"
self.emojis = ['🔳', '➡️', '']
self.placeholder = '<<<>>>'
self.current = 0
self.steps_total = [
(f"{self.placeholder} Query Check", 1),
(f"{self.placeholder} Info Recovery", 0),
(f"{self.placeholder} Report Generation", 0),
]
def update(self) -> 'RunMessage':
text_curr, state_curr = self.steps_total[self.current]
self.steps_total[self.current] = (text_curr, state_curr + 1)
self.current += 1
if self.current < len(self.steps_total):
text_curr, state_curr = self.steps_total[self.current]
self.steps_total[self.current] = (text_curr, state_curr + 1)
return self
def get_latest(self, extra: str = "") -> str:
steps = [msg.replace(self.placeholder, self.emojis[state]) for msg, state in self.steps_total]
if extra:
steps[self.current] = f"{steps[self.current]}: {extra}"
return self.base_message + "\n".join(steps)

View File

@@ -1,3 +1,4 @@
import asyncio
import io
import os
import json
@@ -10,7 +11,7 @@ from markdown_pdf import MarkdownPdf, Section
from telegram import CallbackQuery, InlineKeyboardButton, InlineKeyboardMarkup, Message, Update, User
from telegram.constants import ChatAction
from telegram.ext import Application, CallbackQueryHandler, CommandHandler, ContextTypes, ConversationHandler, MessageHandler, filters
from app.agents.pipeline import Pipeline, PipelineInputs
from app.agents.pipeline import Pipeline, PipelineEvent, PipelineInputs, RunMessage
# per per_message di ConversationHandler che rompe sempre qualunque input tu metta
warnings.filterwarnings("ignore")
@@ -233,7 +234,7 @@ class TelegramApp:
async def __select_config(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
query, user = await self.handle_callbackquery(update)
logging.info(f"@{user.username} --> {query.data}")
logging.debug(f"@{user.username} --> {query.data}")
copilot-pull-request-reviewer[bot] commented 2025-10-23 15:07:19 +02:00 (Migrated from github.com)
Review

Creating async tasks with asyncio.create_task without awaiting or tracking them can lead to unhandled exceptions and race conditions. The task may fail silently if msg.edit_text raises an exception. Consider using await directly or implementing proper task tracking and error handling.

Creating async tasks with `asyncio.create_task` without awaiting or tracking them can lead to unhandled exceptions and race conditions. The task may fail silently if `msg.edit_text` raises an exception. Consider using `await` directly or implementing proper task tracking and error handling.
copilot-pull-request-reviewer[bot] commented 2025-10-23 15:07:19 +02:00 (Migrated from github.com)
Review

The f-string uses backticks for markdown code formatting, but wraps the entire expression. If e.agent_name or e.tool.tool_name contain special MarkdownV2 characters, they should be escaped. Consider adding proper markdown escaping for user-facing content.

The f-string uses backticks for markdown code formatting, but wraps the entire expression. If `e.agent_name` or `e.tool.tool_name` contain special MarkdownV2 characters, they should be escaped. Consider adding proper markdown escaping for user-facing content.
req = self.user_requests[user]
_, state, index = str(query.data).split(QUERY_SEP)
@@ -264,36 +265,33 @@ class TelegramApp:
msg_id = update.message.message_id - 1
chat_id = update.message.chat_id
configs_str = [
'Running with configurations: ',
f'Check: {inputs.query_analyzer_model.label}',
f'Leader: {inputs.team_leader_model.label}',
f'Team: {inputs.team_model.label}',
f'Report: {inputs.report_generation_model.label}',
f'Strategy: {inputs.strategy.label}',
f'Query: "{inputs.user_query}"'
]
full_message = f"""```\n{'\n'.join(configs_str)}\n```\n\n"""
first_message = full_message + "Generating report, please wait"
msg = await bot.edit_message_text(chat_id=chat_id, message_id=msg_id, text=first_message, parse_mode='MarkdownV2')
run_message = RunMessage(inputs, prefix="```\n", suffix="\n```")
msg = await bot.edit_message_text(chat_id=chat_id, message_id=msg_id, text=run_message.get_latest(), parse_mode='MarkdownV2')
if isinstance(msg, bool): return
# Remove user query and bot message
await bot.delete_message(chat_id=chat_id, message_id=update.message.id)
# TODO migliorare messaggi di attesa
def update_user(update: bool = True, extra: str = "") -> None:
if update: run_message.update()
message = run_message.get_latest(extra)
if msg.text != message:
asyncio.create_task(msg.edit_text(message, parse_mode='MarkdownV2'))
await bot.send_chat_action(chat_id=chat_id, action=ChatAction.TYPING)
pipeline = Pipeline(inputs)
report_content = await pipeline.interact_async()
await msg.delete()
report_content = await pipeline.interact_async(listeners=[
(PipelineEvent.QUERY_CHECK, lambda _: update_user()),
(PipelineEvent.TOOL_USED, lambda e: update_user(False, f"`{e.agent_name} {e.tool.tool_name}`")),
(PipelineEvent.INFO_RECOVERY, lambda _: update_user()),
(PipelineEvent.REPORT_GENERATION, lambda _: update_user()),
])
# attach report file to the message
pdf = MarkdownPdf(toc_level=2, optimize=True)
pdf.add_section(Section(report_content, toc=False))
# TODO vedere se ha senso dare il pdf o solo il messaggio
document = io.BytesIO()
pdf.save_bytes(document)
document.seek(0)
await bot.send_document(chat_id=chat_id, document=document, filename="report.pdf", parse_mode='MarkdownV2', caption=full_message)
await msg.reply_document(document=document, filename="report.pdf")