maven: dialogue state scaffold (task 6)
- New internal/dialogue/ package: Session, SessionStore, InheritSlots - Session with Intent, Slots, Timestamp, TTL - SessionStore: in-memory map with TTL expiry, thread-safe - InheritSlots: carries forward slots from previous turn - Tests: expiry, store put/get/expiry, default TTL, slot inheritance Co-Authored-By: opencode <opencode@anthropic.com>
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
package dialogue
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Intent string
|
||||
|
||||
const (
|
||||
IntentAct Intent = "act"
|
||||
IntentReminder Intent = "reminder"
|
||||
IntentFact Intent = "fact"
|
||||
IntentNote Intent = "note"
|
||||
IntentQuery Intent = "query"
|
||||
IntentSystem Intent = "system"
|
||||
)
|
||||
|
||||
type Slots struct {
|
||||
Time time.Time
|
||||
HasTime bool
|
||||
Key string
|
||||
HasKey bool
|
||||
Text string
|
||||
Fn string
|
||||
Args []string
|
||||
HasFn bool
|
||||
}
|
||||
|
||||
type Session struct {
|
||||
Intent Intent
|
||||
Slots Slots
|
||||
Timestamp time.Time
|
||||
TTL time.Duration
|
||||
}
|
||||
|
||||
func (s *Session) IsExpired(now time.Time) bool {
|
||||
return now.After(s.Timestamp.Add(s.TTL))
|
||||
}
|
||||
|
||||
type SessionStore struct {
|
||||
mu sync.RWMutex
|
||||
sessions map[string]*Session
|
||||
defaultTTL time.Duration
|
||||
}
|
||||
|
||||
func NewSessionStore(defaultTTL time.Duration) *SessionStore {
|
||||
if defaultTTL <= 0 {
|
||||
defaultTTL = 2 * time.Minute
|
||||
}
|
||||
return &SessionStore{
|
||||
sessions: make(map[string]*Session),
|
||||
defaultTTL: defaultTTL,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SessionStore) Get(id string, now time.Time) *Session {
|
||||
s.mu.RLock()
|
||||
sess, ok := s.sessions[id]
|
||||
s.mu.RUnlock()
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
if sess.IsExpired(now) {
|
||||
s.Delete(id)
|
||||
return nil
|
||||
}
|
||||
return sess
|
||||
}
|
||||
|
||||
func (s *SessionStore) Put(id string, sess *Session) {
|
||||
if sess.TTL <= 0 {
|
||||
sess.TTL = s.defaultTTL
|
||||
}
|
||||
s.mu.Lock()
|
||||
s.sessions[id] = sess
|
||||
s.mu.Unlock()
|
||||
}
|
||||
|
||||
func (s *SessionStore) Delete(id string) {
|
||||
s.mu.Lock()
|
||||
delete(s.sessions, id)
|
||||
s.mu.Unlock()
|
||||
}
|
||||
|
||||
func InheritSlots(prev, cur Slots) Slots {
|
||||
out := cur
|
||||
if !out.HasTime && prev.HasTime {
|
||||
out.Time = prev.Time
|
||||
out.HasTime = true
|
||||
}
|
||||
if !out.HasKey && prev.HasKey {
|
||||
out.Key = prev.Key
|
||||
out.HasKey = true
|
||||
}
|
||||
if out.Text == "" && prev.Text != "" {
|
||||
out.Text = prev.Text
|
||||
}
|
||||
if !out.HasFn && prev.HasFn {
|
||||
out.Fn = prev.Fn
|
||||
out.HasFn = true
|
||||
}
|
||||
if len(out.Args) == 0 && len(prev.Args) > 0 {
|
||||
out.Args = append([]string(nil), prev.Args...)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user