package router import ( "github.com/kami/maven/internal/lexicon" "github.com/kami/maven/internal/morph" ) // HelpTopic is a Maven-owned operation the user is asking how to perform. type HelpTopic string const ( HelpUnknown HelpTopic = "" HelpReminderCancel HelpTopic = "reminder_cancel" HelpTaskDrop HelpTopic = "task_drop" ) // MavenHelpGrammar keeps questions about using Maven's own mutation surfaces // local (Vikunja V-720). A safe parser declining the mutation is only half the job: sending // "как отменить напоминание" to web search still answers about somebody else's // product. The operation verb and Maven-owned object together anchor SourceSelf. func MavenHelpGrammar() Grammar { return Grammar{Name: "maven-help", Decide: mavenHelpDecision} } func mavenHelpDecision(utterance string) (Decision, bool) { if LocalHelpTopic(utterance) == HelpUnknown { return Decision{}, false } return Decision{ Stage: 0, Intent: IntentQuery, Confidence: 1, Source: SourceSelf, }, true } // LocalHelpTopic parses the two currently supported cancellation surfaces. It // is intentionally object-bound: "как убрать царапину" is world advice, while // the same verb applied to a task or reminder asks how to use Maven. func LocalHelpTopic(utterance string) HelpTopic { tokens := commandFrameTokens(utterance) modal := localHelpModal(tokens) if (!IsQuestionShaped(utterance) && !modal) || CarriesCaptureVerb(utterance) { return HelpUnknown } hasHow := hasTok(tokens, "как") || hasTok(tokens, "how") || modal if !hasHow { return HelpUnknown } hasDropVerb := false for _, token := range tokens { if sameAsAny(token, lexicon.ReminderCancelReportVerbs()) || sameAsAny(token, lexicon.TaskDropWords()) { hasDropVerb = true break } } if !hasDropVerb { return HelpUnknown } hasReminder, hasTask := false, false for _, token := range tokens { if sameAsAny(token, lexicon.ReminderNouns()) { hasReminder = true } if morph.SameWord(token, "задача") || token == "task" || token == "tasks" { hasTask = true } } if hasReminder == hasTask { return HelpUnknown } if hasReminder { return HelpReminderCancel } return HelpTaskDrop } // localHelpModal recognises permission/ability questions about the caller's own // use of Maven. "can/could I" is help; "can you" is an action request and must // continue to the command cascade. Russian impersonal "можно (ли)" carries the // same product-help meaning. Exact leading tokens keep a modal inside a report // or task title from stealing the turn. func localHelpModal(tokens []string) bool { for len(tokens) > 0 && commandLead(tokens[0]) { tokens = tokens[1:] } if len(tokens) >= 2 && tokens[0] == "можно" { return true } return len(tokens) >= 3 && (tokens[0] == "can" || tokens[0] == "could") && tokens[1] == "i" }