56 lines
1.9 KiB
Go
56 lines
1.9 KiB
Go
package router
|
|
|
|
import (
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
// Grammar — one stage-0 exact-match pattern. Wake-word + known command grammar
|
|
// hits the allowlist directly, skips the classifier (lowest latency — the vosk
|
|
// command path). Boring high-frequency acts for free.
|
|
//
|
|
// A Grammar returns a fully-formed Decision (intent + slots) at confidence 1.0
|
|
// when its pattern matches AND its Build returns ok=true; the router stops the
|
|
// cascade. Grammar rules are code, not config — same boundary as rules-as-code
|
|
// in the loop. The tool registry populates the verb set at daemon wiring time.
|
|
type Grammar struct {
|
|
Name string
|
|
Pattern *regexp.Regexp // matched against the raw utterance
|
|
Build func(match []string) (Decision, bool)
|
|
}
|
|
|
|
// wakeWordAct — "maven, restart nginx" / "maven restart nginx" → the remainder
|
|
// is matched against the act allowlist. A non-match returns ok=false so the
|
|
// cascade falls through to the classifier (a wakeword prefix alone doesn't
|
|
// guarantee a known command — "maven, i'm tired" is a fact, not an act).
|
|
var wakeWordAct = regexp.MustCompile(`(?i)^\s*maven[,: ]+(.+)$`)
|
|
|
|
// DefaultGrammars — the wake-word act fast path. The ActMatcher is the same
|
|
// allowlist stage-2 act extraction uses (single source of truth for the fn
|
|
// list). Returns nil grammars if no matcher is wired (the daemon always wires
|
|
// one — the guard is for tests that only exercise the classifier).
|
|
func DefaultGrammars(actMatcher ActMatcher) []Grammar {
|
|
if actMatcher == nil {
|
|
return nil
|
|
}
|
|
return []Grammar{
|
|
{
|
|
Name: "wakeword-act",
|
|
Pattern: wakeWordAct,
|
|
Build: func(m []string) (Decision, bool) {
|
|
rest := strings.TrimSpace(m[1])
|
|
fn, args, ok := actMatcher.Match(rest)
|
|
if !ok {
|
|
return Decision{}, false // fall through to classifier
|
|
}
|
|
return Decision{
|
|
Stage: 0,
|
|
Intent: IntentAct,
|
|
Confidence: 1.0,
|
|
Slots: Slots{Fn: fn, Args: args, HasFn: true, Text: rest},
|
|
}, true
|
|
},
|
|
},
|
|
}
|
|
}
|