package intent import ( "context" "testing" "chat-agent-system/internal/maturity" ) func TestBuildIntentFrameV2_FromCandidate(t *testing.T) { res := &IntentRecognitionResult{ RawInput: "先帮我出一版初步报价单看看", Branch: BranchNewIntentPreempt, TopIntent: &CandidateIntent{ Intent: IntentTriggerTask, Confidence: 0.92, FilledSlots: map[string]string{ SlotTargetTask: "cdo_quote", }, Reasoning: "触发交付任务", }, Candidates: []CandidateIntent{ {Intent: IntentTriggerTask, Confidence: 0.92}, {Intent: IntentCasualChat, Confidence: 0.20}, }, } enrichShadowFields(res) frame := BuildIntentFrameV2(res, DefaultRegistry()) if frame == nil { t.Fatal("expected frame") } if frame.Version != IntentFrameV2Version { t.Errorf("version: want %s got %s", IntentFrameV2Version, frame.Version) } if frame.ActionKey != "task.run" { t.Errorf("action_key: want task.run got %s", frame.ActionKey) } if frame.LegacyIntent != IntentTriggerTask { t.Errorf("legacy_intent: want TRIGGER_TASK got %s", frame.LegacyIntent) } if frame.Goal != GoalGenerate { t.Errorf("goal: want generate got %s", frame.Goal) } if LegacyIntentFromFrame(frame) != IntentTriggerTask { t.Errorf("LegacyIntentFromFrame round-trip failed") } } func TestRecognize_DualWriteIntentFrameV2(t *testing.T) { rec := NewRecognizer() ctx := &ContextSnapshot{CurrentStage: string(maturity.StageV01_Triage)} res, err := rec.Recognize(context.Background(), "现在这个便携超声立项评估到哪一步了?", ctx) if err != nil { t.Fatalf("recognize: %v", err) } if res.IntentFrameV2 == nil { t.Fatal("expected intent_frame_v2 dual-write") } if res.IntentFrameV2.LegacyIntent != res.TopIntent.Intent { t.Errorf("v2 legacy %s != top %s", res.IntentFrameV2.LegacyIntent, res.TopIntent.Intent) } if res.IntentFrameV2.ActionKey == "" { t.Error("expected action_key on v2 frame") } if res.RankedFrames == nil || len(res.RankedFrames.Candidates) == 0 { t.Error("expected ranked_frames candidates") } } func TestBuildIntentFrameV2_ExpectationHitRelation(t *testing.T) { res := &IntentRecognitionResult{ RawInput: "好", Branch: BranchExpectationHit, TopIntent: &CandidateIntent{ Intent: IntentAdvanceStage, Confidence: 1.0, FilledSlots: map[string]string{ SlotTargetStage: string(maturity.StageV05_Feasibility), }, }, } frame := BuildIntentFrameV2(res, DefaultRegistry()) if frame.Relation != RelationExpectationHit { t.Errorf("relation: want expectation_hit got %s", frame.Relation) } }