Files
story/internal/elderagent/native_memory.go
T
Codex Local bf1233d5df
ci / verify (push) Canceled after 0s
feat: expand companion platform, device controls, and memoir workflows
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.
2026-10-08 10:06:44 +08:00

90 lines
3.3 KiB
Go

package elderagent
import (
"bytes"
"context"
"encoding/json"
"fmt"
"strings"
"data-terminal-cloud/internal/memoryidentity"
)
// Native memory uses exactly the identity used by transcript uploads. Never
// inherit the template's shared user filter or use a device as the identity.
func (s *Service) nativeMemoryConfiguration(tenant, subject string, allowed bool) (map[string]any, error) {
if !allowed {
return map[string]any{"Enable": false}, nil
}
collection, event := strings.TrimSpace(s.VikingCollectionName), strings.TrimSpace(s.VikingEventType)
if collection == "" || event == "" || tenant == "" || subject == "" {
return nil, fmt.Errorf("VIKING_NATIVE_MEMORY_CONFIG_REQUIRED")
}
return map[string]any{"Enable": true, "Provider": "volc", "ProviderParams": map[string]any{
"collection_name": collection, "limit": 3,
"filter": map[string]any{"user_id": []string{memoryidentity.UserID(tenant, subject)}, "assistant_id": []string{memoryidentity.AssistantID}, "memory_type": []string{event}},
}}, nil
}
// NativeMemoryConfiguration keeps saved-bot upgrades in the upload namespace.
func (s *Service) NativeMemoryConfiguration(tenant, subject string, allowed bool) (map[string]any, error) {
return s.nativeMemoryConfiguration(tenant, subject, allowed)
}
func (s *Service) configureNativeMemory(ctx context.Context, subject string, config map[string]any) error {
var tenant string
var allowed bool
err := s.Pool.QueryRow(ctx, `SELECT p.tenant_id::text,p.status='active' AND call_memory_authorized(p.id) AND COALESCE((SELECT effective_consents @> '{"voice_chat":true}'::jsonb FROM consent_snapshot WHERE subject_id=p.id ORDER BY snapshot_version DESC LIMIT 1),false) AND NOT EXISTS(SELECT 1 FROM privacy_request WHERE subject_id=p.id AND request_type='DELETE') FROM subject_profile p WHERE p.id=$1::uuid`, subject).Scan(&tenant, &allowed)
if err != nil {
return err
}
config["MemoryConfig"], err = s.nativeMemoryConfiguration(tenant, subject, allowed)
return err
}
// Read back the filter too: checking Enable alone cannot detect cross-elder
// retrieval or an incorrect collection. Provider credentials are never read.
func (c *Client) VerifyNativeMemory(ctx context.Context, id string, expected map[string]any) error {
var result struct {
Bots []Bot `json:"Bots"`
}
if err := c.call(ctx, "AibotQuery", map[string]any{"Id": id}, &result); err != nil {
return err
}
for _, bot := range result.Bots {
if bot.ID != id {
continue
}
actual, _ := bot.Config["MemoryConfig"].(map[string]any)
rawEnabled, present := actual["Enable"]
enabled, valid := rawEnabled.(bool)
if present && !valid {
break
}
wantEnabled, _ := expected["Enable"].(bool)
if enabled != wantEnabled {
break
}
if !wantEnabled {
return nil
}
want, _ := json.Marshal(expected["ProviderParams"])
got, _ := json.Marshal(actual["ProviderParams"])
if actual["Provider"] == expected["Provider"] && bytes.Equal(want, got) {
return nil
}
break
}
return fmt.Errorf("VIKING_NATIVE_MEMORY_VERIFY_FAILED")
}
func (s *Service) verifyNativeMemory(ctx context.Context, bot string, config map[string]any) error {
if verifier, ok := s.Provider.(interface {
VerifyNativeMemory(context.Context, string, map[string]any) error
}); ok {
memory, _ := config["MemoryConfig"].(map[string]any)
return verifier.VerifyNativeMemory(ctx, bot, memory)
}
return nil
}