package router import ( _ "embed" "encoding/json" "fmt" "sort" ) // The task vocabulary lives in task_phrases.json, not in Go source. See the // comment block inside that file for what each list means and why the entries // that are NOT in it were left out. // // go:embed, so the single-binary deploy is unchanged: the JSON is compiled into // mavend and there is nothing to install beside it. Parsed once at init; a // malformed asset panics at startup rather than silently disabling task capture, // which would look like the feature quietly not working. //go:embed task_phrases.json var taskPhrasesJSON []byte type urgencyMarker struct { Word string `json:"word"` Weight int `json:"weight"` } type taskPhrases struct { CapturePrefixes []string `json:"capture_prefixes"` UrgencyMarkers []urgencyMarker `json:"urgency_markers"` ListNouns []string `json:"list_nouns"` ListShortcutNouns []string `json:"list_shortcut_nouns"` } var ( taskCapturePrefixes []string urgencyMarkers []urgencyMarker taskListWords []string taskListWordsShortcut []string ) func init() { var v taskPhrases if err := json.Unmarshal(taskPhrasesJSON, &v); err != nil { panic(fmt.Sprintf("router: task_phrases.json: %v", err)) } if len(v.CapturePrefixes) == 0 || len(v.ListNouns) == 0 { panic("router: task_phrases.json: capture_prefixes and list_nouns must be non-empty") } // Strongest urgency first, so stripUrgency finds "срочно" before "важно" // in an utterance carrying both. The file is written in that order already; // sorting here means a careless edit cannot silently downgrade a task. sort.SliceStable(v.UrgencyMarkers, func(i, j int) bool { return v.UrgencyMarkers[i].Weight > v.UrgencyMarkers[j].Weight }) taskCapturePrefixes = v.CapturePrefixes urgencyMarkers = v.UrgencyMarkers taskListWords = v.ListNouns taskListWordsShortcut = v.ListShortcutNouns }