mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-14 16:26:57 +08:00
feat: NOFXi Agent integrated into NOFX core
This is the key architectural change: NOFXi is no longer a separate sub-project in nofxi/, but a first-class module in agent/ that sits on top of NOFX's existing engine. agent/ package: - agent.go: Core orchestrator, directly uses NOFX's TraderManager, Store, and Market packages. No wrapper/bridge needed. - brain.go: Proactive intelligence (news scan, market briefs, signal handling) - sentinel.go: Market anomaly detection (price breakout, volume spike, funding rate) - scheduler.go: Daily reports, position risk checks - router.go: Intent routing for natural language (中/英 bilingual) - i18n.go: Full Chinese/English message catalog - web.go: Agent REST API on :8900 (chat, klines, ticker) main.go changes: - Banner: NOFX → NOFXi - Agent auto-starts with NOFX (sentinel + brain + scheduler + web) - Zero breaking changes to existing NOFX functionality Key difference from old nofxi/: - Agent reads LIVE data from TraderManager (positions, balances, status) - Uses market.Get() for full technical indicators (EMA/MACD/RSI/BB) - No duplicate code — kernel, trader, store all used directly - Old nofxi/ sub-project will be removed once migration is verified Architecture: NOFX (engine) → kernel + trader + market + store + mcp + telegram NOFXi (brain) → agent/ package → uses all of the above
This commit is contained in:
102
agent/router.go
Normal file
102
agent/router.go
Normal file
@@ -0,0 +1,102 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type IntentType int
|
||||
|
||||
const (
|
||||
IntentChat IntentType = iota
|
||||
IntentTrade
|
||||
IntentQuery
|
||||
IntentAnalyze
|
||||
IntentSettings
|
||||
IntentHelp
|
||||
IntentStatus
|
||||
IntentWatch
|
||||
IntentStrategy
|
||||
)
|
||||
|
||||
type Intent struct {
|
||||
Type IntentType
|
||||
Params map[string]string
|
||||
Raw string
|
||||
}
|
||||
|
||||
type Router struct {
|
||||
tradePatterns []*regexp.Regexp
|
||||
queryPatterns []*regexp.Regexp
|
||||
analyzePatterns []*regexp.Regexp
|
||||
}
|
||||
|
||||
func NewRouter() *Router {
|
||||
return &Router{
|
||||
tradePatterns: []*regexp.Regexp{
|
||||
regexp.MustCompile(`(?i)(buy|sell|long|short|open|close)\s+(.+)`),
|
||||
regexp.MustCompile(`(?i)(做多|做空|买入|卖出|开仓|平仓)\s*(.+)`),
|
||||
},
|
||||
queryPatterns: []*regexp.Regexp{
|
||||
regexp.MustCompile(`(?i)(position|balance|pnl|profit|loss|持仓|余额|盈亏|trader|交易员)`),
|
||||
},
|
||||
analyzePatterns: []*regexp.Regexp{
|
||||
regexp.MustCompile(`(?i)(analyze|analysis|分析|看看)\s+(.+)`),
|
||||
regexp.MustCompile(`(?i)(what.*think|怎么看|你觉得)\s*(.+)?`),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Router) Route(text string) Intent {
|
||||
text = strings.TrimSpace(text)
|
||||
|
||||
if strings.HasPrefix(text, "/") {
|
||||
return r.routeCommand(text)
|
||||
}
|
||||
|
||||
for _, p := range r.tradePatterns {
|
||||
if m := p.FindStringSubmatch(text); m != nil {
|
||||
return Intent{Type: IntentTrade, Params: map[string]string{"action": strings.ToLower(m[1]), "detail": m[2]}, Raw: text}
|
||||
}
|
||||
}
|
||||
for _, p := range r.queryPatterns {
|
||||
if p.MatchString(text) {
|
||||
return Intent{Type: IntentQuery, Raw: text}
|
||||
}
|
||||
}
|
||||
for _, p := range r.analyzePatterns {
|
||||
if m := p.FindStringSubmatch(text); m != nil {
|
||||
d := ""
|
||||
if len(m) > 2 { d = m[2] }
|
||||
return Intent{Type: IntentAnalyze, Params: map[string]string{"detail": d}, Raw: text}
|
||||
}
|
||||
}
|
||||
|
||||
return Intent{Type: IntentChat, Raw: text}
|
||||
}
|
||||
|
||||
func (r *Router) routeCommand(text string) Intent {
|
||||
cmd := strings.ToLower(strings.Fields(text)[0])
|
||||
parts := strings.SplitN(text, " ", 2)
|
||||
detail := ""
|
||||
if len(parts) > 1 { detail = parts[1] }
|
||||
|
||||
switch cmd {
|
||||
case "/start", "/help":
|
||||
return Intent{Type: IntentHelp, Raw: text}
|
||||
case "/status":
|
||||
return Intent{Type: IntentStatus, Raw: text}
|
||||
case "/buy", "/sell", "/long", "/short", "/open", "/close":
|
||||
return Intent{Type: IntentTrade, Params: map[string]string{"action": strings.TrimPrefix(cmd, "/"), "detail": detail}, Raw: text}
|
||||
case "/positions", "/balance", "/pnl", "/traders":
|
||||
return Intent{Type: IntentQuery, Raw: text}
|
||||
case "/analyze":
|
||||
return Intent{Type: IntentAnalyze, Params: map[string]string{"detail": detail}, Raw: text}
|
||||
case "/watch", "/unwatch":
|
||||
return Intent{Type: IntentWatch, Raw: text}
|
||||
case "/strategy":
|
||||
return Intent{Type: IntentStrategy, Raw: text}
|
||||
default:
|
||||
return Intent{Type: IntentChat, Raw: text}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user