Simplify agent skill routing and config updates

This commit is contained in:
lky-spec
2026-04-26 22:22:12 +08:00
parent cfd91069d3
commit ce3a8582af
12 changed files with 325 additions and 925 deletions

View File

@@ -13,10 +13,6 @@ import (
var urlPattern = regexp.MustCompile(`https://[^\s"'<>]+`)
func detectTraderManagementIntent(text string) bool {
return false
}
func hasExplicitCreateIntentForDomain(text, domain string) bool {
lower := strings.ToLower(strings.TrimSpace(text))
if lower == "" || !hasExplicitManagementDomainCue(text, domain) {
@@ -25,18 +21,6 @@ func hasExplicitCreateIntentForDomain(text, domain string) bool {
return containsAny(lower, []string{"创建", "新建", "创一个", "创个", "建一个", "create", "new"})
}
func detectExchangeManagementIntent(text string) bool {
return false
}
func detectModelManagementIntent(text string) bool {
return false
}
func detectStrategyManagementIntent(text string) bool {
return false
}
func hasExplicitDiagnosisIntentForDomain(text, domain string) bool {
lower := strings.ToLower(strings.TrimSpace(text))
if lower == "" || !hasExplicitManagementDomainCue(text, domain) {
@@ -56,10 +40,6 @@ func hasExplicitDiagnosisIntentForDomain(text, domain string) bool {
}
}
func inferExplicitManagementAction(text string, domain string) string {
return ""
}
func extractURL(text string) string {
return strings.TrimSpace(urlPattern.FindString(text))
}
@@ -209,20 +189,6 @@ func hasStrictOptionMention(text string, options []traderSkillOption) bool {
return false
}
func shouldUsePatchFallbackForTargetedUpdate(text string, options []traderSkillOption, existing *EntityReference) bool {
if existing != nil && strings.TrimSpace(existing.ID) != "" {
return true
}
if hasStrictOptionMention(text, options) {
return true
}
lower := strings.ToLower(strings.TrimSpace(text))
if containsAny(lower, []string{"这个", "当前", "该", "this", "current"}) {
return true
}
return len(options) == 1
}
func isSimpleEntityMutationAction(action string) bool {
switch strings.TrimSpace(action) {
case "update", "update_name", "update_status", "update_endpoint", "update_bindings",
@@ -298,82 +264,6 @@ func (a *Agent) buildSimpleEntityConversationResources(storeUserID string, sessi
return resources
}
func applySkillConversationResultToSession(session *skillSession, result skillConversationResult) {
if session == nil {
return
}
ensureSkillFields(session)
mergeFieldSet := func(values map[string]string, source string) {
for key, value := range values {
value = strings.TrimSpace(value)
if value == "" {
continue
}
switch key {
case "target_ref_id":
if session.TargetRef == nil {
session.TargetRef = &EntityReference{}
}
session.TargetRef.ID = value
if source != "" {
session.TargetRef.Source = source
}
case "target_ref_name":
if session.TargetRef == nil {
session.TargetRef = &EntityReference{}
}
session.TargetRef.Name = value
if source != "" {
session.TargetRef.Source = source
}
default:
setField(session, key, value)
}
}
}
mergeFieldSet(result.Extracted, "llm_conversation")
mergeFieldSet(result.DraftGeneratedFields, "llm_generated_draft")
if result.RequiresConfirmationBeforeApply {
setField(session, "_requires_generated_confirmation", "true")
} else if fieldValue(*session, "_requires_generated_confirmation") != "" {
delete(session.Fields, "_requires_generated_confirmation")
}
if session.TargetRef != nil && session.TargetRef.Source == "" {
session.TargetRef.Source = "llm_conversation"
}
}
func shouldUseLLMConversationForSimpleEntity(skillName, action string) bool {
switch skillName {
case "trader_management":
switch action {
case "update", "update_name", "update_bindings", "configure_strategy", "configure_exchange", "configure_model":
return true
}
case "exchange_management":
switch action {
case "update", "update_name", "update_status":
return true
}
case "model_management":
switch action {
case "update", "update_name", "update_status", "update_endpoint":
return true
}
case "strategy_management":
switch action {
case "update", "update_name", "update_prompt", "update_config", "activate", "duplicate":
return true
}
}
switch action {
case "update_bindings", "configure_strategy", "configure_exchange", "configure_model":
return true
default:
return false
}
}
func (a *Agent) inferredCurrentReferenceForSkill(userID int64, skillName string) *EntityReference {
refs := a.semanticCurrentReferences(userID)
if refs == nil {
@@ -475,6 +365,7 @@ func (a *Agent) handleStrategyManagementSkill(storeUserID string, userID int64,
}
const strategyCreateDraftConfigField = "strategy_create_draft_config"
const strategyCreateConfigPatchField = "config_patch"
func applyStrategyCreateIntentToConfig(cfg *store.StrategyConfig, text, lang string) []string {
return nil
@@ -499,6 +390,25 @@ func unmarshalStrategyCreateDraft(raw, lang string) store.StrategyConfig {
return cfg
}
func strategyCreateConfigFromSession(session skillSession, lang string) (store.StrategyConfig, map[string]any, []string, error) {
cfg := unmarshalStrategyCreateDraft(fieldValue(session, strategyCreateDraftConfigField), lang)
patchRaw := strings.TrimSpace(fieldValue(session, strategyCreateConfigPatchField))
var patch map[string]any
if patchRaw != "" {
if err := json.Unmarshal([]byte(patchRaw), &patch); err != nil {
return cfg, nil, nil, fmt.Errorf("策略配置 patch 不是合法 JSON%w", err)
}
merged, err := store.MergeStrategyConfig(cfg, patch)
if err != nil {
return cfg, nil, nil, fmt.Errorf("策略配置 patch 无法应用:%w", err)
}
cfg = merged
}
beforeClamp := cfg
cfg.ClampLimits()
return cfg, patch, store.StrategyClampWarnings(beforeClamp, cfg, cfg.Language), nil
}
func strategyCreateConfirmationReply(text string) bool {
lower := strings.ToLower(strings.TrimSpace(text))
if lower == "" {
@@ -1721,8 +1631,25 @@ func (a *Agent) handleStrategyCreateSkill(storeUserID string, userID int64, lang
}
return "To create a strategy, I need a strategy name. You can say: create a strategy called 'Trend A'."
}
_, patch, warnings, cfgErr := strategyCreateConfigFromSession(session, lang)
if cfgErr != nil {
a.saveSkillSession(userID, session)
if lang == "zh" {
return "创建策略失败:" + cfgErr.Error()
}
return "That strategy config could not be prepared: " + cfgErr.Error()
}
setSkillDAGStep(&session, "execute_create")
args := map[string]any{"action": "create", "name": name, "lang": "zh"}
args := map[string]any{
"action": "create",
"name": name,
"lang": defaultIfEmpty(lang, "zh"),
"allow_clamped_update": true,
}
if len(patch) > 0 {
args["config"] = patch
}
raw, _ := json.Marshal(args)
resp := a.toolManageStrategy(storeUserID, string(raw))
if errMsg := parseSkillError(resp); strings.Contains(resp, `"error"`) {
@@ -1735,9 +1662,17 @@ func (a *Agent) handleStrategyCreateSkill(storeUserID string, userID int64, lang
a.clearSkillSession(userID)
a.rememberReferencesFromToolResult(userID, "manage_strategy", resp)
if lang == "zh" {
return fmt.Sprintf("已创建策略“%s”。默认配置已就绪,你后续可以继续让我帮你改细节。", name)
reply := fmt.Sprintf("已创建策略“%s”,并已按你的需求生成配置。", name)
if len(warnings) > 0 {
reply += "\n有些值超出安全范围系统已自动收敛\n- " + strings.Join(warnings, "\n- ")
}
return reply
}
return fmt.Sprintf("Created strategy %q with the default configuration.", name)
reply := fmt.Sprintf("Created strategy %q with a config generated from your requirements.", name)
if len(warnings) > 0 {
reply += "\nSome values were clamped to product safety limits:\n- " + strings.Join(warnings, "\n- ")
}
return reply
}
func (a *Agent) handleSimpleEntitySkill(storeUserID string, userID int64, lang, text string, session skillSession, skillName, action string, options []traderSkillOption) (string, bool) {