feat(companion): add personality, relationship, and mood engines

This commit is contained in:
2026-06-10 00:49:01 +03:30
parent 8d99c1856b
commit 147a51ecba
3 changed files with 307 additions and 0 deletions

View File

@@ -0,0 +1,121 @@
package companion
import (
"log/slog"
"sync"
"git.db123.ir/db123/divacode/internal/storage"
"git.db123.ir/db123/divacode/pkg/personality"
)
type RelationshipEngine struct {
mu sync.Mutex
db *storage.DB
}
func NewRelationshipEngine(db *storage.DB) *RelationshipEngine {
e := &RelationshipEngine{db: db}
e.seed()
return e
}
func (e *RelationshipEngine) seed() {
defaults := map[string]float64{
"familiarity": 0.0,
"trust": 0.3,
}
for metric, val := range defaults {
err := e.db.Exec(
"INSERT OR IGNORE INTO relationship_metrics (id, metric, value) VALUES (?, ?, ?)",
"rel_"+metric, metric, val,
)
if err != nil {
slog.Warn("seed metric failed", "metric", metric, "error", err)
}
}
}
func (e *RelationshipEngine) Current() *personality.RelationshipMetrics {
e.mu.Lock()
defer e.mu.Unlock()
rm := &personality.RelationshipMetrics{}
row := e.db.QueryRow("SELECT value FROM relationship_metrics WHERE metric = 'familiarity'")
row.Scan(&rm.Familiarity)
row = e.db.QueryRow("SELECT value FROM relationship_metrics WHERE metric = 'trust'")
row.Scan(&rm.Trust)
topics, _ := e.db.Query("SELECT topic FROM shared_topics ORDER BY count DESC LIMIT 20")
if topics != nil {
defer topics.Close()
for topics.Next() {
var t string
topics.Scan(&t)
rm.SharedTopics = append(rm.SharedTopics, t)
}
}
jokes, _ := e.db.Query("SELECT joke FROM inside_jokes LIMIT 20")
if jokes != nil {
defer jokes.Close()
for jokes.Next() {
var j string
jokes.Scan(&j)
rm.InsideJokes = append(rm.InsideJokes, j)
}
}
return rm
}
func (e *RelationshipEngine) Trust() float64 {
var v float64
err := e.db.QueryRow("SELECT value FROM relationship_metrics WHERE metric = 'trust'").Scan(&v)
if err != nil {
return 0.3
}
return v
}
func (e *RelationshipEngine) UpdateFamiliarity(delta float64) error {
return e.adjust("familiarity", delta)
}
func (e *RelationshipEngine) UpdateTrust(delta float64) error {
return e.adjust("trust", delta)
}
func (e *RelationshipEngine) AddSharedTopic(topic string) error {
return e.db.Exec(
`INSERT INTO shared_topics (id, topic, count, last_discussed)
VALUES (?, ?, 1, datetime('now'))
ON CONFLICT(topic) DO UPDATE SET count = count + 1, last_discussed = datetime('now')`,
"topic_"+topic, topic,
)
}
func (e *RelationshipEngine) adjust(metric string, delta float64) error {
e.mu.Lock()
defer e.mu.Unlock()
var current float64
row := e.db.QueryRow("SELECT value FROM relationship_metrics WHERE metric = ?", metric)
if err := row.Scan(&current); err != nil {
current = 0
}
newVal := current + delta
if newVal < 0 {
newVal = 0
}
if newVal > 1 {
newVal = 1
}
return e.db.Exec(
"UPDATE relationship_metrics SET value = ?, updated_at = datetime('now') WHERE metric = ?",
newVal, metric,
)
}