From 380f28b25ff9194c27d0e17cd7c1848cd8f0cad1 Mon Sep 17 00:00:00 2001 From: Guoguo Date: Wed, 29 Apr 2026 19:17:44 -0700 Subject: [PATCH] fix(channels): pass InboundContext to DismissToolFeedback for topic-aware keys Telegram forum topics use scoped tracker keys like "chatID/topicID", resolved via ToolFeedbackMessageChatID with the InboundContext. The previous nil context caused the lookup to fall back to the raw chatID, missing the topic-scoped entry and leaving the animation goroutine orphaned in forum-topic conversations. Co-Authored-By: Claude Opus 4.7 (1M context) --- pkg/agent/adapters/channelmanager.go | 4 ++-- pkg/agent/interfaces/interfaces.go | 4 +++- pkg/agent/pipeline_execute.go | 2 +- pkg/channels/manager.go | 6 ++++-- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/pkg/agent/adapters/channelmanager.go b/pkg/agent/adapters/channelmanager.go index 185269e0c..0dd8dc384 100644 --- a/pkg/agent/adapters/channelmanager.go +++ b/pkg/agent/adapters/channelmanager.go @@ -44,6 +44,6 @@ func (a *channelManagerAdapter) SendPlaceholder(ctx context.Context, channel, ch return a.inner.SendPlaceholder(ctx, channel, chatID) } -func (a *channelManagerAdapter) DismissToolFeedback(ctx context.Context, channel, chatID string) { - a.inner.DismissToolFeedback(ctx, channel, chatID) +func (a *channelManagerAdapter) DismissToolFeedback(ctx context.Context, channel, chatID string, outboundCtx *bus.InboundContext) { + a.inner.DismissToolFeedback(ctx, channel, chatID, outboundCtx) } diff --git a/pkg/agent/interfaces/interfaces.go b/pkg/agent/interfaces/interfaces.go index 93c8df0f6..2efec05e1 100644 --- a/pkg/agent/interfaces/interfaces.go +++ b/pkg/agent/interfaces/interfaces.go @@ -48,5 +48,7 @@ type ChannelManager interface { // DismissToolFeedback clears any tracked tool feedback animation for the // given channel/chat. Call this when a turn ends without a final response // (e.g., ResponseHandled tools) to avoid orphaned animation goroutines. - DismissToolFeedback(ctx context.Context, channel, chatID string) + // outboundCtx carries topic/thread info needed for channels that use + // scoped tracker keys (e.g., Telegram forum topics); may be nil. + DismissToolFeedback(ctx context.Context, channel, chatID string, outboundCtx *bus.InboundContext) } diff --git a/pkg/agent/pipeline_execute.go b/pkg/agent/pipeline_execute.go index 88aebe45d..f6a8eaad6 100644 --- a/pkg/agent/pipeline_execute.go +++ b/pkg/agent/pipeline_execute.go @@ -705,7 +705,7 @@ toolLoop: ts.setPhase(TurnPhaseCompleted) ts.setFinalContent("") if al.channelManager != nil && ts.channel != "" { - al.channelManager.DismissToolFeedback(ctx, ts.channel, ts.chatID) + al.channelManager.DismissToolFeedback(ctx, ts.channel, ts.chatID, ts.opts.InboundContext) } logger.InfoCF("agent", "Tool output satisfied delivery; ending turn without follow-up LLM", map[string]any{ diff --git a/pkg/channels/manager.go b/pkg/channels/manager.go index b87341c6a..eb9d3f75c 100644 --- a/pkg/channels/manager.go +++ b/pkg/channels/manager.go @@ -195,12 +195,14 @@ func clearTrackedToolFeedbackMessage( // DismissToolFeedback clears any tracked tool feedback animation for the // given channel/chat. This is called when a turn ends without a final // response (e.g., ResponseHandled tools) to stop orphaned animation goroutines. -func (m *Manager) DismissToolFeedback(ctx context.Context, channelName, chatID string) { +// outboundCtx carries topic/thread info for channels that use scoped tracker +// keys (e.g., Telegram forum topics); may be nil for non-topic channels. +func (m *Manager) DismissToolFeedback(ctx context.Context, channelName, chatID string, outboundCtx *bus.InboundContext) { ch, ok := m.GetChannel(channelName) if !ok { return } - dismissTrackedToolFeedbackMessage(ctx, ch, chatID, nil) + dismissTrackedToolFeedbackMessage(ctx, ch, chatID, outboundCtx) } func prepareToolFeedbackMessageContent(ch Channel, content string) string {