Add memory system, debug mode, and tools
This commit is contained in:
@@ -4,8 +4,11 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/sipeed/picoclaw/pkg/logger"
|
||||
"github.com/sipeed/picoclaw/pkg/providers"
|
||||
"github.com/sipeed/picoclaw/pkg/skills"
|
||||
)
|
||||
@@ -13,6 +16,7 @@ import (
|
||||
type ContextBuilder struct {
|
||||
workspace string
|
||||
skillsLoader *skills.SkillsLoader
|
||||
memory *MemoryStore
|
||||
}
|
||||
|
||||
func NewContextBuilder(workspace string) *ContextBuilder {
|
||||
@@ -20,12 +24,14 @@ func NewContextBuilder(workspace string) *ContextBuilder {
|
||||
return &ContextBuilder{
|
||||
workspace: workspace,
|
||||
skillsLoader: skills.NewSkillsLoader(workspace, builtinSkillsDir),
|
||||
memory: NewMemoryStore(workspace),
|
||||
}
|
||||
}
|
||||
|
||||
func (cb *ContextBuilder) BuildSystemPrompt() string {
|
||||
func (cb *ContextBuilder) getIdentity() string {
|
||||
now := time.Now().Format("2006-01-02 15:04 (Monday)")
|
||||
workspacePath, _ := filepath.Abs(filepath.Join(cb.workspace))
|
||||
runtime := fmt.Sprintf("%s %s, Go %s", runtime.GOOS, runtime.GOARCH, runtime.Version())
|
||||
|
||||
return fmt.Sprintf(`# picoclaw 🦞
|
||||
|
||||
@@ -39,6 +45,9 @@ You are picoclaw, a helpful AI assistant. You have access to tools that allow yo
|
||||
## Current Time
|
||||
%s
|
||||
|
||||
## Runtime
|
||||
%s
|
||||
|
||||
## Workspace
|
||||
Your workspace is at: %s
|
||||
- Memory files: %s/memory/MEMORY.md
|
||||
@@ -60,7 +69,49 @@ For normal conversation, just respond with text - do not call the message tool.
|
||||
|
||||
Always be helpful, accurate, and concise. When using tools, explain what you're doing.
|
||||
When remembering something, write to %s/memory/MEMORY.md`,
|
||||
now, workspacePath, workspacePath, workspacePath, workspacePath, workspacePath)
|
||||
now, runtime, workspacePath, workspacePath, workspacePath, workspacePath, workspacePath)
|
||||
}
|
||||
|
||||
func (cb *ContextBuilder) BuildSystemPrompt() string {
|
||||
parts := []string{}
|
||||
|
||||
// Core identity section
|
||||
parts = append(parts, cb.getIdentity())
|
||||
|
||||
// Bootstrap files
|
||||
bootstrapContent := cb.LoadBootstrapFiles()
|
||||
if bootstrapContent != "" {
|
||||
parts = append(parts, bootstrapContent)
|
||||
}
|
||||
|
||||
// Skills - progressive loading
|
||||
// 1. Always skills: load full content
|
||||
alwaysSkills := cb.skillsLoader.GetAlwaysSkills()
|
||||
if len(alwaysSkills) > 0 {
|
||||
alwaysContent := cb.skillsLoader.LoadSkillsForContext(alwaysSkills)
|
||||
if alwaysContent != "" {
|
||||
parts = append(parts, "# Active Skills\n\n"+alwaysContent)
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Available skills: only show summary
|
||||
skillsSummary := cb.skillsLoader.BuildSkillsSummary()
|
||||
if skillsSummary != "" {
|
||||
parts = append(parts, fmt.Sprintf(`# Skills
|
||||
|
||||
The following skills extend your capabilities. To use a skill, read its SKILL.md file.
|
||||
|
||||
%s`, skillsSummary))
|
||||
}
|
||||
|
||||
// Memory context
|
||||
memoryContext := cb.memory.GetMemoryContext()
|
||||
if memoryContext != "" {
|
||||
parts = append(parts, "# Memory\n\n"+memoryContext)
|
||||
}
|
||||
|
||||
// Join with "---" separator
|
||||
return strings.Join(parts, "\n\n---\n\n")
|
||||
}
|
||||
|
||||
func (cb *ContextBuilder) LoadBootstrapFiles() string {
|
||||
@@ -84,24 +135,28 @@ func (cb *ContextBuilder) LoadBootstrapFiles() string {
|
||||
return result
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
func (cb *ContextBuilder) BuildMessages(history []providers.Message, summary string, currentMessage string, media []string) []providers.Message {
|
||||
=======
|
||||
func (cb *ContextBuilder) BuildMessages(history []providers.Message, summary string, currentMessage string, media []string, channel, chatID string) []providers.Message {
|
||||
>>>>>>> fd1dd87 (Add memory system, debug mode, and tools)
|
||||
messages := []providers.Message{}
|
||||
|
||||
systemPrompt := cb.BuildSystemPrompt()
|
||||
bootstrapContent := cb.LoadBootstrapFiles()
|
||||
if bootstrapContent != "" {
|
||||
systemPrompt += "\n\n" + bootstrapContent
|
||||
|
||||
// Add Current Session info if provided
|
||||
if channel != "" && chatID != "" {
|
||||
systemPrompt += fmt.Sprintf("\n\n## Current Session\nChannel: %s\nChat ID: %s", channel, chatID)
|
||||
}
|
||||
|
||||
skillsSummary := cb.skillsLoader.BuildSkillsSummary()
|
||||
if skillsSummary != "" {
|
||||
systemPrompt += "\n\n## Available Skills\n\n" + skillsSummary
|
||||
}
|
||||
|
||||
skillsContent := cb.loadSkills()
|
||||
if skillsContent != "" {
|
||||
systemPrompt += "\n\n" + skillsContent
|
||||
}
|
||||
// Log system prompt for debugging
|
||||
logger.InfoCF("agent", "System prompt built",
|
||||
map[string]interface{}{
|
||||
"total_chars": len(systemPrompt),
|
||||
"total_lines": strings.Count(systemPrompt, "\n") + 1,
|
||||
"section_count": strings.Count(systemPrompt, "\n\n---\n\n") + 1,
|
||||
})
|
||||
logger.DebugCF("agent", "Full system prompt:\n"+systemPrompt, nil)
|
||||
|
||||
if summary != "" {
|
||||
systemPrompt += "\n\n## Summary of Previous Conversation\n\n" + summary
|
||||
@@ -160,3 +215,21 @@ func (cb *ContextBuilder) loadSkills() string {
|
||||
|
||||
return "# Skill Definitions\n\n" + content
|
||||
}
|
||||
|
||||
// GetSkillsInfo returns information about loaded skills.
|
||||
func (cb *ContextBuilder) GetSkillsInfo() map[string]interface{} {
|
||||
allSkills := cb.skillsLoader.ListSkills(true)
|
||||
skillNames := make([]string, 0, len(allSkills))
|
||||
availableCount := 0
|
||||
for _, s := range allSkills {
|
||||
skillNames = append(skillNames, s.Name)
|
||||
if s.Available {
|
||||
availableCount++
|
||||
}
|
||||
}
|
||||
return map[string]interface{}{
|
||||
"total": len(allSkills),
|
||||
"available": availableCount,
|
||||
"names": skillNames,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user