package engine // norm_whitespace_assistant.go -- 过滤只包含空白文本的 assistant 消息. // // 来源:新增步骤,早期方案 normalize 未单独处理. // 场景:"\n\n" 或纯空格的 assistant 消息会被 API 拒绝. // 必须在 thinking 剥离之后执行(Priority > orphan_thinking 的 18). // 跨场景通用:任何场景的 assistant 消息都可能因处理产生纯空白内容. import ( "strings" "git.flytoex.net/yuanwei/flyto-agent/pkg/query" ) // WhitespaceAssistantFilter 过滤只包含空白文本的 assistant 消息. // // 精妙之处(CLEVER): 只过滤 assistant 消息.user 消息即使只有空白也可能 // 是有效输入(用户真的发了一个回车),而 assistant 的纯空白一定是 bug. type WhitespaceAssistantFilter struct{} func (f *WhitespaceAssistantFilter) Name() string { return "whitespace_assistant" } func (f *WhitespaceAssistantFilter) Priority() int { return 22 } func (f *WhitespaceAssistantFilter) Normalize(messages []query.Message) []query.Message { if len(messages) == 0 { return messages } result := make([]query.Message, 0, len(messages)) for _, msg := range messages { if msg.Role == query.RoleAssistant && isWhitespaceOnly(msg) { // 跳过只包含空白文本的 assistant 消息 continue } result = append(result, msg) } return result } // isWhitespaceOnly 检查消息是否只包含空白文本块. // 如果消息包含任何非文本块,返回 false. // 如果消息没有内容块,返回 false(由 EmptyMessageFilter 处理). func isWhitespaceOnly(msg query.Message) bool { if len(msg.Content) == 0 { return false } for _, c := range msg.Content { switch c.Type { case query.ContentText: if strings.TrimSpace(c.Text) != "" { return false } default: // 有非文本块,不算纯空白 return false } } return true }