Files
nofx/agent/skill_semantic_gate.go

247 lines
6.6 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package agent
import (
"encoding/json"
"strings"
"nofx/store"
)
func (a *Agent) skillVisibleFieldSummary(storeUserID, lang, skillName, action string) string {
fieldNames := make([]string, 0, 20)
add := func(field string) {
field = strings.TrimSpace(field)
if field == "" {
return
}
for _, existing := range fieldNames {
if existing == field {
return
}
}
fieldNames = append(fieldNames, field)
}
switch skillName {
case "model_management":
if lang == "zh" {
add("Provider")
} else {
add("provider")
}
add(displayCatalogFieldName("name", lang))
for _, field := range manualModelEditableFieldKeys() {
add(displayCatalogFieldName(field, lang))
}
case "exchange_management":
add(slotDisplayName("exchange_type", lang))
for _, field := range manualExchangeEditableFieldKeys() {
add(displayCatalogFieldName(field, lang))
}
case "trader_management":
if strings.TrimSpace(action) == "create" {
add(slotDisplayName("name", lang))
}
for _, field := range manualTraderEditableFieldKeys() {
add(displayCatalogFieldName(field, lang))
}
case "strategy_management":
add(slotDisplayName("name", lang))
for _, field := range manualStrategyEditableFieldKeys() {
add(strategyConfigFieldDisplayName(field, lang))
}
}
if len(fieldNames) == 0 {
return ""
}
prefix := "Visible UI fields"
if lang == "zh" {
prefix = "当前可见字段"
}
return prefix + "" + strings.Join(fieldNames, "、")
}
func (a *Agent) strategyTypeForTarget(storeUserID string, target *EntityReference) (string, bool) {
if a == nil || a.store == nil || target == nil {
return "", false
}
var strategy *store.Strategy
var err error
if id := strings.TrimSpace(target.ID); id != "" {
strategy, err = a.store.Strategy().Get(storeUserID, id)
} else if name := strings.TrimSpace(target.Name); name != "" {
strategies, listErr := a.store.Strategy().List(storeUserID)
if listErr != nil {
return "", false
}
for _, item := range strategies {
if item != nil && strings.EqualFold(strings.TrimSpace(item.Name), name) {
strategy = item
break
}
}
} else {
return "", false
}
if err != nil || strategy == nil {
return "", false
}
cfg := store.GetDefaultStrategyConfig("zh")
if strings.TrimSpace(strategy.Config) != "" {
_ = json.Unmarshal([]byte(strategy.Config), &cfg)
}
strategyType := strings.TrimSpace(cfg.StrategyType)
if strategyType == "" {
strategyType = "ai_trading"
}
return strategyType, true
}
func (a *Agent) skillVisibleOptionSummary(storeUserID, lang, skillName, action string) string {
switch skillName {
case "model_management":
return a.modelSkillOptionSummary(lang)
case "exchange_management":
return a.exchangeSkillOptionSummary(lang)
case "trader_management":
return a.traderSkillOptionSummary(storeUserID, lang)
case "strategy_management":
return a.strategySkillOptionSummary(storeUserID, lang)
default:
return ""
}
}
func (a *Agent) modelSkillOptionSummary(lang string) string {
if lang == "zh" {
return modelProviderChoicePrompt(lang)
}
return modelProviderChoicePrompt(lang)
}
func (a *Agent) exchangeSkillOptionSummary(lang string) string {
options := enumOptionValues("exchange_management", "exchange_type")
if len(options) == 0 {
options = []string{"Binance", "Bybit", "OKX", "Bitget", "Gate", "KuCoin", "Hyperliquid", "Aster", "Lighter", "Indodax"}
}
if lang == "zh" {
return "交易所类型选项:" + strings.Join(options, "、")
}
return "Exchange type options: " + strings.Join(options, ", ")
}
func enumOptionValues(skillName, field string) []string {
def, ok := getSkillDefinition(skillName)
if !ok {
return nil
}
constraint, ok := def.FieldConstraints[field]
if !ok || len(constraint.Values) == 0 {
return nil
}
values := make([]string, 0, len(constraint.Values))
for _, value := range constraint.Values {
if value == "" {
continue
}
switch value {
case "openai":
values = append(values, "OpenAI")
case "deepseek":
values = append(values, "DeepSeek")
case "claude":
values = append(values, "Claude")
case "gemini":
values = append(values, "Gemini")
case "qwen":
values = append(values, "Qwen")
case "kimi":
values = append(values, "Kimi")
case "grok":
values = append(values, "Grok")
case "minimax":
values = append(values, "Minimax")
case "binance":
values = append(values, "Binance")
case "okx":
values = append(values, "OKX")
case "bybit":
values = append(values, "Bybit")
case "gate":
values = append(values, "Gate")
case "kucoin":
values = append(values, "KuCoin")
case "bitget":
values = append(values, "Bitget")
case "hyperliquid":
values = append(values, "Hyperliquid")
case "aster":
values = append(values, "Aster")
case "lighter":
values = append(values, "Lighter")
case "indodax":
values = append(values, "Indodax")
default:
values = append(values, value)
}
}
return values
}
func (a *Agent) traderSkillOptionSummary(storeUserID, lang string) string {
parts := []string{
formatSkillOptionList(lang, "可选模型", "Available models", a.loadEnabledModelOptions(storeUserID)),
formatSkillOptionList(lang, "可选交易所", "Available exchanges", a.loadExchangeOptions(storeUserID)),
formatSkillOptionList(lang, "可选策略", "Available strategies", a.loadStrategyOptions(storeUserID)),
}
return strings.Join(filterNonEmptyStrings(parts), "\n")
}
func (a *Agent) strategySkillOptionSummary(storeUserID, lang string) string {
parts := []string{
"",
formatSkillOptionList(lang, "现有策略", "Existing strategies", a.loadStrategyOptions(storeUserID)),
}
sourceOptions := []string{"static", "ai500", "oi_top", "oi_low"}
if lang == "zh" {
parts[0] = "选币来源选项static、ai500、oi_top、oi_low"
} else {
parts[0] = "Coin source options: static, ai500, oi_top, oi_low"
}
_ = sourceOptions
return strings.Join(filterNonEmptyStrings(parts), "\n")
}
func formatSkillOptionList(lang, zhPrefix, enPrefix string, options []traderSkillOption) string {
names := make([]string, 0, len(options))
for _, option := range options {
label := strings.TrimSpace(defaultIfEmpty(option.Name, option.ID))
if label == "" {
continue
}
names = append(names, label)
}
if len(names) == 0 {
if lang == "zh" {
return zhPrefix + ":暂无"
}
return enPrefix + ": none"
}
if lang == "zh" {
return zhPrefix + "" + strings.Join(names, "、")
}
return enPrefix + ": " + strings.Join(names, ", ")
}
func filterNonEmptyStrings(items []string) []string {
out := make([]string, 0, len(items))
for _, item := range items {
item = strings.TrimSpace(item)
if item == "" {
continue
}
out = append(out, item)
}
return out
}