package engine // norm_tool_input.go -- 规范化 assistant 消息中 tool_use 块的输入. // // 来源:新增步骤,早期方案 normalize 未处理. // 场景: // - 剥离非标准字段(如 plan, caller 等内部字段) // - 工具名规范化(别名 -> 规范名) // // 跨场景通用:仓储工具可能有别名(scan_barcode -> barcode_scanner), // 法律工具可能有内部审计字段需要剥离. import ( "git.flytoex.net/yuanwei/flyto-agent/pkg/query" ) // DefaultInternalInputFields 默认需要剥离的内部字段名. // 这些字段是 engine 内部使用的,不应发送给 API. var DefaultInternalInputFields = []string{ "plan", "caller", "_internal", "_debug", } // ToolUseInputNormalizer 规范化 tool_use 块的输入. type ToolUseInputNormalizer struct { // InternalFields 需要从 tool_use input 中剥离的字段名. // 如果为 nil,使用 DefaultInternalInputFields. InternalFields []string // Aliases 工具名别名映射(别名 -> 规范名). // 如果为 nil,不做工具名替换. Aliases map[string]string } func (n *ToolUseInputNormalizer) Name() string { return "tool_input" } func (n *ToolUseInputNormalizer) Priority() int { return 25 } func (n *ToolUseInputNormalizer) internalFields() []string { if n.InternalFields != nil { return n.InternalFields } return DefaultInternalInputFields } func (n *ToolUseInputNormalizer) Normalize(messages []query.Message) []query.Message { if len(messages) == 0 { return messages } fields := n.internalFields() result := make([]query.Message, 0, len(messages)) for _, msg := range messages { if msg.Role != query.RoleAssistant { result = append(result, msg) continue } modified := false newContent := make([]query.Content, len(msg.Content)) copy(newContent, msg.Content) for i, c := range newContent { if c.Type != query.ContentToolUse { continue } // 工具名别名替换 if n.Aliases != nil { if canonical, ok := n.Aliases[c.Name]; ok { newContent[i].Name = canonical modified = true } } // 剥离内部字段 if len(c.Input) > 0 && len(fields) > 0 { cleaned := make(map[string]any, len(c.Input)) for k, v := range c.Input { cleaned[k] = v } for _, f := range fields { if _, exists := cleaned[f]; exists { delete(cleaned, f) modified = true } } if modified { newContent[i].Input = cleaned } } } if modified { result = append(result, query.Message{ Role: msg.Role, Content: newContent, Time: msg.Time, Metadata: msg.Metadata, }) } else { result = append(result, msg) } } return result }