Add memory system, dynamic tool loading, and fix logging issues
- Add MemoryStore for persistent long-term and daily notes - Add dynamic tool summary generation in system prompt - Fix YAML frontmatter parsing for nanobot skill format - Add GetSummaries() method to ToolRegistry - Fix DebugCF logging to use structured metadata - Improve web_search and shell tool descriptions
This commit is contained in:
@@ -10,12 +10,12 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// MemoryStore manages persistent memory for the agent.
|
||||
// Supports daily notes (memory/YYYY-MM-DD.md) and long-term memory (MEMORY.md).
|
||||
// - Long-term memory: memory/MEMORY.md
|
||||
// - Daily notes: memory/YYYYMM/YYYYMMDD.md
|
||||
type MemoryStore struct {
|
||||
workspace string
|
||||
memoryDir string
|
||||
@@ -38,23 +38,29 @@ func NewMemoryStore(workspace string) *MemoryStore {
|
||||
}
|
||||
}
|
||||
|
||||
// getMemoryDir returns the memory directory path.
|
||||
func (ms *MemoryStore) getMemoryDir() string {
|
||||
return ms.memoryDir
|
||||
}
|
||||
|
||||
// getMemoryFile returns the long-term memory file path.
|
||||
func (ms *MemoryStore) getMemoryFile() string {
|
||||
return ms.memoryFile
|
||||
}
|
||||
|
||||
// getTodayFile returns the path to today's memory file (YYYY-MM-DD.md).
|
||||
// getTodayFile returns the path to today's daily note file (memory/YYYYMM/YYYYMMDD.md).
|
||||
func (ms *MemoryStore) getTodayFile() string {
|
||||
today := time.Now().Format("2006-01-02")
|
||||
return filepath.Join(ms.memoryDir, today+".md")
|
||||
today := time.Now().Format("20060102") // YYYYMMDD
|
||||
monthDir := today[:6] // YYYYMM
|
||||
filePath := filepath.Join(ms.memoryDir, monthDir, today+".md")
|
||||
return filePath
|
||||
}
|
||||
|
||||
// ReadToday reads today's memory notes.
|
||||
// ReadLongTerm reads the long-term memory (MEMORY.md).
|
||||
// Returns empty string if the file doesn't exist.
|
||||
func (ms *MemoryStore) ReadLongTerm() string {
|
||||
if data, err := os.ReadFile(ms.memoryFile); err == nil {
|
||||
return string(data)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// WriteLongTerm writes content to the long-term memory file (MEMORY.md).
|
||||
func (ms *MemoryStore) WriteLongTerm(content string) error {
|
||||
return os.WriteFile(ms.memoryFile, []byte(content), 0644)
|
||||
}
|
||||
|
||||
// ReadToday reads today's daily note.
|
||||
// Returns empty string if the file doesn't exist.
|
||||
func (ms *MemoryStore) ReadToday() string {
|
||||
todayFile := ms.getTodayFile()
|
||||
@@ -64,11 +70,15 @@ func (ms *MemoryStore) ReadToday() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// AppendToday appends content to today's memory notes.
|
||||
// AppendToday appends content to today's daily note.
|
||||
// If the file doesn't exist, it creates a new file with a date header.
|
||||
func (ms *MemoryStore) AppendToday(content string) error {
|
||||
todayFile := ms.getTodayFile()
|
||||
|
||||
// Ensure month directory exists
|
||||
monthDir := filepath.Dir(todayFile)
|
||||
os.MkdirAll(monthDir, 0755)
|
||||
|
||||
var existingContent string
|
||||
if data, err := os.ReadFile(todayFile); err == nil {
|
||||
existingContent = string(data)
|
||||
@@ -87,46 +97,39 @@ func (ms *MemoryStore) AppendToday(content string) error {
|
||||
return os.WriteFile(todayFile, []byte(newContent), 0644)
|
||||
}
|
||||
|
||||
// ReadLongTerm reads the long-term memory (MEMORY.md).
|
||||
// Returns empty string if the file doesn't exist.
|
||||
func (ms *MemoryStore) ReadLongTerm() string {
|
||||
if data, err := os.ReadFile(ms.memoryFile); err == nil {
|
||||
return string(data)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// WriteLongTerm writes content to the long-term memory file (MEMORY.md).
|
||||
func (ms *MemoryStore) WriteLongTerm(content string) error {
|
||||
return os.WriteFile(ms.memoryFile, []byte(content), 0644)
|
||||
}
|
||||
|
||||
// GetRecentMemories returns memories from the last N days.
|
||||
// It reads and combines the contents of memory files from the past days.
|
||||
// GetRecentDailyNotes returns daily notes from the last N days.
|
||||
// Contents are joined with "---" separator.
|
||||
func (ms *MemoryStore) GetRecentMemories(days int) string {
|
||||
var memories []string
|
||||
func (ms *MemoryStore) GetRecentDailyNotes(days int) string {
|
||||
var notes []string
|
||||
|
||||
for i := 0; i < days; i++ {
|
||||
date := time.Now().AddDate(0, 0, -i)
|
||||
dateStr := date.Format("2006-01-02")
|
||||
filePath := filepath.Join(ms.memoryDir, dateStr+".md")
|
||||
dateStr := date.Format("20060102") // YYYYMMDD
|
||||
monthDir := dateStr[:6] // YYYYMM
|
||||
filePath := filepath.Join(ms.memoryDir, monthDir, dateStr+".md")
|
||||
|
||||
if data, err := os.ReadFile(filePath); err == nil {
|
||||
memories = append(memories, string(data))
|
||||
notes = append(notes, string(data))
|
||||
}
|
||||
}
|
||||
|
||||
if len(memories) == 0 {
|
||||
if len(notes) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
return strings.Join(memories, "\n\n---\n\n")
|
||||
// Join with separator
|
||||
var result string
|
||||
for i, note := range notes {
|
||||
if i > 0 {
|
||||
result += "\n\n---\n\n"
|
||||
}
|
||||
result += note
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// GetMemoryContext returns formatted memory context for the agent prompt.
|
||||
// It includes long-term memory and today's notes sections if they exist.
|
||||
// Returns empty string if no memory exists.
|
||||
// Includes long-term memory and recent daily notes.
|
||||
func (ms *MemoryStore) GetMemoryContext() string {
|
||||
var parts []string
|
||||
|
||||
@@ -136,15 +139,23 @@ func (ms *MemoryStore) GetMemoryContext() string {
|
||||
parts = append(parts, "## Long-term Memory\n\n"+longTerm)
|
||||
}
|
||||
|
||||
// Today's notes
|
||||
today := ms.ReadToday()
|
||||
if today != "" {
|
||||
parts = append(parts, "## Today's Notes\n\n"+today)
|
||||
// Recent daily notes (last 3 days)
|
||||
recentNotes := ms.GetRecentDailyNotes(3)
|
||||
if recentNotes != "" {
|
||||
parts = append(parts, "## Recent Daily Notes\n\n"+recentNotes)
|
||||
}
|
||||
|
||||
if len(parts) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
return strings.Join(parts, "\n\n")
|
||||
// Join parts with separator
|
||||
var result string
|
||||
for i, part := range parts {
|
||||
if i > 0 {
|
||||
result += "\n\n---\n\n"
|
||||
}
|
||||
result += part
|
||||
}
|
||||
return fmt.Sprintf("# Memory\n\n%s", result)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user