feat: expand companion platform, device controls, and memoir workflows
ci / verify (push) Canceled after 0s
ci / verify (push) Canceled after 0s
Add customer and operator login, BLE provisioning, device fleet controls, call memory, memoir generation, and refreshed family and maintenance portals. Include API contracts, migrations, firmware sources, tests, assets, and deployment documentation.
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
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)
|
||||
}
|
||||
Reference in New Issue
Block a user