package memory import ( "context" "fmt" ) // Service memory service manager type Service struct { client *Client project string } // NewService creates memory service manager func NewService(baseURL, token, project string) *Service { return &Service{ client: NewClient(baseURL, token), project: project, } } // KnowledgeRecord high-level knowledge record type KnowledgeRecord struct { ID string Level string // L1|L2|reference Title string Content string Source string Metadata map[string]interface{} SHA256 string } // CreateKnowledge creates knowledge record func (s *Service) CreateKnowledge(ctx context.Context, record *KnowledgeRecord) (string, error) { if record.Level == "" { record.Level = "L1" } if record.Source == "" { record.Source = "workflow" } req := &IngestRequest{ Project: s.project, Source: record.Source, Kind: record.Level, Text: record.Content, Metadata: record.Metadata, } resp, err := s.client.Ingest(ctx, req) if err != nil { return "", fmt.Errorf("create knowledge: %w", err) } return resp.ID, nil } // UpdateKnowledge updates existing knowledge (re-ingest) func (s *Service) UpdateKnowledge(ctx context.Context, record *KnowledgeRecord) (string, error) { // Update done by re-ingesting with same signature/source // Memory service deduplicates based on idempotency key if record.Metadata == nil { record.Metadata = make(map[string]interface{}) } // Use ID as session_id for idempotency record.Metadata["session_id"] = record.ID return s.CreateKnowledge(ctx, record) } // RetrievalOptions search options type RetrievalOptions struct { LevelFilter []string // L1, L2, R Floor float32 // minimum relevance Limit int // default 10 Scope string // learned|reference|all } // RetrieveKnowledge searches knowledge func (s *Service) RetrieveKnowledge(ctx context.Context, query string, opts *RetrievalOptions) ([]KnowledgeRecord, error) { if opts == nil { opts = &RetrievalOptions{} } if opts.Limit == 0 { opts.Limit = 10 } req := &QueryRequest{ Project: s.project, Query: query, LevelFilter: opts.LevelFilter, Floor: opts.Floor, Limit: opts.Limit, Scope: opts.Scope, } resp, err := s.client.Query(ctx, req) if err != nil { return nil, fmt.Errorf("retrieve knowledge: %w", err) } records := make([]KnowledgeRecord, len(resp.Results)) for i, r := range resp.Results { records[i] = KnowledgeRecord{ ID: r.ID, Level: r.Level, Content: r.Text, Source: r.Source, SHA256: "", // Not in response Metadata: map[string]interface{}{ "score": r.Score, "semantic_score": r.SemanticScore, "lexical_score": r.LexicalScore, "breadcrumb": r.Breadcrumb, }, } } return records, nil } // ServiceContext tool/task context type ServiceContext struct { Tier int Lessons []Lesson Skills []Skill BudgetUsed int BudgetMax int } // Lesson learned fact or reference type Lesson struct { Tier int Level string Score float32 Text string MatchedKind string SeenCount int LastSeen string } // Skill recommended action type Skill struct { Name string Why string } // RetrieveContext retrieves context for tool/task (three-tier) func (s *Service) RetrieveContext(ctx context.Context, tool, task string, budget int) (*ServiceContext, error) { if budget == 0 { budget = 8192 } req := &ContextRequest{ Project: s.project, Tool: tool, Task: task, SignatureSource: fmt.Sprintf("%s:%s", tool, task), Scope: "tool_context", Budget: budget, } resp, err := s.client.Context(ctx, req) if err != nil { return nil, fmt.Errorf("retrieve context: %w", err) } lessons := make([]Lesson, len(resp.Lessons)) for i, l := range resp.Lessons { lessons[i] = Lesson{ Tier: l.Tier, Level: l.Level, Score: l.Score, Text: l.Text, MatchedKind: l.MatchedKind, SeenCount: l.SeenCount, LastSeen: l.LastSeen, } } skills := make([]Skill, len(resp.Skills)) for i, sk := range resp.Skills { skills[i] = Skill{ Name: sk.Name, Why: sk.Why, } } return &ServiceContext{ Tier: resp.Tier, Lessons: lessons, Skills: skills, BudgetUsed: resp.Budget.Used, BudgetMax: resp.Budget.Requested, }, nil } // VaultInfo vault browsing type VaultInfo struct { Path string Title string Level string UpdatedAt string RecordCount int } // GetVault lists vault files func (s *Service) GetVault(ctx context.Context) ([]VaultInfo, error) { resp, err := s.client.Vault(ctx, s.project) if err != nil { return nil, fmt.Errorf("get vault: %w", err) } files := make([]VaultInfo, len(resp.Files)) for i, f := range resp.Files { files[i] = VaultInfo{ Path: f.Path, Title: f.Title, Level: f.Level, UpdatedAt: f.UpdatedAt, RecordCount: f.RecordCount, } } return files, nil } // IsHealthy checks service health func (s *Service) IsHealthy(ctx context.Context) bool { ok, err := s.client.Health(ctx) return ok && err == nil }