ux: show Thinking placeholder immediately, edit with status and final reply
This commit is contained in:
parent
3c6cafd62d
commit
9316a38699
1 changed files with 28 additions and 10 deletions
38
main.py
38
main.py
|
|
@ -10,6 +10,7 @@ import pathlib
|
|||
import subprocess
|
||||
|
||||
from openai import OpenAI
|
||||
import telegram
|
||||
from telegram import BotCommand, Update
|
||||
from telegram.error import BadRequest, TimedOut
|
||||
from telegram.ext import (
|
||||
|
|
@ -331,8 +332,8 @@ async def handle_message(update: Update, ctx: ContextTypes.DEFAULT_TYPE) -> None
|
|||
messages = get_messages(chat_id)
|
||||
messages.append({"role": "user", "content": user_text})
|
||||
|
||||
# Send "typing" indicator
|
||||
await update.message.chat.send_action("typing")
|
||||
# Send immediate "Thinking ..." placeholder so user knows the bot read their message
|
||||
thinking = await _safe_reply(update, "Thinking ...")
|
||||
|
||||
# Run the LLM loop (with tool calls)
|
||||
max_rounds = 10
|
||||
|
|
@ -346,7 +347,7 @@ async def handle_message(update: Update, ctx: ContextTypes.DEFAULT_TYPE) -> None
|
|||
)
|
||||
except Exception as e:
|
||||
log.error("OpenAI API error: %s", e)
|
||||
await _safe_reply(update, f"Sorry, I hit an error: {e}")
|
||||
await _safe_edit(thinking, update, f"Sorry, I hit an error: {e}")
|
||||
return
|
||||
|
||||
choice = response.choices[0]
|
||||
|
|
@ -361,6 +362,9 @@ async def handle_message(update: Update, ctx: ContextTypes.DEFAULT_TYPE) -> None
|
|||
json.loads(tc.function.arguments) if tc.function.arguments else {}
|
||||
)
|
||||
log.info("Tool call: %s(%s)", tc.function.name, list(args.keys()))
|
||||
# Update placeholder with current tool status
|
||||
status = f"Working ... ({tc.function.name})"
|
||||
await _safe_edit(thinking, update, status)
|
||||
try:
|
||||
result = handle_tool_call(tc.function.name, args)
|
||||
except Exception as e:
|
||||
|
|
@ -373,7 +377,6 @@ async def handle_message(update: Update, ctx: ContextTypes.DEFAULT_TYPE) -> None
|
|||
}
|
||||
)
|
||||
# Continue the loop for the LLM to process tool results
|
||||
await update.message.chat.send_action("typing")
|
||||
continue
|
||||
|
||||
# No tool calls — we have a final text reply
|
||||
|
|
@ -382,21 +385,36 @@ async def handle_message(update: Update, ctx: ContextTypes.DEFAULT_TYPE) -> None
|
|||
if len(messages) > 60:
|
||||
messages[:] = messages[:1] + messages[-40:]
|
||||
|
||||
await _safe_reply(update, msg.content)
|
||||
await _safe_edit(thinking, update, msg.content)
|
||||
return
|
||||
|
||||
await _safe_reply(
|
||||
update, "I ran out of steps — please try again with a simpler request."
|
||||
await _safe_edit(
|
||||
thinking, update, "I ran out of steps — please try again with a simpler request."
|
||||
)
|
||||
|
||||
|
||||
async def _safe_reply(update: Update, text: str, **kwargs) -> None:
|
||||
async def _safe_reply(update: Update, text: str, **kwargs) -> "telegram.Message | None":
|
||||
"""Reply to a message, falling back to send_message if the original is gone."""
|
||||
try:
|
||||
await update.message.reply_text(text, **kwargs)
|
||||
return await update.message.reply_text(text, **kwargs)
|
||||
except BadRequest:
|
||||
log.warning("Could not reply to message, sending without reply")
|
||||
await update.effective_chat.send_message(text, **kwargs)
|
||||
return await update.effective_chat.send_message(text, **kwargs)
|
||||
|
||||
|
||||
async def _safe_edit(
|
||||
thinking: "telegram.Message | None",
|
||||
update: Update,
|
||||
text: str,
|
||||
) -> None:
|
||||
"""Edit the placeholder message, falling back to a new message if it fails."""
|
||||
if thinking:
|
||||
try:
|
||||
await thinking.edit_text(text)
|
||||
return
|
||||
except BadRequest:
|
||||
log.warning("Could not edit placeholder, sending new message")
|
||||
await update.effective_chat.send_message(text)
|
||||
|
||||
|
||||
async def _error_handler(update: object, context: ContextTypes.DEFAULT_TYPE) -> None:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue