mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-06-06 05:51:19 +08:00
Centralize active skill field extraction
This commit is contained in:
@@ -44,7 +44,7 @@ func TestHandleModelCreateSkillAsksProviderFirstWithClaw402Recommendation(t *tes
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandleModelCreateSkillAcceptsBareClaw402PrivateKey(t *testing.T) {
|
||||
func TestHandleModelCreateSkillUsesCollectedClaw402PrivateKey(t *testing.T) {
|
||||
dbPath := filepath.Join(t.TempDir(), "agent-model-create-claw402.db")
|
||||
st, err := store.New(dbPath)
|
||||
if err != nil {
|
||||
@@ -57,13 +57,14 @@ func TestHandleModelCreateSkillAcceptsBareClaw402PrivateKey(t *testing.T) {
|
||||
Action: "create",
|
||||
Phase: "collecting",
|
||||
Fields: map[string]string{
|
||||
"provider": "claw402",
|
||||
"name": "Claw402 (Base USDC)",
|
||||
"provider": "claw402",
|
||||
"name": "Claw402 (Base USDC)",
|
||||
"api_key": "0x205d759b80bae1afa31a36c4afaeec0b10378c1c55e3363bcde5a1db75c747ca",
|
||||
"custom_model_name": "deepseek",
|
||||
},
|
||||
}
|
||||
|
||||
reply := a.handleModelCreateSkill("default", 42, "zh", "0x205d759b80bae1afa31a36c4afaeec0b10378c1c55e3363bcde5a1db75c747ca", session)
|
||||
reply := a.handleModelCreateSkill("default", 42, "zh", "继续", session)
|
||||
|
||||
if strings.Contains(reply, "还缺这些字段:钱包私钥") {
|
||||
t.Fatalf("expected bare private key to be accepted, got: %s", reply)
|
||||
|
||||
@@ -935,7 +935,7 @@ func (a *Agent) tryStatePriorityPath(ctx context.Context, storeUserID string, us
|
||||
if answer, ok := a.answerSkillSessionExplanation(storeUserID, lang, session, text); ok {
|
||||
return answer, true, nil
|
||||
}
|
||||
decision, extraction := a.resolveSkillSessionTurn(ctx, userID, lang, text, session)
|
||||
decision, _ := a.resolveSkillSessionTurn(ctx, userID, lang, text, session)
|
||||
switch decision.Intent {
|
||||
case "cancel":
|
||||
a.clearSkillSession(userID)
|
||||
@@ -947,10 +947,6 @@ func (a *Agent) tryStatePriorityPath(ctx context.Context, storeUserID string, us
|
||||
answer, handled, err := a.handoffFromActiveFlow(ctx, storeUserID, userID, lang, text, decision.TargetSnapshotID, onEvent)
|
||||
return answer, handled, err
|
||||
default:
|
||||
if extraction.Intent == "continue" {
|
||||
a.applyLLMExtractionToSkillSession(storeUserID, &session, extraction, lang, text)
|
||||
a.saveSkillSession(userID, session)
|
||||
}
|
||||
if answer, ok := a.dispatchBridgedSkillSession(storeUserID, userID, lang, text, session); ok {
|
||||
if onEvent != nil && strings.TrimSpace(answer) != "" {
|
||||
switch session.Name {
|
||||
@@ -1234,12 +1230,6 @@ func (a *Agent) resolveSkillSessionTurn(ctx context.Context, userID int64, lang,
|
||||
if isInstantDirectReplyText(text) {
|
||||
return unifiedFlowDecision{Intent: "instant_reply"}, llmFlowExtractionResult{Intent: "instant_reply"}
|
||||
}
|
||||
if a.aiClient != nil {
|
||||
result := a.extractSkillSessionFieldsWithLLM(ctx, userID, lang, text, session)
|
||||
if decision := unifiedFlowDecisionFromIntent(result.Intent, result.TargetSnapshotID); decision.Intent != "" {
|
||||
return decision, result
|
||||
}
|
||||
}
|
||||
return a.classifySkillSessionDecision(ctx, userID, lang, session, text), llmFlowExtractionResult{}
|
||||
}
|
||||
|
||||
|
||||
@@ -516,38 +516,6 @@ func (a *Agent) handleCreateTraderSkill(storeUserID string, userID int64, lang,
|
||||
}
|
||||
}
|
||||
|
||||
availableResources := a.buildTraderCreateConversationResources(storeUserID, session)
|
||||
result := skillConversationResult{}
|
||||
if a != nil && a.aiClient != nil {
|
||||
result = a.llmSkillConversationDriver(context.Background(), storeUserID, userID, lang, text, session, availableResources)
|
||||
} else {
|
||||
result = a.fallbackTraderCreateConversation(storeUserID, lang, text, session, availableResources)
|
||||
}
|
||||
if !result.Cancel && !result.UserRejectedFlow && !result.Ready && result.Question == "" && a != nil && a.aiClient != nil {
|
||||
if extraction := a.extractSkillSessionFieldsWithLLM(context.Background(), userID, lang, text, session); extraction.Intent == "continue" {
|
||||
a.applyLLMExtractionToSkillSession(storeUserID, &session, extraction, lang, text)
|
||||
}
|
||||
}
|
||||
|
||||
if result.Cancel {
|
||||
a.clearSkillSession(userID)
|
||||
if lang == "zh" {
|
||||
return "已取消当前创建交易员流程。", true
|
||||
}
|
||||
return "Cancelled the current trader creation flow.", true
|
||||
}
|
||||
if result.UserRejectedFlow {
|
||||
return a.rerouteRejectedSkillFlow(context.Background(), storeUserID, userID, lang, text)
|
||||
}
|
||||
|
||||
for k, v := range result.Extracted {
|
||||
v = strings.TrimSpace(v)
|
||||
if v == "" {
|
||||
continue
|
||||
}
|
||||
setField(&session, k, v)
|
||||
}
|
||||
|
||||
a.hydrateCreateTraderSlotReferences(storeUserID, &session)
|
||||
if fieldValue(session, "exchange_id") != "" && fieldValue(session, "model_id") != "" && fieldValue(session, "strategy_id") != "" {
|
||||
if err := a.validateTraderDraft(storeUserID, fieldValue(session, "model_id"), fieldValue(session, "exchange_id"), fieldValue(session, "strategy_id")); err != nil {
|
||||
@@ -561,15 +529,6 @@ func (a *Agent) handleCreateTraderSkill(storeUserID string, userID int64, lang,
|
||||
a.saveSkillSession(userID, session)
|
||||
return a.buildTraderCreateMissingPrompt(storeUserID, lang, session, a.buildTraderCreateConversationResources(storeUserID, session)), true
|
||||
}
|
||||
if !result.Ready && result.Question == "" {
|
||||
result.Ready = true
|
||||
}
|
||||
|
||||
if !result.Ready {
|
||||
session.Phase = "collecting"
|
||||
a.saveSkillSession(userID, session)
|
||||
return "", false
|
||||
}
|
||||
|
||||
if stillMissing := missingFieldKeysForSkillSession(session); len(stillMissing) > 0 {
|
||||
session.Phase = "collecting"
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"regexp"
|
||||
@@ -1459,12 +1458,6 @@ func (a *Agent) handleExchangeCreateSkill(storeUserID string, userID int64, lang
|
||||
}
|
||||
return "Cancelled the current exchange creation flow."
|
||||
}
|
||||
if result := a.extractSkillSessionFieldsWithLLM(context.Background(), userID, lang, text, session); result.Intent == "continue" {
|
||||
a.applyLLMExtractionToSkillSession(storeUserID, &session, result, lang, text)
|
||||
}
|
||||
if v := inferCreateDisplayName(text); fieldValue(session, "account_name") == "" && v != "" {
|
||||
setField(&session, "account_name", v)
|
||||
}
|
||||
exType := fieldValue(session, "exchange_type")
|
||||
accountName := fieldValue(session, "account_name")
|
||||
missing := make([]string, 0, 6)
|
||||
@@ -1578,18 +1571,7 @@ func (a *Agent) handleModelCreateSkill(storeUserID string, userID int64, lang, t
|
||||
}
|
||||
return "Cancelled the current model creation flow."
|
||||
}
|
||||
if result := a.extractSkillSessionFieldsWithLLM(context.Background(), userID, lang, text, session); result.Intent == "continue" {
|
||||
a.applyLLMExtractionToSkillSession(storeUserID, &session, result, lang, text)
|
||||
}
|
||||
if v := inferCreateDisplayName(text); fieldValue(session, "name") == "" && v != "" {
|
||||
setField(&session, "name", v)
|
||||
}
|
||||
provider := fieldValue(session, "provider")
|
||||
if provider != "" && fieldValue(session, "api_key") == "" {
|
||||
if credential := inferModelCredentialFromText(provider, text); credential != "" {
|
||||
setField(&session, "api_key", credential)
|
||||
}
|
||||
}
|
||||
if provider != "" {
|
||||
if fieldValue(session, "name") == "" {
|
||||
setField(&session, "name", defaultModelConfigName(provider))
|
||||
@@ -1726,9 +1708,6 @@ func (a *Agent) handleStrategyCreateSkill(storeUserID string, userID int64, lang
|
||||
}
|
||||
return "Cancelled the current strategy creation flow."
|
||||
}
|
||||
if result := a.extractSkillSessionFieldsWithLLM(context.Background(), userID, lang, text, session); result.Intent == "continue" {
|
||||
a.applyLLMExtractionToSkillSession(storeUserID, &session, result, lang, text)
|
||||
}
|
||||
name := fieldValue(session, "name")
|
||||
hasDescriptiveDraftIntent := session.Phase == "draft_create"
|
||||
if hasDescriptiveDraftIntent {
|
||||
@@ -1768,24 +1747,6 @@ func (a *Agent) handleSimpleEntitySkill(storeUserID string, userID int64, lang,
|
||||
if session.Name != skillName || session.Action != action {
|
||||
return "", false
|
||||
}
|
||||
if shouldUseLLMConversationForSimpleEntity(skillName, action) {
|
||||
result := a.llmSkillConversationDriver(context.Background(), storeUserID, userID, lang, text, session, a.buildSimpleEntityConversationResources(storeUserID, session, options))
|
||||
if result.Cancel {
|
||||
a.clearSkillSession(userID)
|
||||
if lang == "zh" {
|
||||
return "已取消当前流程。", true
|
||||
}
|
||||
return "Cancelled the current flow.", true
|
||||
}
|
||||
if result.UserRejectedFlow {
|
||||
return a.rerouteRejectedSkillFlow(context.Background(), storeUserID, userID, lang, text)
|
||||
}
|
||||
applySkillConversationResultToSession(&session, result)
|
||||
if !result.Ready && result.Question != "" {
|
||||
a.saveSkillSession(userID, session)
|
||||
return result.Question, true
|
||||
}
|
||||
}
|
||||
if supportsBulkTargetSelection(skillName, action) && textMeansAllTargets(text) {
|
||||
setField(&session, "bulk_scope", "all")
|
||||
session.TargetRef = nil
|
||||
@@ -1886,26 +1847,6 @@ func (a *Agent) handleSimpleEntitySkill(storeUserID string, userID int64, lang,
|
||||
}
|
||||
|
||||
func (a *Agent) askLLMAmbiguousTargetQuestion(storeUserID string, userID int64, lang, text string, session skillSession, skillName, action string, allOptions, ambiguous []traderSkillOption) string {
|
||||
if a.aiClient != nil {
|
||||
ambiguousSession := session
|
||||
ambiguousSession.Name = skillName
|
||||
ambiguousSession.Action = action
|
||||
ambiguousSession.TargetRef = nil
|
||||
setSkillDAGStep(&ambiguousSession, "resolve_target")
|
||||
|
||||
resources := a.buildSimpleEntityConversationResources(storeUserID, ambiguousSession, allOptions)
|
||||
if resources == nil {
|
||||
resources = map[string]any{}
|
||||
}
|
||||
resources["targets"] = ambiguous
|
||||
resources["target_conflict"] = ambiguous
|
||||
|
||||
result := a.llmSkillConversationDriver(context.Background(), storeUserID, userID, lang, text, ambiguousSession, resources)
|
||||
if question := strings.TrimSpace(result.Question); question != "" {
|
||||
a.saveSkillSession(userID, ambiguousSession)
|
||||
return question
|
||||
}
|
||||
}
|
||||
return formatAmbiguousTargetPrompt(lang, ambiguous)
|
||||
}
|
||||
|
||||
|
||||
@@ -214,7 +214,7 @@ func (a *Agent) handleWorkflowSession(ctx context.Context, storeUserID string, u
|
||||
}
|
||||
|
||||
if activeSkill := a.getSkillSession(userID); strings.TrimSpace(activeSkill.Name) != "" {
|
||||
decision, extraction := a.resolveSkillSessionTurn(ctx, userID, lang, text, activeSkill)
|
||||
decision, _ := a.resolveSkillSessionTurn(ctx, userID, lang, text, activeSkill)
|
||||
switch decision.Intent {
|
||||
case "cancel":
|
||||
a.clearSkillSession(userID)
|
||||
@@ -230,11 +230,6 @@ func (a *Agent) handleWorkflowSession(ctx context.Context, storeUserID string, u
|
||||
a.clearSkillSession(userID)
|
||||
a.clearWorkflowSession(userID)
|
||||
return "", false, nil
|
||||
case "continue_active":
|
||||
if extraction.Intent == "continue" {
|
||||
a.applyLLMExtractionToSkillSession(storeUserID, &activeSkill, extraction, lang, text)
|
||||
a.saveSkillSession(userID, activeSkill)
|
||||
}
|
||||
}
|
||||
answer, handled := a.executeAtomicSkillTask(storeUserID, userID, lang, text, activeSkill.Name, activeSkill.Action, onEvent)
|
||||
if !handled {
|
||||
|
||||
Reference in New Issue
Block a user