package main import ( "time" "github.com/kami/maven/internal/dialogue" "github.com/kami/maven/internal/router" ) // clarifyTTL — how long a parked question stays answerable. Same 90s as the // confirm gate, for the same reason: an answer is a same-breath gesture, and a // stale question must not eat an unrelated later utterance. const clarifyTTL = 90 * time.Second // wantedSlots — what each intent needs before she can act on it. First entry is // the one she asks about; the rest are only used to decide act-vs-drop. // // Intents not listed here are never worth a question: note and query act on the // raw utterance, chat and system have nothing to fill in. For those a clarify // decision keeps the canned "не поняла" reply — inventing a question for noise // is worse than admitting she missed it. var wantedSlots = map[router.Intent][]dialogue.Slot{ router.IntentReminder: {dialogue.SlotTime}, router.IntentFact: {dialogue.SlotKey}, router.IntentAct: {dialogue.SlotFn}, } // clarifyQuestions — one short question per missing slot. // // These are fixed templates, not model output. The resident model is a 0.8B; it // would wander, and a question whose wording changes every time is harder to // answer than a blunt one that always reads the same. They are infinitive // questions, so there is no gender agreement to get wrong; the feminine // self-reference lives in the reply she gives when she drops the request. var clarifyQuestions = map[dialogue.Slot]string{ dialogue.SlotTime: "На когда напомнить?", dialogue.SlotKey: "Что записать?", dialogue.SlotFn: "Что сделать?", } // clarifyDropped — she asked once, the answer still did not fill the gap, so // the request is gone. Said plainly, once, with no second question. const clarifyDropped = "Не разобрала — скажи целиком, пожалуйста." // missingFor returns the slots a decision still needs, most important first. // Empty ⇒ there is nothing identifiable to ask about. func missingFor(dec router.Decision) []dialogue.Slot { return dialogue.StillMissing(wantedSlots[dec.Intent], toDialogueSlots(dec.Slots)) } // clarifyQuestion picks the one question to ask for a clarify decision. Returns // ("", false) when she has no idea what is missing. // // One question about one thing: if two slots are missing she asks about the // first and lets the rest go. Two questions in a row is an interrogation. func clarifyQuestion(dec router.Decision) (dialogue.Slot, string, bool) { missing := missingFor(dec) if len(missing) == 0 { return "", "", false } q, ok := clarifyQuestions[missing[0]] if !ok { return "", "", false } return missing[0], q, true }