Decode the people list from each project's /capabilities and set the /ask person field from a whole-word, case-insensitive name in the question when the caller did not name a person. Match only the routed project's people, so a name from another project does not leak across. Fall back to asker when no name matches. Co-Authored-By: Paperclip <noreply@paperclip.ing>
38 lines
1.1 KiB
Go
38 lines
1.1 KiB
Go
package understand
|
|
|
|
import (
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
// MatchPerson returns the household name from people that appears as a whole
|
|
// word in the question, or "" when no name matches.
|
|
//
|
|
// It is deterministic: no LLM is in this path (AGENTS.md rule 4). The Hub uses
|
|
// it to set the /ask person field from the question when the caller did not
|
|
// name a person. A caller-supplied person always wins; the caller does not call
|
|
// this function in that case.
|
|
//
|
|
// The match is case-insensitive and whole-word, so "harry" matches "What does
|
|
// Harry have on today?" but not "harrypotter". The matched name is returned as
|
|
// the project published it, trimmed.
|
|
func MatchPerson(question string, people []string) string {
|
|
if strings.TrimSpace(question) == "" || len(people) == 0 {
|
|
return ""
|
|
}
|
|
q := strings.ToLower(question)
|
|
for _, p := range people {
|
|
name := strings.TrimSpace(p)
|
|
if name == "" {
|
|
continue
|
|
}
|
|
// \b is a word boundary in Go's RE2. QuoteMeta keeps a name that
|
|
// holds a regexp character literal.
|
|
re := regexp.MustCompile(`\b` + regexp.QuoteMeta(strings.ToLower(name)) + `\b`)
|
|
if re.MatchString(q) {
|
|
return name
|
|
}
|
|
}
|
|
return ""
|
|
}
|