fix(intent): accept 编写/编制/起草 and keep intake markers on intake

The chat fallback only treated 生成/做/跑/出 as task verbs, and the shorter RDev alias 用户需求 stole 初始用户需求表.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
weichen
2026-09-21 06:12:15 +00:00
co-authored by Cursor
parent ddb1e542b6
commit a236ddc0fa
2 changed files with 41 additions and 9 deletions
+33 -9
View File
@@ -1177,6 +1177,15 @@ func matchQueryProgress(input string) *CandidateIntent {
return nil
}
func hasTaskWriteVerb(input string) bool {
for _, verb := range []string{"生成", "做", "跑", "出", "编写", "编制", "起草"} {
if strings.Contains(input, verb) {
return true
}
}
return false
}
func matchTriggerTask(input string) *CandidateIntent {
type phrase struct {
text string
@@ -1210,24 +1219,39 @@ func matchTriggerTask(input string) *CandidateIntent {
return phrases[i].text < phrases[j].text
})
if !(strings.Contains(input, "生成") || strings.Contains(input, "做") || strings.Contains(input, "跑") || strings.Contains(input, "出")) {
if !hasTaskWriteVerb(input) {
return nil
}
// 「初始 / 首轮 / 摸底」是 V0.1 摸底,不能被更短的研发别名「用户需求」截走。
if hasIntakeSemanticMarker(input) && strings.Contains(input, "需求") {
return triggerTaskCandidate("需求表", "intake")
}
for _, item := range phrases {
if strings.Contains(input, item.text) {
return &CandidateIntent{
Intent: IntentTriggerTask,
Confidence: 0.86,
FilledSlots: map[string]string{
SlotTargetTask: item.key,
},
Reasoning: fmt.Sprintf("用户要求显式生成交付任务: %s (%s)", item.text, item.key),
}
return triggerTaskCandidate(item.text, item.key)
}
}
return nil
}
func hasIntakeSemanticMarker(input string) bool {
return strings.Contains(input, "首轮") ||
strings.Contains(input, "初始") ||
strings.Contains(input, "需求摸底") ||
strings.Contains(input, "摸底")
}
func triggerTaskCandidate(phrase, taskKey string) *CandidateIntent {
return &CandidateIntent{
Intent: IntentTriggerTask,
Confidence: 0.86,
FilledSlots: map[string]string{
SlotTargetTask: taskKey,
},
Reasoning: fmt.Sprintf("用户要求显式生成交付任务: %s (%s)", phrase, taskKey),
}
}
func isGreetingOrHelp(input string) bool {
greetings := []string{"你好", "您好", "早上好", "下午好", "晚上好", "早啊", "在吗", "hi", "hello", "你是谁"}
for _, g := range greetings {
+8
View File
@@ -126,6 +126,14 @@ func TestIntentRecognition_RDevProposalAndLongerTitleWins(t *testing.T) {
if intake.TopIntent.FilledSlots[intent.SlotTargetTask] != "intake" {
t.Fatalf("用户需求收集表 must stay intake, got %s", intake.TopIntent.FilledSlots[intent.SlotTargetTask])
}
written, err := rec.Recognize(context.Background(), "编写初始用户需求表", ctx)
if err != nil {
t.Fatal(err)
}
if written.TopIntent.Intent != intent.IntentTriggerTask || written.TopIntent.FilledSlots[intent.SlotTargetTask] != "intake" {
t.Fatalf("编写初始用户需求表 want TRIGGER_TASK/intake, got %s %s", written.TopIntent.Intent, written.TopIntent.FilledSlots[intent.SlotTargetTask])
}
}
func TestIntentRecognition_CasualChat(t *testing.T) {