mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-17 09:24:36 +08:00
feat: wire NOFXi Agent into Telegram bot
- Add NOFXiAgent interface and SetNOFXiAgent() in telegram/bot.go - Telegram messages now route through the unified agent.Agent instead of the legacy telegram/agent package - Language hint injected from Telegram config for proper i18n - Legacy telegram/agent path preserved as fallback - Agent created before Telegram bot starts in main.go - Build verified, API tested
This commit is contained in:
12
main.go
12
main.go
@@ -142,10 +142,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Start Telegram bot (if TELEGRAM_BOT_TOKEN is configured)
|
// Start NOFXi Agent (proactive intelligence layer) — must be created BEFORE Telegram bot
|
||||||
go telegram.Start(cfg, st, telegramReloadCh)
|
|
||||||
|
|
||||||
// Start NOFXi Agent (proactive intelligence layer)
|
|
||||||
nofxiAgent := nofxiagent.New(traderManager, st, nil, slog.Default())
|
nofxiAgent := nofxiagent.New(traderManager, st, nil, slog.Default())
|
||||||
|
|
||||||
// Try to get an AI client from existing trader configs
|
// Try to get an AI client from existing trader configs
|
||||||
@@ -164,6 +161,13 @@ func main() {
|
|||||||
agentWeb := nofxiagent.NewWebHandler(nofxiAgent, slog.Default())
|
agentWeb := nofxiagent.NewWebHandler(nofxiAgent, slog.Default())
|
||||||
server.RegisterAgentHandler(agentWeb)
|
server.RegisterAgentHandler(agentWeb)
|
||||||
|
|
||||||
|
// Wire NOFXi Agent into Telegram bot — messages route through the unified agent
|
||||||
|
telegram.SetNOFXiAgent(nofxiAgent)
|
||||||
|
logger.Info("🔗 NOFXi Agent connected to Telegram bot")
|
||||||
|
|
||||||
|
// Start Telegram bot (if token is configured)
|
||||||
|
go telegram.Start(cfg, st, telegramReloadCh)
|
||||||
|
|
||||||
logger.Info("🧠 NOFXi Agent started (sentinel + brain + scheduler + web:8900)")
|
logger.Info("🧠 NOFXi Agent started (sentinel + brain + scheduler + web:8900)")
|
||||||
|
|
||||||
// Wait for interrupt signal
|
// Wait for interrupt signal
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package telegram
|
package telegram
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"nofx/api"
|
"nofx/api"
|
||||||
"nofx/config"
|
"nofx/config"
|
||||||
"nofx/logger"
|
"nofx/logger"
|
||||||
@@ -17,6 +18,30 @@ import (
|
|||||||
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// NOFXiAgent is the interface that the new agent.Agent satisfies.
|
||||||
|
// When set, Telegram messages are routed through it instead of the legacy telegram/agent package.
|
||||||
|
type NOFXiAgent interface {
|
||||||
|
HandleMessage(ctx context.Context, userID int64, text string) (string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
nofxiAgentMu sync.RWMutex
|
||||||
|
nofxiAgent NOFXiAgent
|
||||||
|
)
|
||||||
|
|
||||||
|
// SetNOFXiAgent registers the new NOFXi agent for Telegram message routing.
|
||||||
|
func SetNOFXiAgent(a NOFXiAgent) {
|
||||||
|
nofxiAgentMu.Lock()
|
||||||
|
defer nofxiAgentMu.Unlock()
|
||||||
|
nofxiAgent = a
|
||||||
|
}
|
||||||
|
|
||||||
|
func getNOFXiAgent() NOFXiAgent {
|
||||||
|
nofxiAgentMu.RLock()
|
||||||
|
defer nofxiAgentMu.RUnlock()
|
||||||
|
return nofxiAgent
|
||||||
|
}
|
||||||
|
|
||||||
// Start initializes and runs the Telegram bot in a blocking supervisor loop.
|
// Start initializes and runs the Telegram bot in a blocking supervisor loop.
|
||||||
// Supports hot-reload: when a signal is sent on reloadCh, the bot restarts
|
// Supports hot-reload: when a signal is sent on reloadCh, the bot restarts
|
||||||
// with the latest token (re-read from DB or env). Must be called as a goroutine from main.go.
|
// with the latest token (re-read from DB or env). Must be called as a goroutine from main.go.
|
||||||
@@ -208,25 +233,46 @@ func runBot(token string, cfg *config.Config, st *store.Store) bool {
|
|||||||
placeholderID = sent.MessageID
|
placeholderID = sent.MessageID
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var reply string
|
||||||
mu sync.Mutex
|
|
||||||
lastEdit time.Time
|
|
||||||
)
|
|
||||||
onChunk := func(accumulated string) {
|
|
||||||
if placeholderID == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
mu.Lock()
|
|
||||||
defer mu.Unlock()
|
|
||||||
if accumulated != "⏳" && time.Since(lastEdit) < time.Second {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
lastEdit = time.Now()
|
|
||||||
edit := tgbotapi.NewEditMessageText(chatID, placeholderID, accumulated)
|
|
||||||
bot.Send(edit) //nolint:errcheck
|
|
||||||
}
|
|
||||||
|
|
||||||
reply := agents.Run(chatID, text, onChunk)
|
// Route through NOFXi Agent if available (new unified architecture),
|
||||||
|
// otherwise fall back to legacy telegram/agent manager.
|
||||||
|
if na := getNOFXiAgent(); na != nil {
|
||||||
|
lang := st.TelegramConfig().GetLanguage()
|
||||||
|
msg := text
|
||||||
|
if lang != "" {
|
||||||
|
msg = "[lang:" + lang + "] " + text
|
||||||
|
}
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 55*time.Second)
|
||||||
|
resp, err := na.HandleMessage(ctx, chatID, msg)
|
||||||
|
cancel()
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("NOFXi agent error: %v", err)
|
||||||
|
reply = "AI assistant temporarily unavailable. Please try again."
|
||||||
|
} else {
|
||||||
|
reply = resp
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Legacy path: stream via telegram/agent
|
||||||
|
var (
|
||||||
|
mu sync.Mutex
|
||||||
|
lastEdit time.Time
|
||||||
|
)
|
||||||
|
onChunk := func(accumulated string) {
|
||||||
|
if placeholderID == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
mu.Lock()
|
||||||
|
defer mu.Unlock()
|
||||||
|
if accumulated != "⏳" && time.Since(lastEdit) < time.Second {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
lastEdit = time.Now()
|
||||||
|
edit := tgbotapi.NewEditMessageText(chatID, placeholderID, accumulated)
|
||||||
|
bot.Send(edit) //nolint:errcheck
|
||||||
|
}
|
||||||
|
reply = agents.Run(chatID, text, onChunk)
|
||||||
|
}
|
||||||
|
|
||||||
if placeholderID != 0 {
|
if placeholderID != 0 {
|
||||||
edit := tgbotapi.NewEditMessageText(chatID, placeholderID, reply)
|
edit := tgbotapi.NewEditMessageText(chatID, placeholderID, reply)
|
||||||
|
|||||||
Reference in New Issue
Block a user