router: add MatchText to NormalizedInput and NormalizeMatchText function (slice 9a)

Add MatchText field to NormalizedInput — a lossy lexical matching view
derived from ingress text: TrimSpace → NFKC → lowercase → collapse
Unicode whitespace. Does NOT fold ё→е, strip punctuation, strip wake
words, rewrite numbers, or invoke morphology.

Both ingress sites (voice + text) construct MatchText at entry. No
existing consumer reads MatchText yet — it is dark data for future
opt-in migration.

Vikunja: #725
This commit is contained in:
2026-09-06 22:32:51 +04:00
parent 0a2e194e76
commit 431e052e6f
3 changed files with 41 additions and 7 deletions
+2 -2
View File
@@ -211,7 +211,7 @@ func (h *reactiveHandler) HandlePushToTalk(ctx context.Context, req voice.PushTo
// 2-5. the shared turn pipeline (confirm → clarify → route → dialogue →
// action → replier), identical to the text path.
replyText := h.runTurn(ctx, router.NormalizedInput{Text: text, Source: sourceVoice})
replyText := h.runTurn(ctx, router.NormalizedInput{Text: text, MatchText: router.NormalizeMatchText(text), Source: sourceVoice})
// 6. tts — synthesise the reply text; return to the voice server which
// ships it back on the conn.
@@ -244,7 +244,7 @@ func (h *reactiveHandler) upgradeAPI(api ipc.CoreAPI) {
// HandlePushToTalk so text channels share the same routing logic.
func (h *reactiveHandler) handleText(ctx context.Context, conversation, text string) string {
log.Printf("voice: handleText: %q", text)
return h.runTurn(withDialogueID(ctx, dialogueIDFor(sourceText, conversation)), router.NormalizedInput{Text: text, Source: sourceText})
return h.runTurn(withDialogueID(ctx, dialogueIDFor(sourceText, conversation)), router.NormalizedInput{Text: text, MatchText: router.NormalizeMatchText(text), Source: sourceText})
}
// turnSource is a local alias for router.InputSource, kept so the daemon code