86 lines
2.8 KiB
Go
86 lines
2.8 KiB
Go
package vikingmemory
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"crypto/sha256"
|
||
|
|
"data-terminal-cloud/internal/callmemory"
|
||
|
|
"encoding/hex"
|
||
|
|
"encoding/json"
|
||
|
|
"errors"
|
||
|
|
"strings"
|
||
|
|
)
|
||
|
|
|
||
|
|
// ChatMemories returns untruncated native-chat records and checks scope again on
|
||
|
|
// every provider result. Memoir extraction and projection assistants are excluded.
|
||
|
|
func (c *Client) ChatMemories(ctx context.Context, user, kind, query string, limit int, start, end int64) ([]callmemory.VikingRecord, bool, error) {
|
||
|
|
if user == "" || kind != "event" && kind != "profile" || limit < 1 || limit > 5000 {
|
||
|
|
return nil, false, errors.New("invalid chat memory scope")
|
||
|
|
}
|
||
|
|
rule := c.options.EventType
|
||
|
|
if kind == "profile" {
|
||
|
|
rule = c.options.ProfileType
|
||
|
|
}
|
||
|
|
filter := map[string]any{"user_id": []string{user}, "assistant_id": []string{AssistantID}, "memory_type": []string{rule}}
|
||
|
|
if start > 0 {
|
||
|
|
filter["start_time"] = start
|
||
|
|
}
|
||
|
|
if end > 0 {
|
||
|
|
filter["end_time"] = end
|
||
|
|
}
|
||
|
|
payload := map[string]any{"filter": filter, "limit": limit}
|
||
|
|
if query != "" {
|
||
|
|
payload["query"] = query
|
||
|
|
}
|
||
|
|
var data struct {
|
||
|
|
Items []struct {
|
||
|
|
Item
|
||
|
|
Time int64 `json:"time"`
|
||
|
|
Types []string `json:"memory_type"`
|
||
|
|
} `json:"result_list"`
|
||
|
|
}
|
||
|
|
if e := c.call(ctx, "/api/memory/"+kind+"/search", payload, &data); e != nil {
|
||
|
|
return nil, false, e
|
||
|
|
}
|
||
|
|
out := []callmemory.VikingRecord{}
|
||
|
|
limited := len(data.Items) >= limit
|
||
|
|
for _, item := range data.Items {
|
||
|
|
// Shared records cannot be deleted through an individual elder's console.
|
||
|
|
if item.ID == "" || len(item.UserID) != 1 || item.UserID[0] != user || len(item.AssistantID) != 1 || item.AssistantID[0] != AssistantID || !contains(item.Types, rule) {
|
||
|
|
// A filtered or malformed response cannot prove a deleted ID is absent.
|
||
|
|
limited = true
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
content := []string{}
|
||
|
|
for _, key := range []string{"summary", "user_profile"} {
|
||
|
|
if raw := item.MemoryInfo[key]; len(raw) > 0 {
|
||
|
|
var text string
|
||
|
|
if json.Unmarshal(raw, &text) != nil {
|
||
|
|
text = string(raw)
|
||
|
|
}
|
||
|
|
if strings.TrimSpace(text) != "" {
|
||
|
|
content = append(content, text)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if len(content) == 0 {
|
||
|
|
b, _ := json.MarshalIndent(item.MemoryInfo, "", " ")
|
||
|
|
content = append(content, string(b))
|
||
|
|
}
|
||
|
|
r := callmemory.VikingRecord{ID: item.ID, Kind: kind, Time: item.Time, SessionID: item.SessionID, Content: strings.Join(content, "\n"), MemoryInfo: item.MemoryInfo}
|
||
|
|
raw, e := json.Marshal(r)
|
||
|
|
if e != nil {
|
||
|
|
return nil, false, e
|
||
|
|
}
|
||
|
|
sum := sha256.Sum256(raw)
|
||
|
|
r.Digest = hex.EncodeToString(sum[:])
|
||
|
|
out = append(out, r)
|
||
|
|
}
|
||
|
|
return out, limited, nil
|
||
|
|
}
|
||
|
|
func (c *Client) DeleteChatMemory(ctx context.Context, kind, id string) error {
|
||
|
|
if (kind != "event" && kind != "profile") || id == "" {
|
||
|
|
return errors.New("invalid chat memory deletion")
|
||
|
|
}
|
||
|
|
return c.call(ctx, "/api/memory/"+kind+"/delete", map[string]any{kind + "_id": id}, nil)
|
||
|
|
}
|