package room import ( "context" "fmt" "log" "os" "path/filepath" "strings" "time" "github.com/sdaduanbilei/agent-team/internal/agent" "github.com/sdaduanbilei/agent-team/internal/llm" ) func (r *Room) updateMasterMemory(ctx context.Context, task string, msgs []llm.Message) { if len([]rune(strings.TrimSpace(task))) < 10 { log.Printf("[memory] 跳过短任务记忆: %q", task) return } summaryPrompt := fmt.Sprintf(`基于这个任务: %q 总结核心经验(最多3条 bullet points)。 如果这个任务没有值得记忆的经验(如简单问候、闲聊),只输出 SKIP。`, task) memMsgs := append(msgs, llm.NewMsg("user", summaryPrompt)) summary, err := r.master.Chat(ctx, memMsgs, nil) if err != nil || summary == "" { return } if strings.TrimSpace(summary) == "SKIP" { log.Printf("[memory] LLM 判断跳过记忆: %q", task) return } filename := time.Now().Format("2006-01") + ".md" existing, _ := os.ReadFile(filepath.Join(r.master.Dir, "memory", filename)) taskTitle := task if len([]rune(taskTitle)) > 50 { taskTitle = string([]rune(taskTitle)[:50]) } content := string(existing) + fmt.Sprintf("\n## %s — %s\n\n%s\n", time.Now().Format("2006-01-02"), taskTitle, summary) r.master.SaveMemory(filename, content) memFile := filepath.Join(r.master.Dir, "memory", filename) if info, err := os.Stat(memFile); err == nil && info.Size() > 20*1024 { log.Printf("[memory] 当月文件 %s 超过 20KB,触发压缩", filename) go r.master.CompressMemory(context.Background()) } } // CompressAllMemory 压缩 room 中所有 agent(master + members)的记忆。 func (r *Room) CompressAllMemory(ctx context.Context) { if r.master != nil { if err := r.master.CompressMemory(ctx); err != nil { log.Printf("[memory] master 压缩失败: %v", err) } } for name, member := range r.members { if err := member.CompressMemory(ctx); err != nil { log.Printf("[memory] 成员 %s 压缩失败: %v", name, err) } } log.Printf("[memory] 全部 agent 记忆压缩完成") } // updateMemberMemory 为成员 agent 保存任务经验。 func (r *Room) updateMemberMemory(ctx context.Context, member *agent.Agent, task, result string) { if len([]rune(strings.TrimSpace(task))) < 10 { return } summaryPrompt := fmt.Sprintf(`基于这个任务和结果: 任务: %q 结果: %.500s 总结1-2条关键经验。如果没有值得记忆的,只输出 SKIP。`, task, result) msgs := []llm.Message{ llm.NewMsg("system", "你是一个团队成员,总结工作经验。"), llm.NewMsg("user", summaryPrompt), } summary, err := member.Chat(ctx, msgs, nil) if err != nil || summary == "" || strings.TrimSpace(summary) == "SKIP" { return } filename := time.Now().Format("2006-01") + ".md" existing, _ := os.ReadFile(filepath.Join(member.Dir, "memory", filename)) taskTitle := task if len([]rune(taskTitle)) > 50 { taskTitle = string([]rune(taskTitle)[:50]) } content := string(existing) + fmt.Sprintf("\n## %s — %s\n\n%s\n", time.Now().Format("2006-01-02"), taskTitle, summary) member.SaveMemory(filename, content) log.Printf("[memory] 成员 %s 记忆已更新", member.Config.Name) } // appendPlanLog 将沟通记录追加到任务计划文档 func (r *Room) appendPlanLog(from, to, content string) { if r.planFilename == "" { return } path := filepath.Join(r.Dir, "workspace", r.planFilename) f, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY, 0644) if err != nil { return } defer f.Close() entry := fmt.Sprintf("\n---\n**[%s] %s → %s**\n\n%s\n", time.Now().Format("15:04:05"), from, to, content) f.WriteString(entry) } func (r *Room) updateTasks(msgs []llm.Message) { var tasks strings.Builder tasks.WriteString("# Tasks\n\n") for _, m := range msgs { if m.Role == "assistant" { assignments := parseAssignments(m.Content) for name, task := range assignments { tasks.WriteString(fmt.Sprintf("- [ ] [%s] %s\n", name, task)) } } } content := tasks.String() os.WriteFile(filepath.Join(r.Dir, "tasks.md"), []byte(content), 0644) r.emit(Event{Type: EvtTasksUpdate, Content: content}) }