package intent import ( "strings" "golang.org/x/text/unicode/norm" ) // foldMatchText 做识别用折叠。nfkc 只做兼容等价(全角 ASCII、组合字符), // 不做繁简转换。caseSensitive 为真时保留大小写。 func foldMatchText(s string, nfkc, caseSensitive bool) string { if nfkc { s = norm.NFKC.String(s) } if !caseSensitive { s = strings.ToLower(s) } return s } // foldInput 返回用于匹配的文本:第一段保留大小写(可选 NFKC),第二段是其小写。 func (s *Snapshot) foldInput(input string) (matchInput, folded string) { if s == nil { return input, strings.ToLower(input) } matchInput = foldMatchText(input, s.nfkc, true) return matchInput, strings.ToLower(matchInput) } func cloneStrings(in []string) []string { if in == nil { return nil } return append([]string(nil), in...) } func cloneIntentSpec(in IntentSpec) IntentSpec { out := in out.Matcher.IncludesAny = cloneStrings(in.Matcher.IncludesAny) out.Matcher.IncludesAll = cloneStrings(in.Matcher.IncludesAll) out.Matcher.ExcludesAny = cloneStrings(in.Matcher.ExcludesAny) out.Matcher.Patterns = cloneStrings(in.Matcher.Patterns) if in.Slots != nil { out.Slots = append([]SlotSpec(nil), in.Slots...) for i := range out.Slots { out.Slots[i].Enum = cloneStrings(in.Slots[i].Enum) out.Slots[i].Normalize = cloneStrings(in.Slots[i].Normalize) } } if in.Metadata != nil { out.Metadata = make(map[string]string, len(in.Metadata)) for k, v := range in.Metadata { out.Metadata[k] = v } } return out } // catalogMetadataAllow 是目录与 Markdown 允许带出的 metadata 键。 // handler 仍留在 CatalogSpec 供执行器按名分派,但不写入 Markdown。 var catalogMetadataAllow = map[string]bool{ "blueprint": true, "guidance": true, } func catalogMetadata(in map[string]string) map[string]string { if len(in) == 0 { return nil } out := map[string]string{} for k, v := range in { if catalogMetadataAllow[k] { out[k] = v } } if len(out) == 0 { return nil } return out }