package memory import ( "context" "fmt" "go.temporal.io/sdk/activity" ) // Activities memory service activities for Temporal workflows type Activities struct { service *Service } // NewActivities creates memory service activities func NewActivities(service *Service) *Activities { return &Activities{ service: service, } } // CreateKnowledgeActivity creates knowledge record from workflow execution func (a *Activities) CreateKnowledgeActivity(ctx context.Context, record *KnowledgeRecord) (string, error) { logger := activity.GetLogger(ctx) logger.Info("Creating knowledge", "title", record.Title) id, err := a.service.CreateKnowledge(ctx, record) if err != nil { logger.Error("Failed to create knowledge", "error", err) return "", err } logger.Info("Knowledge created", "id", id) return id, nil } // UpdateKnowledgeActivity updates existing knowledge record func (a *Activities) UpdateKnowledgeActivity(ctx context.Context, record *KnowledgeRecord) (string, error) { logger := activity.GetLogger(ctx) logger.Info("Updating knowledge", "id", record.ID) id, err := a.service.UpdateKnowledge(ctx, record) if err != nil { logger.Error("Failed to update knowledge", "error", err) return "", err } logger.Info("Knowledge updated", "id", id) return id, nil } // SearchKnowledgeActivity searches knowledge base func (a *Activities) SearchKnowledgeActivity(ctx context.Context, query string, opts *RetrievalOptions) ([]KnowledgeRecord, error) { logger := activity.GetLogger(ctx) logger.Info("Searching knowledge", "query", query) records, err := a.service.RetrieveKnowledge(ctx, query, opts) if err != nil { logger.Error("Search failed", "error", err) return nil, err } logger.Info("Found records", "count", len(records)) return records, nil } // GetContextActivity retrieves context for tool/task (three-tier retrieval) func (a *Activities) GetContextActivity(ctx context.Context, tool, task string, budget int) (*ServiceContext, error) { logger := activity.GetLogger(ctx) logger.Info("Getting context", "tool", tool, "task", task) svcCtx, err := a.service.RetrieveContext(ctx, tool, task, budget) if err != nil { logger.Error("Get context failed", "error", err) return nil, err } logger.Info("Retrieved context", "tier", svcCtx.Tier, "lessons", len(svcCtx.Lessons)) return svcCtx, nil } // GetVaultActivity lists vault files func (a *Activities) GetVaultActivity(ctx context.Context) ([]VaultInfo, error) { logger := activity.GetLogger(ctx) logger.Info("Fetching vault") files, err := a.service.GetVault(ctx) if err != nil { logger.Error("Get vault failed", "error", err) return nil, err } logger.Info("Vault files", "count", len(files)) return files, nil } // HealthCheckActivity checks memory service health func (a *Activities) HealthCheckActivity(ctx context.Context) (bool, error) { logger := activity.GetLogger(ctx) logger.Info("Checking memory service health") if !a.service.IsHealthy(ctx) { logger.Warn("Memory service is unhealthy") return false, fmt.Errorf("memory service unhealthy") } logger.Info("Memory service is healthy") return true, nil } // LearnFromExecutionActivity learns from task execution result func (a *Activities) LearnFromExecutionActivity(ctx context.Context, taskID string, result string, tags []string) (string, error) { logger := activity.GetLogger(ctx) logger.Info("Learning from task execution", "taskID", taskID) metadata := map[string]interface{}{ "task_id": taskID, "type": "execution_result", } if len(tags) > 0 { metadata["tags"] = tags } id, err := a.service.CreateKnowledge(ctx, &KnowledgeRecord{ Level: "L1", Title: fmt.Sprintf("Task Execution: %s", taskID), Content: result, Source: fmt.Sprintf("workflow://task/%s", taskID), Metadata: metadata, }) if err != nil { logger.Error("Failed to learn from execution", "error", err) return "", err } logger.Info("Learned from execution", "id", id) return id, nil } // DiagnoseIssueActivity diagnoses issue using memory context func (a *Activities) DiagnoseIssueActivity(ctx context.Context, tool, issue string) ([]string, error) { logger := activity.GetLogger(ctx) logger.Info("Diagnosing issue", "tool", tool, "issue", issue) svcCtx, err := a.service.RetrieveContext(ctx, tool, issue, 8192) if err != nil { logger.Error("Diagnosis failed", "error", err) return nil, err } // Extract recommendations recommendations := make([]string, 0) // Add tier-1 lessons (highest confidence) for _, lesson := range svcCtx.Lessons { if lesson.Tier == 1 { recommendations = append(recommendations, fmt.Sprintf("[Tier 1] %s", lesson.Text)) } } // Add skills for _, skill := range svcCtx.Skills { recommendations = append(recommendations, fmt.Sprintf("[Skill] %s: %s", skill.Name, skill.Why)) } // Add tier-2 lessons if no tier-1 if len(recommendations) == 0 { for _, lesson := range svcCtx.Lessons { if lesson.Tier == 2 { recommendations = append(recommendations, fmt.Sprintf("[Tier 2] %s", lesson.Text)) } } } logger.Info("Generated recommendations", "count", len(recommendations)) return recommendations, nil } // AnalyzeErrorActivity analyzes error and retrieves relevant knowledge func (a *Activities) AnalyzeErrorActivity(ctx context.Context, errorMsg string) ([]KnowledgeRecord, error) { logger := activity.GetLogger(ctx) logger.Info("Analyzing error") // Search for relevant knowledge records, err := a.service.RetrieveKnowledge(ctx, errorMsg, &RetrievalOptions{ Limit: 10, LevelFilter: []string{"L1", "L2"}, Floor: 0.6, }) if err != nil { logger.Error("Error analysis failed", "error", err) return nil, err } logger.Info("Found relevant records for error", "count", len(records)) return records, nil } // DocumentDecisionActivity documents workflow decision in knowledge base func (a *Activities) DocumentDecisionActivity(ctx context.Context, decisionType string, decision string, reasoning string) (string, error) { logger := activity.GetLogger(ctx) logger.Info("Documenting decision", "type", decisionType) content := fmt.Sprintf("Decision: %s\n\nReasoning: %s", decision, reasoning) id, err := a.service.CreateKnowledge(ctx, &KnowledgeRecord{ Level: "L2", Title: fmt.Sprintf("Decision: %s", decisionType), Content: content, Source: fmt.Sprintf("workflow://decision/%s", decisionType), Metadata: map[string]interface{}{ "decision_type": decisionType, "type": "workflow_decision", }, }) if err != nil { logger.Error("Failed to document decision", "error", err) return "", err } logger.Info("Decision documented", "id", id) return id, nil } // SearchAndApplyActivity searches knowledge and applies it func (a *Activities) SearchAndApplyActivity(ctx context.Context, query string, selector func(record *KnowledgeRecord) bool) ([]string, error) { logger := activity.GetLogger(ctx) logger.Info("Searching and applying", "query", query) records, err := a.service.RetrieveKnowledge(ctx, query, &RetrievalOptions{ Limit: 10, Floor: 0.7, }) if err != nil { logger.Error("Search and apply failed", "error", err) return nil, err } applied := make([]string, 0) for _, record := range records { if selector == nil || selector(&record) { applied = append(applied, record.Content) logger.Info("Applied knowledge", "id", record.ID) } } logger.Info("Applied knowledge records", "count", len(applied)) return applied, nil } // RefreshMemoryActivity refreshes memory context (periodic activity) func (a *Activities) RefreshMemoryActivity(ctx context.Context) (map[string]interface{}, error) { logger := activity.GetLogger(ctx) logger.Info("Refreshing memory context") vault, err := a.service.GetVault(ctx) if err != nil { logger.Error("Memory refresh failed", "error", err) return nil, err } healthy := a.service.IsHealthy(ctx) result := map[string]interface{}{ "vault_files": len(vault), "healthy": healthy, } logger.Info("Memory refreshed", "vault_files", len(vault), "healthy", healthy) return result, nil }