package main import ( "time" "github.com/kami/maven/internal/dialogue" "github.com/kami/maven/internal/router" ) // voiceDialogueID — the single dialogue-session key. This is a single-user box // (ponytail), so one slot suffices; a second speaker would need per-speaker ids, // which waits on voice-print attribution (see PROGRESS multi-user deferral). const voiceDialogueID = "voice" // toDialogueSlots projects the router's slots onto the dialogue layer's subset // (everything except the fact Value, which the dialogue layer doesn't carry). func toDialogueSlots(s router.Slots) dialogue.Slots { return dialogue.Slots{ Time: s.Time, HasTime: s.HasTime, Key: s.Key, HasKey: s.HasKey, Text: s.Text, Fn: s.Fn, Args: s.Args, HasFn: s.HasFn, } } // applyDialogueSlots writes inherited dialogue slots back onto router slots, // preserving router-only fields (Value) the dialogue layer never touched. func applyDialogueSlots(base router.Slots, d dialogue.Slots) router.Slots { base.Time, base.HasTime = d.Time, d.HasTime base.Key, base.HasKey = d.Key, d.HasKey base.Text = d.Text base.Fn, base.Args, base.HasFn = d.Fn, d.Args, d.HasFn return base } // followUpMerge fills the current turn's missing slots from a prior same-intent, // non-expired session — the multi-turn seam. A different intent is a fresh // command, not a follow-up, so it's returned untouched; a clarify turn resolved // nothing, so it never inherits. InheritSlots only fills gaps, so a fully-slotted // current turn is unaffected. func followUpMerge(prev *dialogue.Session, dec router.Decision, now time.Time) router.Decision { if prev == nil || dec.Clarify || prev.IsExpired(now) { return dec } if prev.Intent != dialogue.Intent(dec.Intent) { return dec } merged := dialogue.InheritSlots(prev.Slots, toDialogueSlots(dec.Slots)) dec.Slots = applyDialogueSlots(dec.Slots, merged) return dec }