feat: expand companion platform, device controls, and memoir workflows
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:
Codex Local
2026-10-08 10:06:44 +08:00
parent 98fb2965d0
commit bf1233d5df
861 changed files with 94614 additions and 3209 deletions
+59
View File
@@ -0,0 +1,59 @@
package vikingmemory
import (
"context"
"encoding/json"
"errors"
"strings"
)
// Events are the managed unit: profiles are not independently regenerated from
// a deleted/corrected event. Every event is mirrored into the editable platform
// store before it can be used in a voice prompt.
const ManagedAssistantID = "voicelink_managed_v1"
func (c *Client) AddManagedSession(ctx context.Context, session, user string, messages []Message, at int64) error {
if session == "" || user == "" || len(messages) == 0 || len(messages) > 1000 {
return errors.New("invalid managed session")
}
return c.call(ctx, "/api/memory/session/add", map[string]any{
"session_id": session, "messages": messages, "store_file": false,
"metadata": map[string]any{"default_user_id": user, "default_assistant_id": ManagedAssistantID, "time": at},
"extract_memory_type": []string{c.options.EventType},
}, nil)
}
func (c *Client) ManagedEvents(ctx context.Context, user, session string) ([]Item, error) {
if user == "" || session == "" {
return nil, errors.New("managed scope required")
}
var data struct {
Items []Item `json:"result_list"`
}
err := c.call(ctx, "/api/memory/event/search", map[string]any{"filter": map[string]any{
"user_id": []string{user}, "assistant_id": []string{ManagedAssistantID}, "session_id": []string{session}, "memory_type": []string{c.options.EventType},
}, "limit": 1000}, &data)
if err != nil {
return nil, err
}
if len(data.Items) >= 1000 {
return nil, errors.New("managed result limit reached")
}
out := []Item{}
for _, item := range data.Items {
if item.ID == "" || !contains(item.UserID, user) || !contains(item.AssistantID, ManagedAssistantID) || item.SessionID != session {
continue
}
var summary string
if json.Unmarshal(item.MemoryInfo["summary"], &summary) != nil {
continue
}
summary = strings.TrimSpace(summary)
if summary == "" || len([]rune(summary)) > 4000 {
continue
}
item.Content = summary
out = append(out, item)
}
return out, nil
}