- Introduced Weixin integration support with new configuration options for WeChat iLink Bot. - Updated existing adapters (DingTalk, Discord, Feishu, Telegram) to include sender_id and app_id in message metadata for improved context handling. - Enhanced dispatcher logic to accommodate the new Weixin adapter and ensure proper initialization and shutdown processes. - Improved message handling across integrations to support typing indicators, providing a more interactive user experience.
155 lines
4 KiB
Go
155 lines
4 KiB
Go
package api
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"sync"
|
|
|
|
robotevents "github.com/yaoapp/yao/agent/robot/events"
|
|
"github.com/yaoapp/yao/agent/robot/events/integrations"
|
|
dtadapter "github.com/yaoapp/yao/agent/robot/events/integrations/dingtalk"
|
|
dcadapter "github.com/yaoapp/yao/agent/robot/events/integrations/discord"
|
|
fsadapter "github.com/yaoapp/yao/agent/robot/events/integrations/feishu"
|
|
"github.com/yaoapp/yao/agent/robot/events/integrations/telegram"
|
|
weixinadapter "github.com/yaoapp/yao/agent/robot/events/integrations/weixin"
|
|
"github.com/yaoapp/yao/agent/robot/logger"
|
|
"github.com/yaoapp/yao/agent/robot/manager"
|
|
"github.com/yaoapp/yao/agent/robot/types"
|
|
)
|
|
|
|
var log = logger.New("robot")
|
|
|
|
func init() {
|
|
robotevents.RegisterTriggerFunc(func(ctx *types.Context, memberID string, triggerType types.TriggerType, data interface{}) (string, bool, error) {
|
|
result, err := TriggerManual(ctx, memberID, triggerType, data)
|
|
if err != nil {
|
|
return "", false, err
|
|
}
|
|
return result.ExecutionID, result.Accepted, nil
|
|
})
|
|
}
|
|
|
|
// ==================== Lifecycle API ====================
|
|
// These functions manage the robot agent system lifecycle
|
|
|
|
var (
|
|
globalManager *manager.Manager
|
|
globalDispatcher *integrations.Dispatcher
|
|
managerMu sync.RWMutex
|
|
)
|
|
|
|
// Start starts the robot agent system
|
|
// This initializes and starts the manager which handles:
|
|
// - Robot cache loading
|
|
// - Worker pool
|
|
// - Clock ticker for scheduled triggers
|
|
func Start() error {
|
|
managerMu.Lock()
|
|
defer managerMu.Unlock()
|
|
|
|
if globalManager != nil && globalManager.IsStarted() {
|
|
return fmt.Errorf("robot agent system already started")
|
|
}
|
|
|
|
// Create new manager if not exists
|
|
if globalManager == nil {
|
|
globalManager = manager.New()
|
|
}
|
|
|
|
if err := globalManager.Start(); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Start integration dispatcher (Telegram polling, webhook subscriptions, etc.)
|
|
adapters := map[string]integrations.Adapter{
|
|
"telegram": telegram.NewAdapter(),
|
|
"feishu": fsadapter.NewAdapter(),
|
|
"dingtalk": dtadapter.NewAdapter(),
|
|
"discord": dcadapter.NewAdapter(),
|
|
"weixin": weixinadapter.NewAdapter(),
|
|
}
|
|
globalDispatcher = integrations.NewDispatcher(globalManager.Cache(), adapters)
|
|
if err := globalDispatcher.Start(context.Background()); err != nil {
|
|
log.Error("failed to start integration dispatcher: %v", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// StartWithConfig starts the robot agent system with custom configuration
|
|
func StartWithConfig(config *manager.Config) error {
|
|
managerMu.Lock()
|
|
defer managerMu.Unlock()
|
|
|
|
if globalManager != nil && globalManager.IsStarted() {
|
|
return fmt.Errorf("robot agent system already started")
|
|
}
|
|
|
|
globalManager = manager.NewWithConfig(config)
|
|
return globalManager.Start()
|
|
}
|
|
|
|
// Stop stops the robot agent system gracefully
|
|
// This will:
|
|
// - Stop the clock ticker
|
|
// - Stop cache auto-refresh
|
|
// - Wait for running jobs to complete
|
|
// - Stop the worker pool
|
|
func Stop() error {
|
|
managerMu.Lock()
|
|
defer managerMu.Unlock()
|
|
|
|
if globalManager == nil {
|
|
return nil
|
|
}
|
|
|
|
if globalDispatcher != nil {
|
|
globalDispatcher.Stop()
|
|
globalDispatcher = nil
|
|
}
|
|
|
|
err := globalManager.Stop()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
globalManager = nil
|
|
return nil
|
|
}
|
|
|
|
// IsRunning returns true if the robot agent system is running
|
|
func IsRunning() bool {
|
|
managerMu.RLock()
|
|
defer managerMu.RUnlock()
|
|
|
|
return globalManager != nil && globalManager.IsStarted()
|
|
}
|
|
|
|
// getManager returns the global manager instance
|
|
// Returns error if manager is not started
|
|
func getManager() (*manager.Manager, error) {
|
|
managerMu.RLock()
|
|
defer managerMu.RUnlock()
|
|
|
|
if globalManager == nil || !globalManager.IsStarted() {
|
|
return nil, fmt.Errorf("robot agent system not started")
|
|
}
|
|
return globalManager, nil
|
|
}
|
|
|
|
// GetManager returns the global manager instance, or nil if not started.
|
|
func GetManager() *manager.Manager {
|
|
managerMu.RLock()
|
|
defer managerMu.RUnlock()
|
|
if globalManager == nil || !globalManager.IsStarted() {
|
|
return nil
|
|
}
|
|
return globalManager
|
|
}
|
|
|
|
// SetManager sets the global manager instance (for testing)
|
|
func SetManager(m *manager.Manager) {
|
|
managerMu.Lock()
|
|
defer managerMu.Unlock()
|
|
globalManager = m
|
|
}
|