feat(telegram): show tool progress on placeholder during agent loop

Edit the Telegram placeholder message with tool names and iteration
count (e.g. "🔧 web_search (2/20)") so users see live progress instead
of a static "Thinking... 💭". Non-supporting channels silently skip.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
dj-oyu 2026-02-20 15:33:06 +09:00
parent f83bcb881f
commit d614e1f887
4 changed files with 45 additions and 3 deletions

View file

@ -654,6 +654,16 @@ func (al *AgentLoop) runLLMIteration(ctx context.Context, agent *AgentInstance,
"iteration": iteration, "iteration": iteration,
}) })
// Publish status update for channels that support placeholder editing
if !constants.IsInternalChannel(opts.Channel) {
al.bus.PublishOutbound(bus.OutboundMessage{
Channel: opts.Channel,
ChatID: opts.ChatID,
Content: fmt.Sprintf("🔧 %s (%d/%d)", strings.Join(toolNames, ", "), iteration, agent.MaxIterations),
IsStatus: true,
})
}
// Build assistant message with tool calls // Build assistant message with tool calls
assistantMsg := providers.Message{ assistantMsg := providers.Message{
Role: "assistant", Role: "assistant",

View file

@ -11,9 +11,10 @@ type InboundMessage struct {
} }
type OutboundMessage struct { type OutboundMessage struct {
Channel string `json:"channel"` Channel string `json:"channel"`
ChatID string `json:"chat_id"` ChatID string `json:"chat_id"`
Content string `json:"content"` Content string `json:"content"`
IsStatus bool `json:"is_status,omitempty"`
} }
type MessageHandler func(InboundMessage) error type MessageHandler func(InboundMessage) error

View file

@ -272,6 +272,20 @@ func (m *Manager) dispatchOutbound(ctx context.Context) {
continue continue
} }
if msg.IsStatus {
if sc, ok := channel.(interface {
EditStatus(context.Context, bus.OutboundMessage) error
}); ok {
if err := sc.EditStatus(ctx, msg); err != nil {
logger.DebugCF("channels", "EditStatus failed", map[string]interface{}{
"channel": msg.Channel,
"error": err.Error(),
})
}
}
continue
}
if err := channel.Send(ctx, msg); err != nil { if err := channel.Send(ctx, msg); err != nil {
logger.ErrorCF("channels", "Error sending message to channel", map[string]interface{}{ logger.ErrorCF("channels", "Error sending message to channel", map[string]interface{}{
"channel": msg.Channel, "channel": msg.Channel,

View file

@ -146,6 +146,23 @@ func (c *TelegramChannel) Stop(ctx context.Context) error {
return nil return nil
} }
func (c *TelegramChannel) EditStatus(ctx context.Context, msg bus.OutboundMessage) error {
if !c.IsRunning() {
return nil
}
chatID, err := parseChatID(msg.ChatID)
if err != nil {
return nil
}
pID, ok := c.placeholders.Load(msg.ChatID)
if !ok {
return nil // no placeholder → nothing to edit
}
editMsg := tu.EditMessageText(tu.ID(chatID), pID.(int), msg.Content)
_, err = c.bot.EditMessageText(ctx, editMsg)
return err
}
func (c *TelegramChannel) Send(ctx context.Context, msg bus.OutboundMessage) error { func (c *TelegramChannel) Send(ctx context.Context, msg bus.OutboundMessage) error {
if !c.IsRunning() { if !c.IsRunning() {
return fmt.Errorf("telegram bot not running") return fmt.Errorf("telegram bot not running")