fe489dff6d
attentionq.go, repair.go and internal/router/complaint.go carry the last
hand-written Russian patterns of the V-522 sweep, and they live on task/467.
internal/lexicon, internal/morph and cmd/mavend/topics.go live here. One of
the two had to move.
Four conflicts, and one of them is a real collision rather than a mechanical
one. Both branches wrote the narrative stage 0 rule. This side had
NarrativeQueryGrammars, plural, with the rest-of-day rule beside it and the
verb alternation built from the lexicon; task/467 had NarrativeQueryGrammar,
singular, which extracts the topic into Slots.Text, refuses a bare "расскажи",
and excludes the shapes that are chat ("расскажи о себе", "историю на ночь").
Resolved by keeping this side's container and this side's lexicon-built
pattern, and taking every behaviour only the other side had: the topic slot,
the empty-topic refusal, chatNarrativeTopics, and its wiring position after
TaskCaptureGrammar so "запиши" still beats "расскажи".
The rest: queryFeeds keeps task/467's conditional claim (V-474 supersedes the
unconditional one), rank.go keeps Spoken and drops pluralTasksRU because
say.CountWord is the one copy of Russian count agreement, and vendor/ was
re-vendored — the merged modules.txt claimed replaces for nexus and praxis
that neither go.mod has.
Routing fixture 58/82, unchanged from both sides.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
38 lines
1.2 KiB
Go
38 lines
1.2 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"log"
|
|
|
|
"github.com/kami/maven/internal/phraser"
|
|
"github.com/kami/maven/internal/router"
|
|
)
|
|
|
|
// actionReminder handles router.IntentReminder: parse the time when stage-0
|
|
// skipped the extractor, then create the reminder.
|
|
func (h *reactiveHandler) actionReminder(ctx context.Context, dec router.Decision) string {
|
|
if !dec.Slots.HasTime {
|
|
// Stage-0 (reminder-wakeword grammar) skips the extractor, so the
|
|
// time wasn't parsed. Run the parser as a fallback.
|
|
if dec.Stage == 0 && h.timeParser != nil {
|
|
t, ok, err := h.timeParser.Parse(ctx, dec.Utterance, h.now())
|
|
if err == nil && ok {
|
|
dec.Slots.Time = t
|
|
dec.Slots.HasTime = true
|
|
}
|
|
}
|
|
if !dec.Slots.HasTime {
|
|
return phraser.Ack(phraser.FailReminderTime, nil)
|
|
}
|
|
}
|
|
// The body is what she says at the hour, so the marker and the time come
|
|
// out of it: the fire time is already a column, and "напомни" is an
|
|
// instruction that has been carried out (Vikunja #469).
|
|
payload := `{"text":` + jsonString(reminderBody(dec.Utterance, dec.Slots.Text)) + `}`
|
|
if _, err := h.api.CreateReminder(ctx, dec.Slots.Time, payload, ""); err != nil {
|
|
log.Printf("voice: create reminder: %v", err)
|
|
return phraser.Ack(phraser.FailReminder, nil)
|
|
}
|
|
return ""
|
|
}
|