feat: Support installing built-in AGENT files and skills during picoclaw onboard
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -10,6 +10,7 @@ build/
|
||||
*.out
|
||||
/picoclaw
|
||||
/picoclaw-test
|
||||
cmd/picoclaw/workspace
|
||||
|
||||
# Picoclaw specific
|
||||
|
||||
|
||||
@@ -25,12 +25,8 @@ RUN apk add --no-cache ca-certificates tzdata
|
||||
# Copy binary
|
||||
COPY --from=builder /src/build/picoclaw /usr/local/bin/picoclaw
|
||||
|
||||
# Copy builtin skills
|
||||
COPY --from=builder /src/skills /opt/picoclaw/skills
|
||||
|
||||
# Create picoclaw home directory
|
||||
RUN mkdir -p /root/.picoclaw/workspace/skills && \
|
||||
cp -r /opt/picoclaw/skills/* /root/.picoclaw/workspace/skills/ 2>/dev/null || true
|
||||
RUN /usr/local/bin/picoclaw onboard
|
||||
|
||||
ENTRYPOINT ["picoclaw"]
|
||||
CMD ["gateway"]
|
||||
|
||||
31
Makefile
31
Makefile
@@ -67,6 +67,8 @@ all: build
|
||||
build:
|
||||
@echo "Building $(BINARY_NAME) for $(PLATFORM)/$(ARCH)..."
|
||||
@mkdir -p $(BUILD_DIR)
|
||||
@rm -r ./$(CMD_DIR)/workspace 2>/dev/null || true
|
||||
@cp -r workspace ./$(CMD_DIR)/workspace 2>/dev/null || true
|
||||
$(GO) build $(GOFLAGS) $(LDFLAGS) -o $(BINARY_PATH) ./$(CMD_DIR)
|
||||
@echo "Build complete: $(BINARY_PATH)"
|
||||
@ln -sf $(BINARY_NAME)-$(PLATFORM)-$(ARCH) $(BUILD_DIR)/$(BINARY_NAME)
|
||||
@@ -74,6 +76,8 @@ build:
|
||||
## build-all: Build picoclaw for all platforms
|
||||
build-all:
|
||||
@echo "Building for multiple platforms..."
|
||||
@rm -r ./$(CMD_DIR)/workspace 2>/dev/null || true
|
||||
@cp -r workspace ./$(CMD_DIR)/workspace 2>/dev/null || true
|
||||
@mkdir -p $(BUILD_DIR)
|
||||
GOOS=linux GOARCH=amd64 $(GO) build $(LDFLAGS) -o $(BUILD_DIR)/$(BINARY_NAME)-linux-amd64 ./$(CMD_DIR)
|
||||
GOOS=linux GOARCH=arm64 $(GO) build $(LDFLAGS) -o $(BUILD_DIR)/$(BINARY_NAME)-linux-arm64 ./$(CMD_DIR)
|
||||
@@ -89,35 +93,8 @@ install: build
|
||||
@cp $(BUILD_DIR)/$(BINARY_NAME) $(INSTALL_BIN_DIR)/$(BINARY_NAME)
|
||||
@chmod +x $(INSTALL_BIN_DIR)/$(BINARY_NAME)
|
||||
@echo "Installed binary to $(INSTALL_BIN_DIR)/$(BINARY_NAME)"
|
||||
@echo "Installing builtin skills to $(WORKSPACE_SKILLS_DIR)..."
|
||||
@mkdir -p $(WORKSPACE_SKILLS_DIR)
|
||||
@for skill in $(BUILTIN_SKILLS_DIR)/*/; do \
|
||||
if [ -d "$$skill" ]; then \
|
||||
skill_name=$$(basename "$$skill"); \
|
||||
if [ -f "$$skill/SKILL.md" ]; then \
|
||||
cp -r "$$skill" $(WORKSPACE_SKILLS_DIR); \
|
||||
echo " ✓ Installed skill: $$skill_name"; \
|
||||
fi; \
|
||||
fi; \
|
||||
done
|
||||
@echo "Installation complete!"
|
||||
|
||||
## install-skills: Install builtin skills to workspace
|
||||
install-skills:
|
||||
@echo "Installing builtin skills to $(WORKSPACE_SKILLS_DIR)..."
|
||||
@mkdir -p $(WORKSPACE_SKILLS_DIR)
|
||||
@for skill in $(BUILTIN_SKILLS_DIR)/*/; do \
|
||||
if [ -d "$$skill" ]; then \
|
||||
skill_name=$$(basename "$$skill"); \
|
||||
if [ -f "$$skill/SKILL.md" ]; then \
|
||||
mkdir -p $(WORKSPACE_SKILLS_DIR)/$$skill_name; \
|
||||
cp -r "$$skill" $(WORKSPACE_SKILLS_DIR); \
|
||||
echo " ✓ Installed skill: $$skill_name"; \
|
||||
fi; \
|
||||
fi; \
|
||||
done
|
||||
@echo "Skills installation complete!"
|
||||
|
||||
## uninstall: Remove picoclaw from system
|
||||
uninstall:
|
||||
@echo "Uninstalling $(BINARY_NAME)..."
|
||||
|
||||
@@ -11,12 +11,14 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
"embed"
|
||||
|
||||
"github.com/chzyer/readline"
|
||||
"github.com/sipeed/picoclaw/pkg/agent"
|
||||
@@ -36,6 +38,10 @@ import (
|
||||
"github.com/sipeed/picoclaw/pkg/voice"
|
||||
)
|
||||
|
||||
//go:embed workspace
|
||||
var embeddedFiles embed.FS
|
||||
|
||||
|
||||
var (
|
||||
version = "dev"
|
||||
gitCommit string
|
||||
@@ -208,6 +214,7 @@ func printHelp() {
|
||||
fmt.Println(" version Show version information")
|
||||
}
|
||||
|
||||
|
||||
func onboard() {
|
||||
configPath := getConfigPath()
|
||||
|
||||
@@ -229,10 +236,6 @@ func onboard() {
|
||||
}
|
||||
|
||||
workspace := cfg.WorkspacePath()
|
||||
os.MkdirAll(workspace, 0755)
|
||||
os.MkdirAll(filepath.Join(workspace, "memory"), 0755)
|
||||
os.MkdirAll(filepath.Join(workspace, "skills"), 0755)
|
||||
|
||||
createWorkspaceTemplates(workspace)
|
||||
|
||||
fmt.Printf("%s picoclaw is ready!\n", logo)
|
||||
@@ -242,170 +245,57 @@ func onboard() {
|
||||
fmt.Println(" 2. Chat: picoclaw agent -m \"Hello!\"")
|
||||
}
|
||||
|
||||
func copyEmbeddedToTarget(targetDir string) error {
|
||||
// Ensure target directory exists
|
||||
if err := os.MkdirAll(targetDir, 0755); err != nil {
|
||||
return fmt.Errorf("Failed to create target directory: %w", err)
|
||||
}
|
||||
|
||||
// Walk through all files in embed.FS
|
||||
err := fs.WalkDir(embeddedFiles, "workspace", func(path string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Skip directories
|
||||
if d.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Read embedded file
|
||||
data, err := embeddedFiles.ReadFile(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to read embedded file %s: %w", path, err)
|
||||
}
|
||||
|
||||
new_path, err := filepath.Rel("workspace", path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to get relative path for %s: %v\n", path, err)
|
||||
}
|
||||
|
||||
// Build target file path
|
||||
targetPath := filepath.Join(targetDir, new_path)
|
||||
|
||||
// Ensure target file's directory exists
|
||||
if err := os.MkdirAll(filepath.Dir(targetPath), 0755); err != nil {
|
||||
return fmt.Errorf("Failed to create directory %s: %w", filepath.Dir(targetPath), err)
|
||||
}
|
||||
|
||||
// Write file
|
||||
if err := os.WriteFile(targetPath, data, 0644); err != nil {
|
||||
return fmt.Errorf("Failed to write file %s: %w", targetPath, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func createWorkspaceTemplates(workspace string) {
|
||||
templates := map[string]string{
|
||||
"AGENTS.md": `# Agent Instructions
|
||||
|
||||
You are a helpful AI assistant. Be concise, accurate, and friendly.
|
||||
|
||||
## Guidelines
|
||||
|
||||
- Always explain what you're doing before taking actions
|
||||
- Ask for clarification when request is ambiguous
|
||||
- Use tools to help accomplish tasks
|
||||
- Remember important information in your memory files
|
||||
- Be proactive and helpful
|
||||
- Learn from user feedback
|
||||
`,
|
||||
"SOUL.md": `# Soul
|
||||
|
||||
I am picoclaw, a lightweight AI assistant powered by AI.
|
||||
|
||||
## Personality
|
||||
|
||||
- Helpful and friendly
|
||||
- Concise and to the point
|
||||
- Curious and eager to learn
|
||||
- Honest and transparent
|
||||
|
||||
## Values
|
||||
|
||||
- Accuracy over speed
|
||||
- User privacy and safety
|
||||
- Transparency in actions
|
||||
- Continuous improvement
|
||||
`,
|
||||
"USER.md": `# User
|
||||
|
||||
Information about user goes here.
|
||||
|
||||
## Preferences
|
||||
|
||||
- Communication style: (casual/formal)
|
||||
- Timezone: (your timezone)
|
||||
- Language: (your preferred language)
|
||||
|
||||
## Personal Information
|
||||
|
||||
- Name: (optional)
|
||||
- Location: (optional)
|
||||
- Occupation: (optional)
|
||||
|
||||
## Learning Goals
|
||||
|
||||
- What the user wants to learn from AI
|
||||
- Preferred interaction style
|
||||
- Areas of interest
|
||||
`,
|
||||
"IDENTITY.md": `# Identity
|
||||
|
||||
## Name
|
||||
PicoClaw 🦞
|
||||
|
||||
## Description
|
||||
Ultra-lightweight personal AI assistant written in Go, inspired by nanobot.
|
||||
|
||||
## Version
|
||||
0.1.0
|
||||
|
||||
## Purpose
|
||||
- Provide intelligent AI assistance with minimal resource usage
|
||||
- Support multiple LLM providers (OpenAI, Anthropic, Zhipu, etc.)
|
||||
- Enable easy customization through skills system
|
||||
- Run on minimal hardware ($10 boards, <10MB RAM)
|
||||
|
||||
## Capabilities
|
||||
|
||||
- Web search and content fetching
|
||||
- File system operations (read, write, edit)
|
||||
- Shell command execution
|
||||
- Multi-channel messaging (Telegram, WhatsApp, Feishu)
|
||||
- Skill-based extensibility
|
||||
- Memory and context management
|
||||
|
||||
## Philosophy
|
||||
|
||||
- Simplicity over complexity
|
||||
- Performance over features
|
||||
- User control and privacy
|
||||
- Transparent operation
|
||||
- Community-driven development
|
||||
|
||||
## Goals
|
||||
|
||||
- Provide a fast, lightweight AI assistant
|
||||
- Support offline-first operation where possible
|
||||
- Enable easy customization and extension
|
||||
- Maintain high quality responses
|
||||
- Run efficiently on constrained hardware
|
||||
|
||||
## License
|
||||
MIT License - Free and open source
|
||||
|
||||
## Repository
|
||||
https://github.com/sipeed/picoclaw
|
||||
|
||||
## Contact
|
||||
Issues: https://github.com/sipeed/picoclaw/issues
|
||||
Discussions: https://github.com/sipeed/picoclaw/discussions
|
||||
|
||||
---
|
||||
|
||||
"Every bit helps, every bit matters."
|
||||
- Picoclaw
|
||||
`,
|
||||
}
|
||||
|
||||
for filename, content := range templates {
|
||||
filePath := filepath.Join(workspace, filename)
|
||||
if _, err := os.Stat(filePath); os.IsNotExist(err) {
|
||||
os.WriteFile(filePath, []byte(content), 0644)
|
||||
fmt.Printf(" Created %s\n", filename)
|
||||
}
|
||||
}
|
||||
|
||||
memoryDir := filepath.Join(workspace, "memory")
|
||||
os.MkdirAll(memoryDir, 0755)
|
||||
memoryFile := filepath.Join(memoryDir, "MEMORY.md")
|
||||
if _, err := os.Stat(memoryFile); os.IsNotExist(err) {
|
||||
memoryContent := `# Long-term Memory
|
||||
|
||||
This file stores important information that should persist across sessions.
|
||||
|
||||
## User Information
|
||||
|
||||
(Important facts about user)
|
||||
|
||||
## Preferences
|
||||
|
||||
(User preferences learned over time)
|
||||
|
||||
## Important Notes
|
||||
|
||||
(Things to remember)
|
||||
|
||||
## Configuration
|
||||
|
||||
- Model preferences
|
||||
- Channel settings
|
||||
- Skills enabled
|
||||
`
|
||||
os.WriteFile(memoryFile, []byte(memoryContent), 0644)
|
||||
fmt.Println(" Created memory/MEMORY.md")
|
||||
|
||||
skillsDir := filepath.Join(workspace, "skills")
|
||||
if _, err := os.Stat(skillsDir); os.IsNotExist(err) {
|
||||
os.MkdirAll(skillsDir, 0755)
|
||||
fmt.Println(" Created skills/")
|
||||
}
|
||||
}
|
||||
|
||||
for filename, content := range templates {
|
||||
filePath := filepath.Join(workspace, filename)
|
||||
if _, err := os.Stat(filePath); os.IsNotExist(err) {
|
||||
os.WriteFile(filePath, []byte(content), 0644)
|
||||
fmt.Printf(" Created %s\n", filename)
|
||||
}
|
||||
err := copyEmbeddedToTarget(workspace)
|
||||
if err != nil {
|
||||
fmt.Printf("Error copying workspace templates: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
12
workspace/AGENT.md
Normal file
12
workspace/AGENT.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Agent Instructions
|
||||
|
||||
You are a helpful AI assistant. Be concise, accurate, and friendly.
|
||||
|
||||
## Guidelines
|
||||
|
||||
- Always explain what you're doing before taking actions
|
||||
- Ask for clarification when request is ambiguous
|
||||
- Use tools to help accomplish tasks
|
||||
- Remember important information in your memory files
|
||||
- Be proactive and helpful
|
||||
- Learn from user feedback
|
||||
56
workspace/IDENTITY.md
Normal file
56
workspace/IDENTITY.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# Identity
|
||||
|
||||
## Name
|
||||
PicoClaw 🦞
|
||||
|
||||
## Description
|
||||
Ultra-lightweight personal AI assistant written in Go, inspired by nanobot.
|
||||
|
||||
## Version
|
||||
0.1.0
|
||||
|
||||
## Purpose
|
||||
- Provide intelligent AI assistance with minimal resource usage
|
||||
- Support multiple LLM providers (OpenAI, Anthropic, Zhipu, etc.)
|
||||
- Enable easy customization through skills system
|
||||
- Run on minimal hardware ($10 boards, <10MB RAM)
|
||||
|
||||
## Capabilities
|
||||
|
||||
- Web search and content fetching
|
||||
- File system operations (read, write, edit)
|
||||
- Shell command execution
|
||||
- Multi-channel messaging (Telegram, WhatsApp, Feishu)
|
||||
- Skill-based extensibility
|
||||
- Memory and context management
|
||||
|
||||
## Philosophy
|
||||
|
||||
- Simplicity over complexity
|
||||
- Performance over features
|
||||
- User control and privacy
|
||||
- Transparent operation
|
||||
- Community-driven development
|
||||
|
||||
## Goals
|
||||
|
||||
- Provide a fast, lightweight AI assistant
|
||||
- Support offline-first operation where possible
|
||||
- Enable easy customization and extension
|
||||
- Maintain high quality responses
|
||||
- Run efficiently on constrained hardware
|
||||
|
||||
## License
|
||||
MIT License - Free and open source
|
||||
|
||||
## Repository
|
||||
https://github.com/sipeed/picoclaw
|
||||
|
||||
## Contact
|
||||
Issues: https://github.com/sipeed/picoclaw/issues
|
||||
Discussions: https://github.com/sipeed/picoclaw/discussions
|
||||
|
||||
---
|
||||
|
||||
"Every bit helps, every bit matters."
|
||||
- Picoclaw
|
||||
17
workspace/SOUL.md
Normal file
17
workspace/SOUL.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# Soul
|
||||
|
||||
I am picoclaw, a lightweight AI assistant powered by AI.
|
||||
|
||||
## Personality
|
||||
|
||||
- Helpful and friendly
|
||||
- Concise and to the point
|
||||
- Curious and eager to learn
|
||||
- Honest and transparent
|
||||
|
||||
## Values
|
||||
|
||||
- Accuracy over speed
|
||||
- User privacy and safety
|
||||
- Transparency in actions
|
||||
- Continuous improvement
|
||||
21
workspace/USER.md
Normal file
21
workspace/USER.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# User
|
||||
|
||||
Information about user goes here.
|
||||
|
||||
## Preferences
|
||||
|
||||
- Communication style: (casual/formal)
|
||||
- Timezone: (your timezone)
|
||||
- Language: (your preferred language)
|
||||
|
||||
## Personal Information
|
||||
|
||||
- Name: (optional)
|
||||
- Location: (optional)
|
||||
- Occupation: (optional)
|
||||
|
||||
## Learning Goals
|
||||
|
||||
- What the user wants to learn from AI
|
||||
- Preferred interaction style
|
||||
- Areas of interest
|
||||
21
workspace/memory/MEMORY.md
Normal file
21
workspace/memory/MEMORY.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Long-term Memory
|
||||
|
||||
This file stores important information that should persist across sessions.
|
||||
|
||||
## User Information
|
||||
|
||||
(Important facts about user)
|
||||
|
||||
## Preferences
|
||||
|
||||
(User preferences learned over time)
|
||||
|
||||
## Important Notes
|
||||
|
||||
(Things to remember)
|
||||
|
||||
## Configuration
|
||||
|
||||
- Model preferences
|
||||
- Channel settings
|
||||
- Skills enabled
|
||||
Reference in New Issue
Block a user