Merge pull request #1 from 24f2006619/24f2006619-patch-1

fix: locate builtin skills directory
This commit is contained in:
Harshdeep Sharma 2026-02-11 18:29:59 +05:30 committed by GitHub
commit e6ecd15867
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -102,11 +102,7 @@ func main() {
workspace := cfg.WorkspacePath() workspace := cfg.WorkspacePath()
installer := skills.NewSkillInstaller(workspace) installer := skills.NewSkillInstaller(workspace)
// 获取全局配置目录和内置 skills 目录 skillsLoader := skills.NewSkillsLoader(workspace, "")
globalDir := filepath.Dir(getConfigPath())
globalSkillsDir := filepath.Join(globalDir, "skills")
builtinSkillsDir := filepath.Join(globalDir, "picoclaw", "skills")
skillsLoader := skills.NewSkillsLoader(workspace, globalSkillsDir, builtinSkillsDir)
switch subcommand { switch subcommand {
case "list": case "list":
@ -246,6 +242,70 @@ Information about user goes here.
- What the user wants to learn from AI - What the user wants to learn from AI
- Preferred interaction style - Preferred interaction style
- Areas of interest - Areas of interest
`,
"TOOLS.md": `# Available Tools
This document describes the tools available to picoclaw.
## File Operations
### Read Files
- Read file contents
- Supports text, markdown, code files
### Write Files
- Create new files
- Overwrite existing files
- Supports various formats
### List Directories
- List directory contents
- Recursive listing support
### Edit Files
- Make specific edits to files
- Line-by-line editing
- String replacement
## Web Tools
### Web Search
- Search the internet using search API
- Returns titles, URLs, snippets
- Optional: Requires API key for best results
### Web Fetch
- Fetch specific URLs
- Extract readable content
- Supports HTML, JSON, plain text
- Automatic content extraction
## Command Execution
### Shell Commands
- Execute any shell command
- Run in workspace directory
- Full shell access with timeout protection
## Messaging
### Send Messages
- Send messages to chat channels
- Supports Telegram, WhatsApp, Feishu
- Used for notifications and responses
## AI Capabilities
### Context Building
- Load system instructions from files
- Load skills dynamically
- Build conversation history
- Include timezone and other context
### Memory Management
- Long-term memory via MEMORY.md
- Daily notes via dated files
- Persistent across sessions
`, `,
"IDENTITY.md": `# Identity "IDENTITY.md": `# Identity
@ -366,9 +426,6 @@ func agentCmd() {
args := os.Args[2:] args := os.Args[2:]
for i := 0; i < len(args); i++ { for i := 0; i < len(args); i++ {
switch args[i] { switch args[i] {
case "--debug", "-d":
logger.SetLevel(logger.DEBUG)
fmt.Println("🔍 Debug mode enabled")
case "-m", "--message": case "-m", "--message":
if i+1 < len(args) { if i+1 < len(args) {
message = args[i+1] message = args[i+1]
@ -397,15 +454,6 @@ func agentCmd() {
msgBus := bus.NewMessageBus() msgBus := bus.NewMessageBus()
agentLoop := agent.NewAgentLoop(cfg, msgBus, provider) agentLoop := agent.NewAgentLoop(cfg, msgBus, provider)
// Print agent startup info (only for interactive mode)
startupInfo := agentLoop.GetStartupInfo()
logger.InfoCF("agent", "Agent initialized",
map[string]interface{}{
"tools_count": startupInfo["tools"].(map[string]interface{})["count"],
"skills_total": startupInfo["skills"].(map[string]interface{})["total"],
"skills_available": startupInfo["skills"].(map[string]interface{})["available"],
})
if message != "" { if message != "" {
ctx := context.Background() ctx := context.Background()
response, err := agentLoop.ProcessDirect(ctx, message, sessionKey) response, err := agentLoop.ProcessDirect(ctx, message, sessionKey)
@ -507,16 +555,6 @@ func simpleInteractiveMode(agentLoop *agent.AgentLoop, sessionKey string) {
} }
func gatewayCmd() { func gatewayCmd() {
// Check for --debug flag
args := os.Args[2:]
for _, arg := range args {
if arg == "--debug" || arg == "-d" {
logger.SetLevel(logger.DEBUG)
fmt.Println("🔍 Debug mode enabled")
break
}
}
cfg, err := loadConfig() cfg, err := loadConfig()
if err != nil { if err != nil {
fmt.Printf("Error loading config: %v\n", err) fmt.Printf("Error loading config: %v\n", err)
@ -532,24 +570,6 @@ func gatewayCmd() {
msgBus := bus.NewMessageBus() msgBus := bus.NewMessageBus()
agentLoop := agent.NewAgentLoop(cfg, msgBus, provider) agentLoop := agent.NewAgentLoop(cfg, msgBus, provider)
// Print agent startup info
fmt.Println("\n📦 Agent Status:")
startupInfo := agentLoop.GetStartupInfo()
toolsInfo := startupInfo["tools"].(map[string]interface{})
skillsInfo := startupInfo["skills"].(map[string]interface{})
fmt.Printf(" • Tools: %d loaded\n", toolsInfo["count"])
fmt.Printf(" • Skills: %d/%d available\n",
skillsInfo["available"],
skillsInfo["total"])
// Log to file as well
logger.InfoCF("agent", "Agent initialized",
map[string]interface{}{
"tools_count": toolsInfo["count"],
"skills_total": skillsInfo["total"],
"skills_available": skillsInfo["available"],
})
cronStorePath := filepath.Join(filepath.Dir(getConfigPath()), "cron", "jobs.json") cronStorePath := filepath.Join(filepath.Dir(getConfigPath()), "cron", "jobs.json")
cronService := cron.NewCronService(cronStorePath, nil) cronService := cron.NewCronService(cronStorePath, nil)
@ -917,11 +937,7 @@ func skillsCmd() {
workspace := cfg.WorkspacePath() workspace := cfg.WorkspacePath()
installer := skills.NewSkillInstaller(workspace) installer := skills.NewSkillInstaller(workspace)
// 获取全局配置目录和内置 skills 目录 skillsLoader := skills.NewSkillsLoader(workspace, "")
globalDir := filepath.Dir(getConfigPath())
globalSkillsDir := filepath.Join(globalDir, "skills")
builtinSkillsDir := filepath.Join(globalDir, "picoclaw", "skills")
skillsLoader := skills.NewSkillsLoader(workspace, globalSkillsDir, builtinSkillsDir)
switch subcommand { switch subcommand {
case "list": case "list":
@ -967,7 +983,7 @@ func skillsHelp() {
} }
func skillsListCmd(loader *skills.SkillsLoader) { func skillsListCmd(loader *skills.SkillsLoader) {
allSkills := loader.ListSkills() allSkills := loader.ListSkills(false)
if len(allSkills) == 0 { if len(allSkills) == 0 {
fmt.Println("No skills installed.") fmt.Println("No skills installed.")
@ -977,10 +993,17 @@ func skillsListCmd(loader *skills.SkillsLoader) {
fmt.Println("\nInstalled Skills:") fmt.Println("\nInstalled Skills:")
fmt.Println("------------------") fmt.Println("------------------")
for _, skill := range allSkills { for _, skill := range allSkills {
fmt.Printf(" ✓ %s (%s)\n", skill.Name, skill.Source) status := "✓"
if !skill.Available {
status = "✗"
}
fmt.Printf(" %s %s (%s)\n", status, skill.Name, skill.Source)
if skill.Description != "" { if skill.Description != "" {
fmt.Printf(" %s\n", skill.Description) fmt.Printf(" %s\n", skill.Description)
} }
if !skill.Available {
fmt.Printf(" Missing: %s\n", skill.Missing)
}
} }
} }
@ -1017,7 +1040,7 @@ func skillsRemoveCmd(installer *skills.SkillInstaller, skillName string) {
} }
func skillsInstallBuiltinCmd(workspace string) { func skillsInstallBuiltinCmd(workspace string) {
builtinSkillsDir := "./picoclaw/skills" builtinSkillsDir := getBuiltinSkillsDir()
workspaceSkillsDir := filepath.Join(workspace, "skills") workspaceSkillsDir := filepath.Join(workspace, "skills")
fmt.Printf("Copying builtin skills to workspace...\n") fmt.Printf("Copying builtin skills to workspace...\n")
@ -1053,12 +1076,7 @@ func skillsInstallBuiltinCmd(workspace string) {
} }
func skillsListBuiltinCmd() { func skillsListBuiltinCmd() {
cfg, err := loadConfig() builtinSkillsDir := getBuiltinSkillsDir()
if err != nil {
fmt.Printf("Error loading config: %v\n", err)
return
}
builtinSkillsDir := filepath.Join(filepath.Dir(cfg.WorkspacePath()), "picoclaw", "skills")
fmt.Println("\nAvailable Builtin Skills:") fmt.Println("\nAvailable Builtin Skills:")
fmt.Println("-----------------------") fmt.Println("-----------------------")
@ -1104,6 +1122,22 @@ func skillsListBuiltinCmd() {
} }
} }
func getBuiltinSkillsDir() string {
if _, err := os.Stat("skills"); err == nil {
return "skills"
}
exePath, err := os.Executable()
if err == nil {
exeSkills := filepath.Join(filepath.Dir(exePath), "skills")
if _, err := os.Stat(exeSkills); err == nil {
return exeSkills
}
}
return "skills"
}
func skillsSearchCmd(installer *skills.SkillInstaller) { func skillsSearchCmd(installer *skills.SkillInstaller) {
fmt.Println("Searching for available skills...") fmt.Println("Searching for available skills...")