diff --git a/pkg/channels/qq/qq.go b/pkg/channels/qq/qq.go index 2ba43cdf3..4b8124398 100644 --- a/pkg/channels/qq/qq.go +++ b/pkg/channels/qq/qq.go @@ -30,9 +30,9 @@ type QQChannel struct { sessionManager botgo.SessionManager processedIDs map[string]bool mu sync.RWMutex -} chatTypeMap map[string]string // Track whether a ChatID is group or C2C chatTypeMu sync.RWMutex // Protects chatTypeMap +} func NewQQChannel(cfg config.QQConfig, messageBus *bus.MessageBus) (*QQChannel, error) { base := channels.NewBaseChannel("qq", cfg, messageBus, cfg.AllowFrom, diff --git a/pkg/tools/subagent.go b/pkg/tools/subagent.go index 69f1a49a2..f1cbc83a7 100644 --- a/pkg/tools/subagent.go +++ b/pkg/tools/subagent.go @@ -216,19 +216,19 @@ After completing the task, provide a clear summary of what was done.` } // Send announce message back to main agent - if sm.bus != nil { - announceContent := fmt.Sprintf("Task '%s' completed.\n\nResult:\n%s", task.Label, task.Result) - pubCtx, pubCancel := context.WithTimeout(context.Background(), 5*time.Second) - defer pubCancel() - sm.bus.PublishInbound(pubCtx, bus.InboundMessage{ - Channel: "system", - SenderID: fmt.Sprintf("subagent:%s", task.ID), - // Format: "original_channel:original_chat_id" for routing back - ChatID: fmt.Sprintf("%s:%s", task.OriginChannel, task.OriginChatID), - Content: announceContent, + // Use sync.Once to ensure the announcement is sent only once + task.announcedOnce.Do(func() { + announceContent := fmt.Sprintf("Task '%s' completed.\n\nResult:\n%s", task.Label, task.Result) + pubCtx, pubCancel := context.WithTimeout(context.Background(), 5*time.Second) + defer pubCancel() + sm.bus.PublishInbound(pubCtx, bus.InboundMessage{ + Channel: "system", + SenderID: fmt.Sprintf("subagent:%s", task.ID), + // Format: "original_channel:original_chat_id" for routing back + ChatID: fmt.Sprintf("%s:%s", task.OriginChannel, task.OriginChatID), + Content: announceContent, + }) }) - } -} func (sm *SubagentManager) GetTask(taskID string) (*SubagentTask, bool) { sm.mu.RLock()