mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-11 12:18:59 +00:00
* fix(memory): surface passive channel episodic recall * fix(memory): expose episodic key topics --------- Co-authored-by: Collective Developer <man@collective.dev>
98 lines
2.5 KiB
Go
98 lines
2.5 KiB
Go
package channelmemory
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"slices"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/nextlevelbuilder/goclaw/internal/store"
|
|
)
|
|
|
|
func (s *Service) itemFromExtracted(run *store.ChannelMemoryExtractionRun, extracted ExtractedItem) *store.ChannelMemoryExtractionItem {
|
|
topics, _ := json.Marshal(extracted.Topics)
|
|
entities, _ := json.Marshal(extracted.Entities)
|
|
hash := sha256.Sum256([]byte(strings.Join([]string{run.ChannelInstanceID.String(), run.HistoryKey, extracted.Type, extracted.Summary}, "\x00")))
|
|
itemID := hex.EncodeToString(hash[:])
|
|
return &store.ChannelMemoryExtractionItem{
|
|
RunID: run.ID,
|
|
ChannelInstanceID: run.ChannelInstanceID,
|
|
AgentID: run.AgentID,
|
|
UserID: run.UserID,
|
|
ItemHash: itemID,
|
|
ItemType: extracted.Type,
|
|
Summary: extracted.Summary,
|
|
Topics: topics,
|
|
Entities: entities,
|
|
Confidence: extracted.Confidence,
|
|
SourceID: "channel:" + itemID,
|
|
}
|
|
}
|
|
|
|
func eligibleHistoryKey(key string, cfg Config) bool {
|
|
if slices.Contains(cfg.ExcludeHistoryKeys, key) {
|
|
return false
|
|
}
|
|
if !cfg.GroupOnly {
|
|
return key != ""
|
|
}
|
|
k := strings.ToLower(key)
|
|
return key != "" && !strings.Contains(k, "dm") && !strings.Contains(k, "private")
|
|
}
|
|
|
|
func eligibleHistoryGroup(group store.PendingMessageGroup, cfg Config) bool {
|
|
if group.ParentHistoryKey != "" && slices.Contains(cfg.ExcludeHistoryKeys, group.ParentHistoryKey) {
|
|
return false
|
|
}
|
|
return eligibleHistoryKey(group.HistoryKey, cfg)
|
|
}
|
|
|
|
func messageSourceID(msg store.PendingMessage) string {
|
|
if msg.PlatformMsgID != "" {
|
|
return msg.PlatformMsgID
|
|
}
|
|
return msg.ID.String()
|
|
}
|
|
|
|
func decodeStrings(raw json.RawMessage) []string {
|
|
var out []string
|
|
_ = json.Unmarshal(raw, &out)
|
|
return out
|
|
}
|
|
|
|
func memoryKeyTopics(item *store.ChannelMemoryExtractionItem) []string {
|
|
if item == nil {
|
|
return nil
|
|
}
|
|
return mergeTopicLabels(decodeStrings(item.Topics), decodeStrings(item.Entities))
|
|
}
|
|
|
|
func mergeTopicLabels(groups ...[]string) []string {
|
|
seen := make(map[string]struct{})
|
|
var out []string
|
|
for _, group := range groups {
|
|
for _, value := range group {
|
|
label := strings.TrimSpace(value)
|
|
if label == "" {
|
|
continue
|
|
}
|
|
key := strings.ToLower(label)
|
|
if _, ok := seen[key]; ok {
|
|
continue
|
|
}
|
|
seen[key] = struct{}{}
|
|
out = append(out, label)
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|
|
//go:fix inline
|
|
func timePtr(t time.Time) *time.Time { return &t }
|
|
|
|
func contains(values []string, v string) bool {
|
|
return slices.Contains(values, v)
|
|
}
|