From ad7fc241f1b84fb92d5078f574d8b9f12a861594 Mon Sep 17 00:00:00 2001 From: William Valentin Date: Thu, 5 Feb 2026 17:53:54 -0800 Subject: [PATCH] feat(telegram): display tool execution status messages Telegram bot now shows tool status during execution: - Sends status message when tool starts (tool name + args snippet) - Edits status message with result on completion - Keeps typing indicator active during tool execution - Adds setOnToolUse() to NativeAgent for per-message callback control --- src/backends/native/agent.ts | 4 ++++ src/frontends/telegram/bot.ts | 36 +++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/backends/native/agent.ts b/src/backends/native/agent.ts index c65e065..b5d6708 100644 --- a/src/backends/native/agent.ts +++ b/src/backends/native/agent.ts @@ -190,4 +190,8 @@ export class NativeAgent { getModelTier(): ModelTier { return this.currentTier; } + + setOnToolUse(callback: ((event: ToolUseEvent) => void) | undefined): void { + this.onToolUse = callback; + } } diff --git a/src/frontends/telegram/bot.ts b/src/frontends/telegram/bot.ts index 9ee83f9..fd16431 100644 --- a/src/frontends/telegram/bot.ts +++ b/src/frontends/telegram/bot.ts @@ -97,9 +97,44 @@ export function createTelegramBot(config: TelegramBotConfig): Bot { // Show typing indicator await ctx.replyWithChatAction('typing'); + // Set up tool status display for this message + let statusMsgId: number | undefined; + config.agent.setOnToolUse(async (event) => { + try { + if (event.type === 'start') { + const argsSnippet = event.args ? ` ${JSON.stringify(event.args).slice(0, 100)}` : ''; + const statusText = `⚡ ${event.tool}${argsSnippet}`; + const msg = await ctx.reply(statusText); + statusMsgId = msg.message_id; + // Keep typing indicator active + await ctx.replyWithChatAction('typing'); + } else if (event.type === 'end' && event.result && statusMsgId) { + const icon = event.result.success ? '✓' : '✗'; + const detail = event.result.success + ? `${event.result.output.split('\n').length} lines` + : (event.result.error ?? 'error'); + try { + await ctx.api.editMessageText( + ctx.chat.id, + statusMsgId, + `${icon} ${event.tool}: ${detail}`, + ); + } catch { + // Edit may fail if message was deleted; ignore + } + statusMsgId = undefined; + } + } catch { + // Don't let status display errors break the tool loop + } + }); + try { const response = await handleMessage(text); + // Clear tool use callback + config.agent.setOnToolUse(undefined); + // Telegram has a 4096 character limit per message if (response.length <= 4096) { await ctx.reply(response, { parse_mode: 'Markdown' }); @@ -111,6 +146,7 @@ export function createTelegramBot(config: TelegramBotConfig): Bot { } } } catch (error) { + config.agent.setOnToolUse(undefined); console.error('Error processing message:', error); await ctx.reply('Sorry, an error occurred while processing your message.'); }