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,89 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user