* Add tools enable or diable config
This commit is contained in:
parent
b82bb9acc0
commit
ad8bb3d9b7
5 changed files with 351 additions and 90 deletions
|
|
@ -223,19 +223,24 @@ func setupCronTool(
|
|||
// Create cron service
|
||||
cronService := cron.NewCronService(cronStorePath, nil)
|
||||
|
||||
// Create and register CronTool
|
||||
// Create and register CronTool if enabled
|
||||
var cronTool *tools.CronTool
|
||||
if cfg.Tools.IsToolEnabled("cron") {
|
||||
cronTool, err := tools.NewCronTool(cronService, agentLoop, msgBus, workspace, restrict, execTimeout, cfg)
|
||||
if err != nil {
|
||||
log.Fatalf("Critical error during CronTool initialization: %v", err)
|
||||
}
|
||||
|
||||
agentLoop.RegisterTool(cronTool)
|
||||
}
|
||||
|
||||
// Set the onJob handler
|
||||
// Set onJob handler
|
||||
if cronTool != nil {
|
||||
cronService.SetOnJob(func(job *cron.CronJob) (string, error) {
|
||||
result := cronTool.ExecuteJob(context.Background(), job)
|
||||
return result, nil
|
||||
})
|
||||
}
|
||||
|
||||
return cronService
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,17 +59,30 @@ func NewAgentInstance(
|
|||
allowWritePaths := compilePatterns(cfg.Tools.AllowWritePaths)
|
||||
|
||||
toolsRegistry := tools.NewToolRegistry()
|
||||
|
||||
if cfg.Tools.IsToolEnabled("read_file") {
|
||||
toolsRegistry.Register(tools.NewReadFileTool(workspace, readRestrict, allowReadPaths))
|
||||
}
|
||||
if cfg.Tools.IsToolEnabled("write_file") {
|
||||
toolsRegistry.Register(tools.NewWriteFileTool(workspace, restrict, allowWritePaths))
|
||||
}
|
||||
if cfg.Tools.IsToolEnabled("list_dir") {
|
||||
toolsRegistry.Register(tools.NewListDirTool(workspace, readRestrict, allowReadPaths))
|
||||
}
|
||||
if cfg.Tools.IsToolEnabled("exec") {
|
||||
execTool, err := tools.NewExecToolWithConfig(workspace, restrict, cfg)
|
||||
if err != nil {
|
||||
log.Fatalf("Critical error: unable to initialize exec tool: %v", err)
|
||||
}
|
||||
toolsRegistry.Register(execTool)
|
||||
}
|
||||
|
||||
if cfg.Tools.IsToolEnabled("edit_file") {
|
||||
toolsRegistry.Register(tools.NewEditFileTool(workspace, restrict, allowWritePaths))
|
||||
}
|
||||
if cfg.Tools.IsToolEnabled("append_file") {
|
||||
toolsRegistry.Register(tools.NewAppendFileTool(workspace, restrict, allowWritePaths))
|
||||
}
|
||||
|
||||
sessionsDir := filepath.Join(workspace, "sessions")
|
||||
sessionsManager := session.NewSessionManager(sessionsDir)
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ func registerSharedTools(
|
|||
}
|
||||
|
||||
// Web tools
|
||||
if cfg.Tools.IsToolEnabled("web_search") {
|
||||
searchTool, err := tools.NewWebSearchTool(tools.WebSearchToolOptions{
|
||||
BraveAPIKey: cfg.Tools.Web.Brave.APIKey,
|
||||
BraveMaxResults: cfg.Tools.Web.Brave.MaxResults,
|
||||
|
|
@ -130,18 +131,26 @@ func registerSharedTools(
|
|||
} else if searchTool != nil {
|
||||
agent.Tools.Register(searchTool)
|
||||
}
|
||||
}
|
||||
if cfg.Tools.IsToolEnabled("web_fetch") {
|
||||
fetchTool, err := tools.NewWebFetchToolWithProxy(50000, cfg.Tools.Web.Proxy, cfg.Tools.Web.FetchLimitBytes)
|
||||
if err != nil {
|
||||
logger.ErrorCF("agent", "Failed to create web fetch tool", map[string]any{"error": err.Error()})
|
||||
} else {
|
||||
agent.Tools.Register(fetchTool)
|
||||
}
|
||||
}
|
||||
|
||||
// Hardware tools (I2C, SPI) - Linux only, returns error on other platforms
|
||||
if cfg.Tools.IsToolEnabled("i2c") {
|
||||
agent.Tools.Register(tools.NewI2CTool())
|
||||
}
|
||||
if cfg.Tools.IsToolEnabled("spi") {
|
||||
agent.Tools.Register(tools.NewSPITool())
|
||||
}
|
||||
|
||||
// Message tool
|
||||
if cfg.Tools.IsToolEnabled("message") {
|
||||
messageTool := tools.NewMessageTool()
|
||||
messageTool.SetSendCallback(func(channel, chatID, content string) error {
|
||||
pubCtx, pubCancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
|
|
@ -153,6 +162,7 @@ func registerSharedTools(
|
|||
})
|
||||
})
|
||||
agent.Tools.Register(messageTool)
|
||||
}
|
||||
|
||||
// Skill discovery and installation tools
|
||||
registryMgr := skills.NewRegistryManagerFromConfig(skills.RegistryConfig{
|
||||
|
|
@ -163,10 +173,15 @@ func registerSharedTools(
|
|||
cfg.Tools.Skills.SearchCache.MaxSize,
|
||||
time.Duration(cfg.Tools.Skills.SearchCache.TTLSeconds)*time.Second,
|
||||
)
|
||||
if cfg.Tools.IsToolEnabled("find_skills") {
|
||||
agent.Tools.Register(tools.NewFindSkillsTool(registryMgr, searchCache))
|
||||
}
|
||||
if cfg.Tools.IsToolEnabled("install_skill") {
|
||||
agent.Tools.Register(tools.NewInstallSkillTool(registryMgr, agent.Workspace))
|
||||
}
|
||||
|
||||
// Spawn tool with allowlist checker
|
||||
if cfg.Tools.IsToolEnabled("spawn") {
|
||||
subagentManager := tools.NewSubagentManager(provider, agent.Model, agent.Workspace, msgBus)
|
||||
subagentManager.SetLLMOptions(agent.MaxTokens, agent.Temperature)
|
||||
spawnTool := tools.NewSpawnTool(subagentManager)
|
||||
|
|
@ -176,6 +191,7 @@ func registerSharedTools(
|
|||
})
|
||||
agent.Tools.Register(spawnTool)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (al *AgentLoop) Run(ctx context.Context) error {
|
||||
|
|
@ -224,6 +240,7 @@ func (al *AgentLoop) Run(ctx context.Context) error {
|
|||
if !ok {
|
||||
continue
|
||||
}
|
||||
if al.cfg.Tools.IsToolEnabled("mcp") {
|
||||
mcpTool := tools.NewMCPTool(mcpManager, serverName, tool)
|
||||
agent.Tools.Register(mcpTool)
|
||||
totalRegistrations++
|
||||
|
|
@ -237,6 +254,7 @@ func (al *AgentLoop) Run(ctx context.Context) error {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
logger.InfoCF("agent", "MCP tools registered successfully",
|
||||
map[string]any{
|
||||
"server_count": len(servers),
|
||||
|
|
|
|||
|
|
@ -523,6 +523,10 @@ type GatewayConfig struct {
|
|||
Port int `json:"port" env:"PICOCLAW_GATEWAY_PORT"`
|
||||
}
|
||||
|
||||
type ToolConfig struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
}
|
||||
|
||||
type BraveConfig struct {
|
||||
Enabled bool `json:"enabled" env:"PICOCLAW_TOOLS_WEB_BRAVE_ENABLED"`
|
||||
APIKey string `json:"api_key" env:"PICOCLAW_TOOLS_WEB_BRAVE_API_KEY"`
|
||||
|
|
@ -558,6 +562,7 @@ type GLMSearchConfig struct {
|
|||
}
|
||||
|
||||
type WebToolsConfig struct {
|
||||
ToolConfig
|
||||
Brave BraveConfig `json:"brave"`
|
||||
Tavily TavilyConfig `json:"tavily"`
|
||||
DuckDuckGo DuckDuckGoConfig `json:"duckduckgo"`
|
||||
|
|
@ -570,17 +575,26 @@ type WebToolsConfig struct {
|
|||
}
|
||||
|
||||
type CronToolsConfig struct {
|
||||
ToolConfig
|
||||
ExecTimeoutMinutes int `json:"exec_timeout_minutes" env:"PICOCLAW_TOOLS_CRON_EXEC_TIMEOUT_MINUTES"` // 0 means no timeout
|
||||
}
|
||||
|
||||
type ExecConfig struct {
|
||||
ToolConfig
|
||||
EnableDenyPatterns bool `json:"enable_deny_patterns" env:"PICOCLAW_TOOLS_EXEC_ENABLE_DENY_PATTERNS"`
|
||||
CustomDenyPatterns []string `json:"custom_deny_patterns" env:"PICOCLAW_TOOLS_EXEC_CUSTOM_DENY_PATTERNS"`
|
||||
CustomAllowPatterns []string `json:"custom_allow_patterns" env:"PICOCLAW_TOOLS_EXEC_CUSTOM_ALLOW_PATTERNS"`
|
||||
}
|
||||
|
||||
type SkillsToolsConfig struct {
|
||||
ToolConfig
|
||||
Registries SkillsRegistriesConfig `json:"registries"`
|
||||
MaxConcurrentSearches int `json:"max_concurrent_searches" env:"PICOCLAW_SKILLS_MAX_CONCURRENT_SEARCHES"`
|
||||
SearchCache SearchCacheConfig `json:"search_cache"`
|
||||
}
|
||||
|
||||
type MediaCleanupConfig struct {
|
||||
Enabled bool `json:"enabled" env:"PICOCLAW_MEDIA_CLEANUP_ENABLED"`
|
||||
ToolConfig
|
||||
MaxAge int `json:"max_age_minutes" env:"PICOCLAW_MEDIA_CLEANUP_MAX_AGE"`
|
||||
Interval int `json:"interval_minutes" env:"PICOCLAW_MEDIA_CLEANUP_INTERVAL"`
|
||||
}
|
||||
|
|
@ -594,12 +608,116 @@ type ToolsConfig struct {
|
|||
Skills SkillsToolsConfig `json:"skills"`
|
||||
MediaCleanup MediaCleanupConfig `json:"media_cleanup"`
|
||||
MCP MCPConfig `json:"mcp"`
|
||||
AppendFile ToolConfig `json:"append_file"`
|
||||
CronTool ToolConfig `json:"cron_tool"`
|
||||
EditFile ToolConfig `json:"edit_file"`
|
||||
ExecTool ToolConfig `json:"exec_tool"`
|
||||
FindSkills ToolConfig `json:"find_skills"`
|
||||
I2C ToolConfig `json:"i2c"`
|
||||
InstallSkill ToolConfig `json:"install_skill"`
|
||||
ListDir ToolConfig `json:"list_dir"`
|
||||
Message ToolConfig `json:"message"`
|
||||
ReadFile ToolConfig `json:"read_file"`
|
||||
Spawn ToolConfig `json:"spawn"`
|
||||
SPI ToolConfig `json:"spi"`
|
||||
Subagent ToolConfig `json:"subagent"`
|
||||
WebFetch ToolConfig `json:"web_fetch"`
|
||||
WebSearch ToolConfig `json:"web_search"`
|
||||
WriteFile ToolConfig `json:"write_file"`
|
||||
}
|
||||
|
||||
type SkillsToolsConfig struct {
|
||||
Registries SkillsRegistriesConfig `json:"registries"`
|
||||
MaxConcurrentSearches int `json:"max_concurrent_searches" env:"PICOCLAW_SKILLS_MAX_CONCURRENT_SEARCHES"`
|
||||
SearchCache SearchCacheConfig `json:"search_cache"`
|
||||
type ToolsConfigRaw struct {
|
||||
AllowReadPaths []string `json:"allow_read_paths"`
|
||||
AllowWritePaths []string `json:"allow_write_paths"`
|
||||
Web WebToolsConfig `json:"web"`
|
||||
Cron CronToolsConfig `json:"cron"`
|
||||
Exec ExecConfig `json:"exec"`
|
||||
Skills SkillsToolsConfig `json:"skills"`
|
||||
MediaCleanup MediaCleanupConfig `json:"media_cleanup"`
|
||||
MCP MCPConfig `json:"mcp"`
|
||||
AppendFile *ToolConfig `json:"append_file,omitempty"`
|
||||
CronTool *ToolConfig `json:"cron_tool,omitempty"`
|
||||
EditFile *ToolConfig `json:"edit_file,omitempty"`
|
||||
ExecTool *ToolConfig `json:"exec_tool,omitempty"`
|
||||
FindSkills *ToolConfig `json:"find_skills,omitempty"`
|
||||
I2C *ToolConfig `json:"i2c,omitempty"`
|
||||
InstallSkill *ToolConfig `json:"install_skill,omitempty"`
|
||||
ListDir *ToolConfig `json:"list_dir,omitempty"`
|
||||
Message *ToolConfig `json:"message,omitempty"`
|
||||
ReadFile *ToolConfig `json:"read_file,omitempty"`
|
||||
Spawn *ToolConfig `json:"spawn,omitempty"`
|
||||
SPI *ToolConfig `json:"spi,omitempty"`
|
||||
Subagent *ToolConfig `json:"subagent,omitempty"`
|
||||
WebFetch *ToolConfig `json:"web_fetch,omitempty"`
|
||||
WebSearch *ToolConfig `json:"web_search,omitempty"`
|
||||
WriteFile *ToolConfig `json:"write_file,omitempty"`
|
||||
}
|
||||
|
||||
func (t *ToolsConfig) UnmarshalJSON(data []byte) error {
|
||||
var raw ToolsConfigRaw
|
||||
if err := json.Unmarshal(data, &raw); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
t.AllowReadPaths = raw.AllowReadPaths
|
||||
t.AllowWritePaths = raw.AllowWritePaths
|
||||
t.Web = raw.Web
|
||||
t.Cron = raw.Cron
|
||||
t.Exec = raw.Exec
|
||||
t.Skills = raw.Skills
|
||||
t.MediaCleanup = raw.MediaCleanup
|
||||
t.MCP = raw.MCP
|
||||
|
||||
if raw.AppendFile != nil {
|
||||
t.AppendFile = *raw.AppendFile
|
||||
}
|
||||
if raw.CronTool != nil {
|
||||
t.CronTool = *raw.CronTool
|
||||
}
|
||||
if raw.EditFile != nil {
|
||||
t.EditFile = *raw.EditFile
|
||||
}
|
||||
if raw.ExecTool != nil {
|
||||
t.ExecTool = *raw.ExecTool
|
||||
}
|
||||
if raw.FindSkills != nil {
|
||||
t.FindSkills = *raw.FindSkills
|
||||
}
|
||||
if raw.I2C != nil {
|
||||
t.I2C = *raw.I2C
|
||||
}
|
||||
if raw.InstallSkill != nil {
|
||||
t.InstallSkill = *raw.InstallSkill
|
||||
}
|
||||
if raw.ListDir != nil {
|
||||
t.ListDir = *raw.ListDir
|
||||
}
|
||||
if raw.Message != nil {
|
||||
t.Message = *raw.Message
|
||||
}
|
||||
if raw.ReadFile != nil {
|
||||
t.ReadFile = *raw.ReadFile
|
||||
}
|
||||
if raw.Spawn != nil {
|
||||
t.Spawn = *raw.Spawn
|
||||
}
|
||||
if raw.SPI != nil {
|
||||
t.SPI = *raw.SPI
|
||||
}
|
||||
if raw.Subagent != nil {
|
||||
t.Subagent = *raw.Subagent
|
||||
}
|
||||
if raw.WebFetch != nil {
|
||||
t.WebFetch = *raw.WebFetch
|
||||
}
|
||||
if raw.WebSearch != nil {
|
||||
t.WebSearch = *raw.WebSearch
|
||||
}
|
||||
if raw.WriteFile != nil {
|
||||
t.WriteFile = *raw.WriteFile
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type SearchCacheConfig struct {
|
||||
|
|
@ -832,3 +950,48 @@ func (c *Config) ValidateModelList() error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *ToolsConfig) IsToolEnabled(name string) bool {
|
||||
switch name {
|
||||
case "web":
|
||||
return t.Web.Enabled
|
||||
case "cron":
|
||||
return t.Cron.Enabled
|
||||
case "exec":
|
||||
return t.Exec.Enabled
|
||||
case "skills":
|
||||
return t.Skills.Enabled
|
||||
case "media_cleanup":
|
||||
return t.MediaCleanup.Enabled
|
||||
case "append_file":
|
||||
return t.AppendFile.Enabled
|
||||
case "edit_file":
|
||||
return t.EditFile.Enabled
|
||||
case "find_skills":
|
||||
return t.FindSkills.Enabled
|
||||
case "i2c":
|
||||
return t.I2C.Enabled
|
||||
case "install_skill":
|
||||
return t.InstallSkill.Enabled
|
||||
case "list_dir":
|
||||
return t.ListDir.Enabled
|
||||
case "message":
|
||||
return t.Message.Enabled
|
||||
case "read_file":
|
||||
return t.ReadFile.Enabled
|
||||
case "spawn":
|
||||
return t.Spawn.Enabled
|
||||
case "spi":
|
||||
return t.SPI.Enabled
|
||||
case "subagent":
|
||||
return t.Subagent.Enabled
|
||||
case "web_fetch":
|
||||
return t.WebFetch.Enabled
|
||||
case "web_search":
|
||||
return t.WebSearch.Enabled
|
||||
case "write_file":
|
||||
return t.WriteFile.Enabled
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -322,11 +322,16 @@ func DefaultConfig() *Config {
|
|||
},
|
||||
Tools: ToolsConfig{
|
||||
MediaCleanup: MediaCleanupConfig{
|
||||
ToolConfig: ToolConfig{
|
||||
Enabled: true,
|
||||
},
|
||||
MaxAge: 30,
|
||||
Interval: 5,
|
||||
},
|
||||
Web: WebToolsConfig{
|
||||
ToolConfig: ToolConfig{
|
||||
Enabled: true,
|
||||
},
|
||||
Proxy: "",
|
||||
FetchLimitBytes: 10 * 1024 * 1024, // 10MB by default
|
||||
Brave: BraveConfig{
|
||||
|
|
@ -352,12 +357,21 @@ func DefaultConfig() *Config {
|
|||
},
|
||||
},
|
||||
Cron: CronToolsConfig{
|
||||
ToolConfig: ToolConfig{
|
||||
Enabled: true,
|
||||
},
|
||||
ExecTimeoutMinutes: 5,
|
||||
},
|
||||
Exec: ExecConfig{
|
||||
ToolConfig: ToolConfig{
|
||||
Enabled: true,
|
||||
},
|
||||
EnableDenyPatterns: true,
|
||||
},
|
||||
Skills: SkillsToolsConfig{
|
||||
ToolConfig: ToolConfig{
|
||||
Enabled: true,
|
||||
},
|
||||
Registries: SkillsRegistriesConfig{
|
||||
ClawHub: ClawHubRegistryConfig{
|
||||
Enabled: true,
|
||||
|
|
@ -374,6 +388,54 @@ func DefaultConfig() *Config {
|
|||
Enabled: false,
|
||||
Servers: map[string]MCPServerConfig{},
|
||||
},
|
||||
AppendFile: ToolConfig{
|
||||
Enabled: true,
|
||||
},
|
||||
CronTool: ToolConfig{
|
||||
Enabled: true,
|
||||
},
|
||||
EditFile: ToolConfig{
|
||||
Enabled: true,
|
||||
},
|
||||
ExecTool: ToolConfig{
|
||||
Enabled: true,
|
||||
},
|
||||
FindSkills: ToolConfig{
|
||||
Enabled: true,
|
||||
},
|
||||
I2C: ToolConfig{
|
||||
Enabled: false, // Hardware tool - Linux only
|
||||
},
|
||||
InstallSkill: ToolConfig{
|
||||
Enabled: true,
|
||||
},
|
||||
ListDir: ToolConfig{
|
||||
Enabled: false,
|
||||
},
|
||||
Message: ToolConfig{
|
||||
Enabled: true,
|
||||
},
|
||||
ReadFile: ToolConfig{
|
||||
Enabled: true,
|
||||
},
|
||||
Spawn: ToolConfig{
|
||||
Enabled: true,
|
||||
},
|
||||
SPI: ToolConfig{
|
||||
Enabled: false, // Hardware tool - Linux only
|
||||
},
|
||||
Subagent: ToolConfig{
|
||||
Enabled: true,
|
||||
},
|
||||
WebFetch: ToolConfig{
|
||||
Enabled: true,
|
||||
},
|
||||
WebSearch: ToolConfig{
|
||||
Enabled: true,
|
||||
},
|
||||
WriteFile: ToolConfig{
|
||||
Enabled: true,
|
||||
},
|
||||
},
|
||||
Heartbeat: HeartbeatConfig{
|
||||
Enabled: true,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue